mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-23 12:42:22 -04:00
Support custom dirt/grass blocks.
This commit is contained in:
parent
935a90b0cd
commit
3457a6e5fa
@ -20,13 +20,13 @@ using MCGalaxy.Blocks.Physics;
|
|||||||
|
|
||||||
namespace MCGalaxy.Blocks {
|
namespace MCGalaxy.Blocks {
|
||||||
|
|
||||||
/// <summary> Handles the player placing a block at the given coordinates. </summary>
|
/// <summary> Handles the player deleting a block at the given coordinates. </summary>
|
||||||
/// <remarks> Use p.ChangeBlock to do a normal player block change (adds to BlockDB, updates dirt/grass beneath) </remarks>
|
/// <remarks> Use p.ChangeBlock to do a normal player block change (adds to BlockDB, updates dirt/grass beneath) </remarks>
|
||||||
public delegate void HandleDelete(Player p, ExtBlock oldBlock, ushort x, ushort y, ushort z);
|
public delegate void HandleDelete(Player p, ExtBlock oldBlock, ushort x, ushort y, ushort z);
|
||||||
|
|
||||||
/// <summary> Handles the player deleting a block at the given coordinates. </summary>
|
/// <summary> Handles the player placing a block at the given coordinates. </summary>
|
||||||
/// <remarks> Use p.ChangeBlock to do a normal player block change (adds to BlockDB, updates dirt/grass beneath) </remarks>
|
/// <remarks> Use p.ChangeBlock to do a normal player block change (adds to BlockDB, updates dirt/grass beneath) </remarks>
|
||||||
public delegate void HandlePlace(Player p, ExtBlock oldBlock, ushort x, ushort y, ushort z);
|
public delegate void HandlePlace(Player p, ExtBlock newBlock, ushort x, ushort y, ushort z);
|
||||||
|
|
||||||
/// <summary> Returns whether this block handles the player walking through this block at the given coordinates. </summary>
|
/// <summary> Returns whether this block handles the player walking through this block at the given coordinates. </summary>
|
||||||
/// <remarks> If this returns true, the usual 'death check' behaviour is skipped. </remarks>
|
/// <remarks> If this returns true, the usual 'death check' behaviour is skipped. </remarks>
|
||||||
@ -40,13 +40,13 @@ namespace MCGalaxy.Blocks {
|
|||||||
/// <summary> Retrieves the default place block handler for the given block. </summary>
|
/// <summary> Retrieves the default place block handler for the given block. </summary>
|
||||||
internal static HandlePlace GetPlaceHandler(ExtBlock block, BlockProps[] props) {
|
internal static HandlePlace GetPlaceHandler(ExtBlock block, BlockProps[] props) {
|
||||||
switch (block.BlockID) {
|
switch (block.BlockID) {
|
||||||
case Block.Dirt: return PlaceBehaviour.Dirt;
|
|
||||||
case Block.Grass: return PlaceBehaviour.Grass;
|
|
||||||
case Block.C4: return PlaceBehaviour.C4;
|
case Block.C4: return PlaceBehaviour.C4;
|
||||||
case Block.C4Detonator: return PlaceBehaviour.C4Det;
|
case Block.C4Detonator: return PlaceBehaviour.C4Det;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props[block.Index].StackId != Block.Air) return PlaceBehaviour.Stack(block);
|
if (props[block.Index].GrassIndex != Block.Invalid) return PlaceBehaviour.DirtGrow;
|
||||||
|
if (props[block.Index].DirtIndex != Block.Invalid) return PlaceBehaviour.GrassDie;
|
||||||
|
if (props[block.Index].StackId != Block.Air) return PlaceBehaviour.Stack;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,8 +120,6 @@ namespace MCGalaxy.Blocks {
|
|||||||
case Block.Deadly_FastLava: return SimpleLiquidPhysics.DoFastLava;
|
case Block.Deadly_FastLava: return SimpleLiquidPhysics.DoFastLava;
|
||||||
|
|
||||||
case Block.Air: return AirPhysics.DoAir;
|
case Block.Air: return AirPhysics.DoAir;
|
||||||
case Block.Dirt: return OtherPhysics.DoDirt;
|
|
||||||
case Block.Grass: return OtherPhysics.DoGrass;
|
|
||||||
case Block.Leaves: return LeafPhysics.DoLeaf;
|
case Block.Leaves: return LeafPhysics.DoLeaf;
|
||||||
case Block.Sapling: return OtherPhysics.DoShrub;
|
case Block.Sapling: return OtherPhysics.DoShrub;
|
||||||
case Block.Fire: return FirePhysics.Do;
|
case Block.Fire: return FirePhysics.Do;
|
||||||
@ -158,6 +156,8 @@ namespace MCGalaxy.Blocks {
|
|||||||
HandlePhysics animalAI = AnimalAIHandler(props[i].AnimalAI);
|
HandlePhysics animalAI = AnimalAIHandler(props[i].AnimalAI);
|
||||||
if (animalAI != null) return animalAI;
|
if (animalAI != null) return animalAI;
|
||||||
if (props[i].oDoorIndex != Block.Invalid) return DoorPhysics.oDoor;
|
if (props[i].oDoorIndex != Block.Invalid) return DoorPhysics.oDoor;
|
||||||
|
if (props[i].GrassIndex != Block.Invalid) return OtherPhysics.DoDirtGrow;
|
||||||
|
if (props[i].DirtIndex != Block.Invalid) return OtherPhysics.DoGrassDie;
|
||||||
|
|
||||||
i = block.BlockID; // TODO: should this be checking WaterKills/LavaKills
|
i = block.BlockID; // TODO: should this be checking WaterKills/LavaKills
|
||||||
// Adv physics updating anything placed next to water or lava
|
// Adv physics updating anything placed next to water or lava
|
||||||
|
@ -22,32 +22,36 @@ namespace MCGalaxy.Blocks {
|
|||||||
|
|
||||||
internal static class PlaceBehaviour {
|
internal static class PlaceBehaviour {
|
||||||
|
|
||||||
internal static void Grass(Player p, ExtBlock block, ushort x, ushort y, ushort z) {
|
static bool SkipGrassDirt(Player p, ExtBlock block) {
|
||||||
DirtGrass(p, (ExtBlock)Block.Grass, x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Dirt(Player p, ExtBlock block, ushort x, ushort y, ushort z) {
|
|
||||||
DirtGrass(p, (ExtBlock)Block.Dirt, x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DirtGrass(Player p, ExtBlock block, ushort x, ushort y, ushort z) {
|
|
||||||
Level lvl = p.level;
|
Level lvl = p.level;
|
||||||
if (!lvl.Config.GrassGrow || !(lvl.physics == 0 || lvl.physics == 5)) {
|
return !lvl.Config.GrassGrow || p.ModeBlock == block || !(lvl.physics == 0 || lvl.physics == 5);
|
||||||
p.ChangeBlock(x, y, z, block); return;
|
|
||||||
}
|
|
||||||
if (p.ModeBlock.BlockID == Block.Dirt || p.ModeBlock.BlockID == Block.Grass) {
|
|
||||||
p.ChangeBlock(x, y, z, block); return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void GrassDie(Player p, ExtBlock block, ushort x, ushort y, ushort z) {
|
||||||
|
if (SkipGrassDirt(p, block)) { p.ChangeBlock(x, y, z, block); return; }
|
||||||
|
Level lvl = p.level;
|
||||||
ExtBlock above = lvl.GetBlock(x, (ushort)(y + 1), z);
|
ExtBlock above = lvl.GetBlock(x, (ushort)(y + 1), z);
|
||||||
block.BlockID = (above.BlockID == Block.Invalid || lvl.LightPasses(above)) ? Block.Grass : Block.Dirt;
|
|
||||||
|
if (above.BlockID != Block.Invalid && !lvl.LightPasses(above)) {
|
||||||
|
ushort index = p.level.Props[block.Index].DirtIndex;
|
||||||
|
block = ExtBlock.FromIndex(index);
|
||||||
|
}
|
||||||
p.ChangeBlock(x, y, z, block);
|
p.ChangeBlock(x, y, z, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static HandlePlace Stack(ExtBlock block) {
|
internal static void DirtGrow(Player p, ExtBlock block, ushort x, ushort y, ushort z) {
|
||||||
return (p, b, x, y, z) => Stack(p, block, x, y, z);
|
if (SkipGrassDirt(p, block)) { p.ChangeBlock(x, y, z, block); return; }
|
||||||
|
Level lvl = p.level;
|
||||||
|
ExtBlock above = lvl.GetBlock(x, (ushort)(y + 1), z);
|
||||||
|
|
||||||
|
if (above.BlockID == Block.Invalid || lvl.LightPasses(above)) {
|
||||||
|
ushort index = p.level.Props[block.Index].GrassIndex;
|
||||||
|
block = ExtBlock.FromIndex(index);
|
||||||
}
|
}
|
||||||
static void Stack(Player p, ExtBlock block, ushort x, ushort y, ushort z) {
|
p.ChangeBlock(x, y, z, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Stack(Player p, ExtBlock block, ushort x, ushort y, ushort z) {
|
||||||
if (p.level.GetBlock(x, (ushort)(y - 1), z) != block) {
|
if (p.level.GetBlock(x, (ushort)(y - 1), z) != block) {
|
||||||
p.ChangeBlock(x, y, z, block); return;
|
p.ChangeBlock(x, y, z, block); return;
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ namespace MCGalaxy {
|
|||||||
Props[CobblestoneSlab].StackId = Cobblestone;
|
Props[CobblestoneSlab].StackId = Cobblestone;
|
||||||
Props[Water].Drownable = true; Props[StillWater].Drownable = true;
|
Props[Water].Drownable = true; Props[StillWater].Drownable = true;
|
||||||
Props[Lava].Drownable = true; Props[StillLava].Drownable = true;
|
Props[Lava].Drownable = true; Props[StillLava].Drownable = true;
|
||||||
|
Props[Dirt].GrassIndex = Block.Grass; Props[Grass].DirtIndex = Block.Dirt;
|
||||||
|
|
||||||
// Block specific physics properties
|
// Block specific physics properties
|
||||||
Props[Block.Bird_Black].AnimalAI = AnimalAI.Fly;
|
Props[Block.Bird_Black].AnimalAI = AnimalAI.Fly;
|
||||||
|
@ -67,12 +67,20 @@ namespace MCGalaxy.Blocks {
|
|||||||
/// <summary> Whether players can drown inside this block (e.g. water). </summary>
|
/// <summary> Whether players can drown inside this block (e.g. water). </summary>
|
||||||
public bool Drownable;
|
public bool Drownable;
|
||||||
|
|
||||||
|
/// <summary> The block ID this is changed into when exposed to sunlight. </summary>
|
||||||
|
public ushort GrassIndex;
|
||||||
|
|
||||||
|
/// <summary> The block ID this is changed into when no longer exposed to sunlight. </summary>
|
||||||
|
public ushort DirtIndex;
|
||||||
|
|
||||||
/// <summary> Whether the properties for this block have been modified and hence require saving. </summary>
|
/// <summary> Whether the properties for this block have been modified and hence require saving. </summary>
|
||||||
public bool Changed;
|
public bool Changed;
|
||||||
|
|
||||||
public static BlockProps MakeDefault() {
|
public static BlockProps MakeDefault() {
|
||||||
BlockProps props = default(BlockProps);
|
BlockProps props = default(BlockProps);
|
||||||
props.oDoorIndex = Block.Invalid;
|
props.oDoorIndex = Block.Invalid;
|
||||||
|
props.GrassIndex = Block.Invalid;
|
||||||
|
props.DirtIndex = Block.Invalid;
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +98,8 @@ namespace MCGalaxy.Blocks {
|
|||||||
w.WriteLine("# This represents the physics properties for blocks, in the format of:");
|
w.WriteLine("# This represents the physics properties for blocks, in the format of:");
|
||||||
w.WriteLine("# id : Is rails : Is tdoor : Is door : Is message block : Is portal : " +
|
w.WriteLine("# id : Is rails : Is tdoor : Is door : Is message block : Is portal : " +
|
||||||
"Killed by water : Killed by lava : Kills players : death message : " +
|
"Killed by water : Killed by lava : Kills players : death message : " +
|
||||||
"Animal AI type : Stack block : Is OP block : oDoor block : Drownable");
|
"Animal AI type : Stack block : Is OP block : oDoor block : Drownable : " +
|
||||||
|
"Grass block : Dirt block");
|
||||||
for (int i = 0; i < scope.Length; i++) {
|
for (int i = 0; i < scope.Length; i++) {
|
||||||
if (!scope[i].Changed || (selector != null && !selector(i))) continue;
|
if (!scope[i].Changed || (selector != null && !selector(i))) continue;
|
||||||
BlockProps props = scope[i];
|
BlockProps props = scope[i];
|
||||||
@ -102,7 +111,7 @@ namespace MCGalaxy.Blocks {
|
|||||||
+ props.IsMessageBlock + ":" + props.IsPortal + ":" + props.WaterKills + ":"
|
+ props.IsMessageBlock + ":" + props.IsPortal + ":" + props.WaterKills + ":"
|
||||||
+ props.LavaKills + ":" + props.KillerBlock + ":" + deathMsg + ":"
|
+ props.LavaKills + ":" + props.KillerBlock + ":" + deathMsg + ":"
|
||||||
+ (byte)props.AnimalAI + ":" + props.StackId + ":" + props.OPBlock + ":"
|
+ (byte)props.AnimalAI + ":" + props.StackId + ":" + props.OPBlock + ":"
|
||||||
+ props.oDoorIndex + ":" + props.Drownable);
|
+ props.oDoorIndex + ":" + props.Drownable + ":" + props.GrassIndex + ":" + props.DirtIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,19 +163,23 @@ namespace MCGalaxy.Blocks {
|
|||||||
scope[idx].AnimalAI = (AnimalAI)ai;
|
scope[idx].AnimalAI = (AnimalAI)ai;
|
||||||
}
|
}
|
||||||
if (parts.Length > 11) {
|
if (parts.Length > 11) {
|
||||||
byte stackId; byte.TryParse(parts[11], out stackId);
|
byte.TryParse(parts[11], out scope[idx].StackId);
|
||||||
scope[idx].StackId = stackId;
|
|
||||||
}
|
}
|
||||||
if (parts.Length > 12) {
|
if (parts.Length > 12) {
|
||||||
bool.TryParse(parts[12], out scope[idx].OPBlock);
|
bool.TryParse(parts[12], out scope[idx].OPBlock);
|
||||||
}
|
}
|
||||||
if (parts.Length > 13) {
|
if (parts.Length > 13) {
|
||||||
ushort oDoor; ushort.TryParse(parts[13], out oDoor);
|
ushort.TryParse(parts[13], out scope[idx].oDoorIndex);
|
||||||
scope[idx].oDoorIndex = oDoor;
|
|
||||||
}
|
}
|
||||||
if (parts.Length > 14) {
|
if (parts.Length > 14) {
|
||||||
bool.TryParse(parts[14], out scope[idx].Drownable);
|
bool.TryParse(parts[14], out scope[idx].Drownable);
|
||||||
}
|
}
|
||||||
|
if (parts.Length > 15) {
|
||||||
|
ushort.TryParse(parts[15], out scope[idx].GrassIndex);
|
||||||
|
}
|
||||||
|
if (parts.Length > 16) {
|
||||||
|
ushort.TryParse(parts[16], out scope[idx].DirtIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,28 +111,36 @@ namespace MCGalaxy.Blocks.Physics {
|
|||||||
C.data.Data = PhysicsArgs.RemoveFromChecks;
|
C.data.Data = PhysicsArgs.RemoveFromChecks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DoDirt(Level lvl, ref Check C) {
|
public static void DoDirtGrow(Level lvl, ref Check C) {
|
||||||
if (!lvl.Config.GrassGrow) { C.data.Data = PhysicsArgs.RemoveFromChecks; return; }
|
if (!lvl.Config.GrassGrow) { C.data.Data = PhysicsArgs.RemoveFromChecks; return; }
|
||||||
ushort x, y, z;
|
ushort x, y, z;
|
||||||
lvl.IntToPos(C.b, out x, out y, out z);
|
lvl.IntToPos(C.b, out x, out y, out z);
|
||||||
|
|
||||||
if (C.data.Data > 20) {
|
if (C.data.Data > 20) {
|
||||||
ExtBlock above = lvl.GetBlock(x, (ushort)(y + 1), z);
|
ExtBlock above = lvl.GetBlock(x, (ushort)(y + 1), z);
|
||||||
if (lvl.LightPasses(above)) lvl.AddUpdate(C.b, Block.Grass);
|
if (lvl.LightPasses(above)) {
|
||||||
|
ExtBlock block = lvl.GetBlock(x, y, z);
|
||||||
|
ExtBlock grass = ExtBlock.FromIndex(lvl.Props[block.Index].GrassIndex);
|
||||||
|
lvl.AddUpdate(C.b, grass);
|
||||||
|
}
|
||||||
C.data.Data = PhysicsArgs.RemoveFromChecks;
|
C.data.Data = PhysicsArgs.RemoveFromChecks;
|
||||||
} else {
|
} else {
|
||||||
C.data.Data++;
|
C.data.Data++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DoGrass(Level lvl, ref Check C) {
|
public static void DoGrassDie(Level lvl, ref Check C) {
|
||||||
if (!lvl.Config.GrassGrow) { C.data.Data = PhysicsArgs.RemoveFromChecks; return; }
|
if (!lvl.Config.GrassGrow) { C.data.Data = PhysicsArgs.RemoveFromChecks; return; }
|
||||||
ushort x, y, z;
|
ushort x, y, z;
|
||||||
lvl.IntToPos(C.b, out x, out y, out z);
|
lvl.IntToPos(C.b, out x, out y, out z);
|
||||||
|
|
||||||
if (C.data.Data > 20) {
|
if (C.data.Data > 20) {
|
||||||
ExtBlock above = lvl.GetBlock(x, (ushort)(y + 1), z);
|
ExtBlock above = lvl.GetBlock(x, (ushort)(y + 1), z);
|
||||||
if (!lvl.LightPasses(above)) lvl.AddUpdate(C.b, Block.Dirt);
|
if (!lvl.LightPasses(above)) {
|
||||||
|
ExtBlock block = lvl.GetBlock(x, y, z);
|
||||||
|
ExtBlock dirt = ExtBlock.FromIndex(lvl.Props[block.Index].DirtIndex);
|
||||||
|
lvl.AddUpdate(C.b, dirt);
|
||||||
|
}
|
||||||
C.data.Data = PhysicsArgs.RemoveFromChecks;
|
C.data.Data = PhysicsArgs.RemoveFromChecks;
|
||||||
} else {
|
} else {
|
||||||
C.data.Data++;
|
C.data.Data++;
|
||||||
|
@ -125,7 +125,11 @@ namespace MCGalaxy.Commands.World {
|
|||||||
} else if (prop == "opblock" || prop == "op") {
|
} else if (prop == "opblock" || prop == "op") {
|
||||||
Toggle(p, scope, block, "an OP block", ref scope[i].OPBlock);
|
Toggle(p, scope, block, "an OP block", ref scope[i].OPBlock);
|
||||||
} else if (prop == "odoor") {
|
} else if (prop == "odoor") {
|
||||||
SetODoor(p, scope, block, i, text);
|
SetBlock(p, scope, block, i, text, ref scope[i].oDoorIndex, "oDoor");
|
||||||
|
} else if (prop == "grass") {
|
||||||
|
SetBlock(p, scope, block, i, text, ref scope[i].GrassIndex, "Grass form");
|
||||||
|
} else if (prop == "dirt") {
|
||||||
|
SetBlock(p, scope, block, i, text, ref scope[i].DirtIndex, "Dirt form");
|
||||||
} else if (prop == "drownable" || prop == "drown") {
|
} else if (prop == "drownable" || prop == "drown") {
|
||||||
Toggle(p, scope, block, "drowns players", ref scope[i].Drownable);
|
Toggle(p, scope, block, "drowns players", ref scope[i].Drownable);
|
||||||
} else {
|
} else {
|
||||||
@ -134,7 +138,8 @@ namespace MCGalaxy.Commands.World {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void Toggle(Player p, BlockProps[] scope, ExtBlock block, string type, ref bool on) {
|
static void Toggle(Player p, BlockProps[] scope, ExtBlock block,
|
||||||
|
string type, ref bool on) {
|
||||||
on = !on;
|
on = !on;
|
||||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||||
Player.Message(p, "Block {0} is {1}: {2}",
|
Player.Message(p, "Block {0} is {1}: {2}",
|
||||||
@ -143,7 +148,8 @@ namespace MCGalaxy.Commands.World {
|
|||||||
OnPropsChanged(scope, lvl, block);
|
OnPropsChanged(scope, lvl, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetEnum(Player p, BlockProps[] scope, ExtBlock block, int i, string msg) {
|
static void SetEnum(Player p, BlockProps[] scope, ExtBlock block,
|
||||||
|
int i, string msg) {
|
||||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||||
AnimalAI ai = AnimalAI.None;
|
AnimalAI ai = AnimalAI.None;
|
||||||
if (!CommandParser.GetEnum(p, msg, "Animal AI", ref ai)) return;
|
if (!CommandParser.GetEnum(p, msg, "Animal AI", ref ai)) return;
|
||||||
@ -154,7 +160,8 @@ namespace MCGalaxy.Commands.World {
|
|||||||
OnPropsChanged(scope, lvl, block);
|
OnPropsChanged(scope, lvl, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetDeathMessage(Player p, BlockProps[] scope, ExtBlock block, int i, string msg) {
|
static void SetDeathMessage(Player p, BlockProps[] scope, ExtBlock block,
|
||||||
|
int i, string msg) {
|
||||||
scope[i].DeathMessage = msg;
|
scope[i].DeathMessage = msg;
|
||||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||||
|
|
||||||
@ -168,7 +175,8 @@ namespace MCGalaxy.Commands.World {
|
|||||||
OnPropsChanged(scope, lvl, block);
|
OnPropsChanged(scope, lvl, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetStackId(Player p, BlockProps[] scope, ExtBlock block, int i, string msg) {
|
static void SetStackId(Player p, BlockProps[] scope, ExtBlock block,
|
||||||
|
int i, string msg) {
|
||||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||||
|
|
||||||
ExtBlock stackBlock;
|
ExtBlock stackBlock;
|
||||||
@ -190,20 +198,20 @@ namespace MCGalaxy.Commands.World {
|
|||||||
OnPropsChanged(scope, lvl, block);
|
OnPropsChanged(scope, lvl, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetODoor(Player p, BlockProps[] scope, ExtBlock block, int i, string msg) {
|
static void SetBlock(Player p, BlockProps[] scope, ExtBlock block,
|
||||||
|
int i, string msg, ref ushort target, string type) {
|
||||||
Level lvl = Player.IsSuper(p) ? null : p.level;
|
Level lvl = Player.IsSuper(p) ? null : p.level;
|
||||||
if (msg == null) {
|
if (msg == null) {
|
||||||
scope[i].oDoorIndex = Block.Invalid;
|
target = Block.Invalid;
|
||||||
Player.Message(p, "oDoor for {0} removed.", BlockName(scope, lvl, block));
|
Player.Message(p, "{1} for {0} removed.", BlockName(scope, lvl, block), type);
|
||||||
} else {
|
} else {
|
||||||
ExtBlock other = GetBlock(p, scope, msg);
|
ExtBlock other;
|
||||||
if (other.IsInvalid) return;
|
if (!CommandParser.GetBlock(p, msg, out other)) return;
|
||||||
if (other == block) { Player.Message(p, "ID of oDoor must be different."); return; }
|
if (other == block) { Player.Message(p, "ID of {0} must be different.", type); return; }
|
||||||
|
|
||||||
scope[i].oDoorIndex = (ushort)other.Index;
|
target = (ushort)other.Index;
|
||||||
|
Player.Message(p, "{2} for {0} set to: {1}", BlockName(scope, lvl, block),
|
||||||
Player.Message(p, "oDoor for {0} set to: {1}",
|
BlockName(scope, lvl, other), type);
|
||||||
BlockName(scope, lvl, block), BlockName(scope, lvl, other));
|
|
||||||
}
|
}
|
||||||
OnPropsChanged(scope, lvl, block);
|
OnPropsChanged(scope, lvl, block);
|
||||||
}
|
}
|
||||||
@ -302,6 +310,12 @@ namespace MCGalaxy.Commands.World {
|
|||||||
} else if (message.CaselessEq("drownable")) {
|
} else if (message.CaselessEq("drownable")) {
|
||||||
Player.Message(p, "%HSets whether this block can drown players.");
|
Player.Message(p, "%HSets whether this block can drown players.");
|
||||||
Player.Message(p, "%T/Map death %Hmust be enabled for players to drown.");
|
Player.Message(p, "%T/Map death %Hmust be enabled for players to drown.");
|
||||||
|
} else if (message.CaselessEq("grass")) {
|
||||||
|
Player.Message(p, "%HSets the block that this block is changed into, when exposed to sunlight");
|
||||||
|
Player.Message(p, "%HLeave block blank to remove this behaviour.");
|
||||||
|
} else if (message.CaselessEq("dirt")) {
|
||||||
|
Player.Message(p, "%HSets the block that this block is changed into, when no longer exposed to sunlight");
|
||||||
|
Player.Message(p, "%HLeave block blank to remove this behaviour.");
|
||||||
} else {
|
} else {
|
||||||
Player.Message(p, "&cUnrecognised property \"{0}\"", message);
|
Player.Message(p, "&cUnrecognised property \"{0}\"", message);
|
||||||
}
|
}
|
||||||
|
@ -33,13 +33,13 @@ namespace MCGalaxy.Commands.World {
|
|||||||
if (!LevelInfo.ValidateAction(p, lvl.name, "use %T/fixgrass %Son this level")) return;
|
if (!LevelInfo.ValidateAction(p, lvl.name, "use %T/fixgrass %Son this level")) return;
|
||||||
|
|
||||||
if (message.Length == 0) {
|
if (message.Length == 0) {
|
||||||
FixDirtAndGrass(p, lvl, ref totalFixed);
|
Fix(p, lvl, ref totalFixed, true, true);
|
||||||
} else if (message.CaselessEq("light")) {
|
} else if (message.CaselessEq("light")) {
|
||||||
FixLight(p, lvl, ref totalFixed);
|
FixLight(p, lvl, ref totalFixed);
|
||||||
} else if (message.CaselessEq("grass")) {
|
} else if (message.CaselessEq("grass")) {
|
||||||
FixGrass(p, lvl, ref totalFixed);
|
Fix(p, lvl, ref totalFixed, true, false);
|
||||||
} else if (message.CaselessEq("dirt")) {
|
} else if (message.CaselessEq("dirt")) {
|
||||||
FixDirt(p, lvl, ref totalFixed);
|
Fix(p, lvl, ref totalFixed, false, true);
|
||||||
} else {
|
} else {
|
||||||
Help(p); return;
|
Help(p); return;
|
||||||
}
|
}
|
||||||
@ -47,43 +47,43 @@ namespace MCGalaxy.Commands.World {
|
|||||||
Player.Message(p, "Fixed " + totalFixed + " blocks.");
|
Player.Message(p, "Fixed " + totalFixed + " blocks.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Fix(Player p, Level lvl, ref int totalFixed, bool fixGrass, bool fixDirt) {
|
||||||
static void FixDirtAndGrass(Player p, Level lvl, ref int totalFixed) {
|
|
||||||
int index = 0, maxY = lvl.Height - 1, oneY = lvl.Width * lvl.Length;
|
int index = 0, maxY = lvl.Height - 1, oneY = lvl.Width * lvl.Length;
|
||||||
BufferedBlockSender buffer = new BufferedBlockSender(lvl);
|
BufferedBlockSender buffer = new BufferedBlockSender(lvl);
|
||||||
ExtBlock above = default(ExtBlock);
|
ExtBlock above = default(ExtBlock), block = default(ExtBlock);
|
||||||
ExtBlock dirt = (ExtBlock)Block.Dirt, grass = (ExtBlock)Block.Grass;
|
|
||||||
|
|
||||||
for (int y = 0; y < lvl.Height; y++)
|
for (ushort y = 0; y < lvl.Height; y++)
|
||||||
for (int z = 0; z < lvl.Length; z++)
|
for (ushort z = 0; z < lvl.Length; z++)
|
||||||
for (int x = 0; x < lvl.Width; x++)
|
for (ushort x = 0; x < lvl.Width; x++)
|
||||||
{
|
{
|
||||||
byte block = lvl.blocks[index];
|
block.BlockID = lvl.blocks[index];
|
||||||
if (block == Block.Dirt) {
|
block.ExtID = 0;
|
||||||
|
if (block.BlockID == Block.custom_block)
|
||||||
|
block.ExtID = lvl.GetExtTile(x, y, z);
|
||||||
|
|
||||||
|
if (fixGrass && lvl.Props[block.Index].GrassIndex != Block.Invalid) {
|
||||||
above.BlockID = y == maxY ? Block.Air : lvl.blocks[index + oneY];
|
above.BlockID = y == maxY ? Block.Air : lvl.blocks[index + oneY];
|
||||||
above.ExtID = 0;
|
above.ExtID = 0;
|
||||||
if (above.BlockID == Block.custom_block)
|
if (above.BlockID == Block.custom_block)
|
||||||
above.ExtID = lvl.GetExtTile((ushort)x, (ushort)(y + 1), (ushort)z);
|
above.ExtID = lvl.GetExtTile(x, (ushort)(y + 1), z);
|
||||||
|
|
||||||
if (lvl.LightPasses(above)) {
|
ExtBlock grass = ExtBlock.FromIndex(lvl.Props[block.Index].GrassIndex);
|
||||||
if (p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, grass) == 2) {
|
if (lvl.LightPasses(above) && p.level.DoBlockchange(p, x, y, z, grass) == 2) {
|
||||||
buffer.Add(index, Block.Grass, 0);
|
buffer.Add(index, grass.BlockID, grass.ExtID);
|
||||||
totalFixed++;
|
totalFixed++;
|
||||||
}
|
}
|
||||||
}
|
} else if (fixDirt && lvl.Props[block.Index].DirtIndex != Block.Invalid) {
|
||||||
} else if (block == Block.Grass) {
|
|
||||||
above.BlockID = y == maxY ? Block.Air : lvl.blocks[index + oneY];
|
above.BlockID = y == maxY ? Block.Air : lvl.blocks[index + oneY];
|
||||||
above.ExtID = 0;
|
above.ExtID = 0;
|
||||||
if (above.BlockID == Block.custom_block)
|
if (above.BlockID == Block.custom_block)
|
||||||
above.ExtID = lvl.GetExtTile((ushort)x, (ushort)(y + 1), (ushort)z);
|
above.ExtID = lvl.GetExtTile(x, (ushort)(y + 1), z);
|
||||||
|
|
||||||
if (!lvl.LightPasses(above)) {
|
ExtBlock dirt = ExtBlock.FromIndex(lvl.Props[block.Index].DirtIndex);
|
||||||
if (p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, dirt) == 2) {
|
if (!lvl.LightPasses(above) && p.level.DoBlockchange(p, x, y, z, dirt) == 2) {
|
||||||
buffer.Add(index, Block.Dirt, 0);
|
buffer.Add(index, dirt.BlockID, dirt.ExtID);
|
||||||
totalFixed++;
|
totalFixed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
buffer.Send(true);
|
buffer.Send(true);
|
||||||
@ -92,99 +92,46 @@ namespace MCGalaxy.Commands.World {
|
|||||||
static void FixLight(Player p, Level lvl, ref int totalFixed) {
|
static void FixLight(Player p, Level lvl, ref int totalFixed) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
BufferedBlockSender buffer = new BufferedBlockSender(lvl);
|
BufferedBlockSender buffer = new BufferedBlockSender(lvl);
|
||||||
ExtBlock above = default(ExtBlock);
|
ExtBlock above = default(ExtBlock), block = default(ExtBlock);
|
||||||
ExtBlock dirt = (ExtBlock)Block.Dirt, grass = (ExtBlock)Block.Grass;
|
|
||||||
|
|
||||||
for (int y = 0; y < lvl.Height - 1; y++)
|
for (ushort y = 0; y < lvl.Height - 1; y++)
|
||||||
for (int z = 0; z < lvl.Length; z++)
|
for (ushort z = 0; z < lvl.Length; z++)
|
||||||
for (int x = 0; x < lvl.Width; x++)
|
for (ushort x = 0; x < lvl.Width; x++)
|
||||||
{
|
{
|
||||||
byte block = lvl.blocks[index];
|
block.BlockID = lvl.blocks[index];
|
||||||
|
block.ExtID = 0;
|
||||||
bool inShadow = false;
|
bool inShadow = false;
|
||||||
if (block == Block.Dirt) {
|
if (block.BlockID == Block.custom_block)
|
||||||
|
block.ExtID = lvl.GetExtTile(x, y, z);
|
||||||
|
|
||||||
|
if (lvl.Props[block.Index].GrassIndex != Block.Invalid) {
|
||||||
for (int i = 1; i < (lvl.Height - y); i++) {
|
for (int i = 1; i < (lvl.Height - y); i++) {
|
||||||
above.BlockID = lvl.blocks[index + (lvl.Width * lvl.Length) * i];
|
above.BlockID = lvl.blocks[index + (lvl.Width * lvl.Length) * i];
|
||||||
above.ExtID = 0;
|
above.ExtID = 0;
|
||||||
if (above.BlockID == Block.custom_block)
|
if (above.BlockID == Block.custom_block)
|
||||||
above.ExtID = lvl.GetExtTile((ushort)x, (ushort)(y + i), (ushort)z);
|
above.ExtID = lvl.GetExtTile(x, (ushort)(y + i), z);
|
||||||
|
|
||||||
if (!lvl.LightPasses(above)) { inShadow = true; break; }
|
if (!lvl.LightPasses(above)) { inShadow = true; break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inShadow && p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, grass) == 2) {
|
ExtBlock grass = ExtBlock.FromIndex(lvl.Props[block.Index].GrassIndex);
|
||||||
buffer.Add(index, Block.Grass, 0);
|
if (!inShadow && p.level.DoBlockchange(p, x, (ushort)y, z, grass) == 2) {
|
||||||
|
buffer.Add(index, grass.BlockID, grass.ExtID);
|
||||||
totalFixed++;
|
totalFixed++;
|
||||||
}
|
}
|
||||||
} else if (block == Block.Grass) {
|
} else if (lvl.Props[block.Index].DirtIndex != Block.Invalid) {
|
||||||
for (int i = 1; i < (lvl.Height - y); i++) {
|
for (int i = 1; i < (lvl.Height - y); i++) {
|
||||||
above.BlockID = lvl.blocks[index + (lvl.Width * lvl.Length) * i];
|
above.BlockID = lvl.blocks[index + (lvl.Width * lvl.Length) * i];
|
||||||
above.ExtID = 0;
|
above.ExtID = 0;
|
||||||
if (above.BlockID == Block.custom_block)
|
if (above.BlockID == Block.custom_block)
|
||||||
above.ExtID = lvl.GetExtTile((ushort)x, (ushort)(y + i), (ushort)z);
|
above.ExtID = lvl.GetExtTile(x, (ushort)(y + i), z);
|
||||||
|
|
||||||
if (!lvl.LightPasses(above)) { inShadow = true; break; }
|
if (!lvl.LightPasses(above)) { inShadow = true; break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inShadow && p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, dirt) == 2) {
|
ExtBlock dirt = ExtBlock.FromIndex(lvl.Props[block.Index].DirtIndex);
|
||||||
buffer.Add(index, Block.Dirt, 0);
|
if (inShadow && p.level.DoBlockchange(p, x, (ushort)y, z, dirt) == 2) {
|
||||||
totalFixed++;
|
buffer.Add(index, dirt.BlockID, dirt.ExtID);
|
||||||
}
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
buffer.Send(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FixDirt(Player p, Level lvl, ref int totalFixed) {
|
|
||||||
int index = 0, maxY = lvl.Height - 1, oneY = lvl.Width * lvl.Length;
|
|
||||||
BufferedBlockSender buffer = new BufferedBlockSender(lvl);
|
|
||||||
ExtBlock above = default(ExtBlock);
|
|
||||||
ExtBlock grass = (ExtBlock)Block.Grass;
|
|
||||||
|
|
||||||
for (int y = 0; y < lvl.Height; y++)
|
|
||||||
for (int z = 0; z < lvl.Length; z++)
|
|
||||||
for (int x = 0; x < lvl.Width; x++)
|
|
||||||
{
|
|
||||||
byte block = lvl.blocks[index];
|
|
||||||
if (block != Block.Dirt) { index++; continue; }
|
|
||||||
|
|
||||||
above.BlockID = y == maxY ? Block.Air : lvl.blocks[index + oneY];
|
|
||||||
above.ExtID = 0;
|
|
||||||
if (above.BlockID == Block.custom_block)
|
|
||||||
above.ExtID = lvl.GetExtTile((ushort)x, (ushort)(y + 1), (ushort)z);
|
|
||||||
|
|
||||||
if (lvl.LightPasses(above)) {
|
|
||||||
if (p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, grass) == 2) {
|
|
||||||
buffer.Add(index, Block.Grass, 0);
|
|
||||||
totalFixed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
buffer.Send(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FixGrass(Player p, Level lvl, ref int totalFixed) {
|
|
||||||
int index = 0, maxY = lvl.Height - 1, oneY = lvl.Width * lvl.Length;
|
|
||||||
BufferedBlockSender buffer = new BufferedBlockSender(lvl);
|
|
||||||
ExtBlock above = default(ExtBlock);
|
|
||||||
ExtBlock dirt = (ExtBlock)Block.Dirt;
|
|
||||||
|
|
||||||
for (int y = 0; y < lvl.Height; y++)
|
|
||||||
for (int z = 0; z < lvl.Length; z++)
|
|
||||||
for (int x = 0; x < lvl.Width; x++)
|
|
||||||
{
|
|
||||||
byte block = lvl.blocks[index];
|
|
||||||
if (block != Block.Grass) { index++; continue; }
|
|
||||||
|
|
||||||
above.BlockID = y == maxY ? Block.Air : lvl.blocks[index + oneY];
|
|
||||||
above.ExtID = 0;
|
|
||||||
if (above.BlockID == Block.custom_block)
|
|
||||||
above.ExtID = lvl.GetExtTile((ushort)x, (ushort)(y + 1), (ushort)z);
|
|
||||||
|
|
||||||
if (!lvl.LightPasses(above)) {
|
|
||||||
if (p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, dirt) == 2) {
|
|
||||||
buffer.Add(index, Block.Dirt, 0);
|
|
||||||
totalFixed++;
|
totalFixed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ namespace MCGalaxy {
|
|||||||
bool PlaceBlock(ExtBlock old, ushort x, ushort y, ushort z, ExtBlock block) {
|
bool PlaceBlock(ExtBlock old, ushort x, ushort y, ushort z, ExtBlock block) {
|
||||||
HandlePlace handler = level.placeHandlers[block.Index];
|
HandlePlace handler = level.placeHandlers[block.Index];
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler(this, old, x, y, z);
|
handler(this, block, x, y, z);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return ChangeBlock(x, y, z, block) == 2;
|
return ChangeBlock(x, y, z, block) == 2;
|
||||||
@ -177,13 +177,16 @@ namespace MCGalaxy {
|
|||||||
|
|
||||||
bool autoGrass = level.Config.GrassGrow && (level.physics == 0 || level.physics == 5);
|
bool autoGrass = level.Config.GrassGrow && (level.physics == 0 || level.physics == 5);
|
||||||
if (!autoGrass) return type;
|
if (!autoGrass) return type;
|
||||||
|
ExtBlock below = level.GetBlock(x, (ushort)(y - 1), z);
|
||||||
|
|
||||||
byte below = level.GetTile(x, (ushort)(y - 1), z);
|
ushort grassIdx = level.Props[below.Index].GrassIndex;
|
||||||
if (below == Block.Dirt && block.BlockID == Block.Air) {
|
if (grassIdx != Block.Invalid && block.BlockID == Block.Air) {
|
||||||
level.Blockchange(this, x, (ushort)(y - 1), z, (ExtBlock)Block.Grass);
|
level.Blockchange(this, x, (ushort)(y - 1), z, ExtBlock.FromIndex(grassIdx));
|
||||||
}
|
}
|
||||||
if (below == Block.Grass && !level.LightPasses(block)) {
|
|
||||||
level.Blockchange(this, x, (ushort)(y - 1), z, (ExtBlock)Block.Dirt);
|
ushort dirtIdx = level.Props[below.Index].DirtIndex;
|
||||||
|
if (dirtIdx != Block.Invalid && !level.LightPasses(block)) {
|
||||||
|
level.Blockchange(this, x, (ushort)(y - 1), z, ExtBlock.FromIndex(dirtIdx));
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user