Support custom dirt/grass blocks.

This commit is contained in:
UnknownShadow200 2017-10-15 19:29:30 +11:00
parent 935a90b0cd
commit 3457a6e5fa
8 changed files with 149 additions and 159 deletions

View File

@ -20,13 +20,13 @@ using MCGalaxy.Blocks.Physics;
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>
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>
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>
/// <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>
internal static HandlePlace GetPlaceHandler(ExtBlock block, BlockProps[] props) {
switch (block.BlockID) {
case Block.Dirt: return PlaceBehaviour.Dirt;
case Block.Grass: return PlaceBehaviour.Grass;
case Block.C4: return PlaceBehaviour.C4;
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;
}
@ -120,8 +120,6 @@ namespace MCGalaxy.Blocks {
case Block.Deadly_FastLava: return SimpleLiquidPhysics.DoFastLava;
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.Sapling: return OtherPhysics.DoShrub;
case Block.Fire: return FirePhysics.Do;
@ -158,6 +156,8 @@ namespace MCGalaxy.Blocks {
HandlePhysics animalAI = AnimalAIHandler(props[i].AnimalAI);
if (animalAI != null) return animalAI;
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
// Adv physics updating anything placed next to water or lava

View File

@ -22,32 +22,36 @@ namespace MCGalaxy.Blocks {
internal static class PlaceBehaviour {
internal static void Grass(Player p, ExtBlock block, ushort x, ushort y, ushort z) {
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) {
static bool SkipGrassDirt(Player p, ExtBlock block) {
Level lvl = p.level;
return !lvl.Config.GrassGrow || p.ModeBlock == block || !(lvl.physics == 0 || lvl.physics == 5);
}
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;
if (!lvl.Config.GrassGrow || !(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;
}
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);
}
internal static HandlePlace Stack(ExtBlock block) {
return (p, b, x, y, z) => Stack(p, block, x, y, z);
internal static void DirtGrow(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);
if (above.BlockID == Block.Invalid || lvl.LightPasses(above)) {
ushort index = p.level.Props[block.Index].GrassIndex;
block = ExtBlock.FromIndex(index);
}
p.ChangeBlock(x, y, z, block);
}
static void Stack(Player p, ExtBlock block, ushort x, ushort y, ushort z) {
internal static void Stack(Player p, ExtBlock block, ushort x, ushort y, ushort z) {
if (p.level.GetBlock(x, (ushort)(y - 1), z) != block) {
p.ChangeBlock(x, y, z, block); return;
}

View File

@ -92,6 +92,7 @@ namespace MCGalaxy {
Props[CobblestoneSlab].StackId = Cobblestone;
Props[Water].Drownable = true; Props[StillWater].Drownable = true;
Props[Lava].Drownable = true; Props[StillLava].Drownable = true;
Props[Dirt].GrassIndex = Block.Grass; Props[Grass].DirtIndex = Block.Dirt;
// Block specific physics properties
Props[Block.Bird_Black].AnimalAI = AnimalAI.Fly;

View File

@ -67,12 +67,20 @@ namespace MCGalaxy.Blocks {
/// <summary> Whether players can drown inside this block (e.g. water). </summary>
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>
public bool Changed;
public static BlockProps MakeDefault() {
BlockProps props = default(BlockProps);
props.oDoorIndex = Block.Invalid;
props.GrassIndex = Block.Invalid;
props.DirtIndex = Block.Invalid;
return props;
}
@ -90,7 +98,8 @@ namespace MCGalaxy.Blocks {
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 : " +
"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++) {
if (!scope[i].Changed || (selector != null && !selector(i))) continue;
BlockProps props = scope[i];
@ -102,7 +111,7 @@ namespace MCGalaxy.Blocks {
+ props.IsMessageBlock + ":" + props.IsPortal + ":" + props.WaterKills + ":"
+ props.LavaKills + ":" + props.KillerBlock + ":" + deathMsg + ":"
+ (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;
}
if (parts.Length > 11) {
byte stackId; byte.TryParse(parts[11], out stackId);
scope[idx].StackId = stackId;
byte.TryParse(parts[11], out scope[idx].StackId);
}
if (parts.Length > 12) {
bool.TryParse(parts[12], out scope[idx].OPBlock);
}
if (parts.Length > 13) {
ushort oDoor; ushort.TryParse(parts[13], out oDoor);
scope[idx].oDoorIndex = oDoor;
ushort.TryParse(parts[13], out scope[idx].oDoorIndex);
}
if (parts.Length > 14) {
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);
}
}
}
}

View File

@ -111,28 +111,36 @@ namespace MCGalaxy.Blocks.Physics {
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; }
ushort x, y, 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);
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;
} else {
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; }
ushort x, y, z;
lvl.IntToPos(C.b, out x, out y, out z);
if (C.data.Data > 20) {
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;
} else {
C.data.Data++;

View File

@ -125,7 +125,11 @@ namespace MCGalaxy.Commands.World {
} else if (prop == "opblock" || prop == "op") {
Toggle(p, scope, block, "an OP block", ref scope[i].OPBlock);
} 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") {
Toggle(p, scope, block, "drowns players", ref scope[i].Drownable);
} 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;
Level lvl = Player.IsSuper(p) ? null : p.level;
Player.Message(p, "Block {0} is {1}: {2}",
@ -143,7 +148,8 @@ namespace MCGalaxy.Commands.World {
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;
AnimalAI ai = AnimalAI.None;
if (!CommandParser.GetEnum(p, msg, "Animal AI", ref ai)) return;
@ -154,7 +160,8 @@ namespace MCGalaxy.Commands.World {
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;
Level lvl = Player.IsSuper(p) ? null : p.level;
@ -168,7 +175,8 @@ namespace MCGalaxy.Commands.World {
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;
ExtBlock stackBlock;
@ -190,20 +198,20 @@ namespace MCGalaxy.Commands.World {
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;
if (msg == null) {
scope[i].oDoorIndex = Block.Invalid;
Player.Message(p, "oDoor for {0} removed.", BlockName(scope, lvl, block));
target = Block.Invalid;
Player.Message(p, "{1} for {0} removed.", BlockName(scope, lvl, block), type);
} else {
ExtBlock other = GetBlock(p, scope, msg);
if (other.IsInvalid) return;
if (other == block) { Player.Message(p, "ID of oDoor must be different."); return; }
ExtBlock other;
if (!CommandParser.GetBlock(p, msg, out other)) return;
if (other == block) { Player.Message(p, "ID of {0} must be different.", type); return; }
scope[i].oDoorIndex = (ushort)other.Index;
Player.Message(p, "oDoor for {0} set to: {1}",
BlockName(scope, lvl, block), BlockName(scope, lvl, other));
target = (ushort)other.Index;
Player.Message(p, "{2} for {0} set to: {1}", BlockName(scope, lvl, block),
BlockName(scope, lvl, other), type);
}
OnPropsChanged(scope, lvl, block);
}
@ -302,6 +310,12 @@ namespace MCGalaxy.Commands.World {
} else if (message.CaselessEq("drownable")) {
Player.Message(p, "%HSets whether this block can drown players.");
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 {
Player.Message(p, "&cUnrecognised property \"{0}\"", message);
}

View File

@ -33,55 +33,55 @@ namespace MCGalaxy.Commands.World {
if (!LevelInfo.ValidateAction(p, lvl.name, "use %T/fixgrass %Son this level")) return;
if (message.Length == 0) {
FixDirtAndGrass(p, lvl, ref totalFixed);
Fix(p, lvl, ref totalFixed, true, true);
} else if (message.CaselessEq("light")) {
FixLight(p, lvl, ref totalFixed);
} else if (message.CaselessEq("grass")) {
FixGrass(p, lvl, ref totalFixed);
Fix(p, lvl, ref totalFixed, true, false);
} else if (message.CaselessEq("dirt")) {
FixDirt(p, lvl, ref totalFixed);
Fix(p, lvl, ref totalFixed, false, true);
} else {
Help(p); return;
}
Player.Message(p, "Fixed " + totalFixed + " blocks.");
}
}
static void FixDirtAndGrass(Player p, Level lvl, ref int totalFixed) {
static void Fix(Player p, Level lvl, ref int totalFixed, bool fixGrass, bool fixDirt) {
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, grass = (ExtBlock)Block.Grass;
ExtBlock above = default(ExtBlock), block = default(ExtBlock);
for (int y = 0; y < lvl.Height; y++)
for (int z = 0; z < lvl.Length; z++)
for (int x = 0; x < lvl.Width; x++)
for (ushort y = 0; y < lvl.Height; y++)
for (ushort z = 0; z < lvl.Length; z++)
for (ushort x = 0; x < lvl.Width; x++)
{
byte block = lvl.blocks[index];
if (block == Block.Dirt) {
block.BlockID = lvl.blocks[index];
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.ExtID = 0;
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)) {
if (p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, grass) == 2) {
buffer.Add(index, Block.Grass, 0);
totalFixed++;
}
ExtBlock grass = ExtBlock.FromIndex(lvl.Props[block.Index].GrassIndex);
if (lvl.LightPasses(above) && p.level.DoBlockchange(p, x, y, z, grass) == 2) {
buffer.Add(index, grass.BlockID, grass.ExtID);
totalFixed++;
}
} else if (block == Block.Grass) {
} else if (fixDirt && lvl.Props[block.Index].DirtIndex != Block.Invalid) {
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);
above.ExtID = lvl.GetExtTile(x, (ushort)(y + 1), 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++;
}
ExtBlock dirt = ExtBlock.FromIndex(lvl.Props[block.Index].DirtIndex);
if (!lvl.LightPasses(above) && p.level.DoBlockchange(p, x, y, z, dirt) == 2) {
buffer.Add(index, dirt.BlockID, dirt.ExtID);
totalFixed++;
}
}
index++;
@ -92,99 +92,46 @@ namespace MCGalaxy.Commands.World {
static void FixLight(Player p, Level lvl, ref int totalFixed) {
int index = 0;
BufferedBlockSender buffer = new BufferedBlockSender(lvl);
ExtBlock above = default(ExtBlock);
ExtBlock dirt = (ExtBlock)Block.Dirt, grass = (ExtBlock)Block.Grass;
ExtBlock above = default(ExtBlock), block = default(ExtBlock);
for (int y = 0; y < lvl.Height - 1; y++)
for (int z = 0; z < lvl.Length; z++)
for (int x = 0; x < lvl.Width; x++)
for (ushort y = 0; y < lvl.Height - 1; y++)
for (ushort z = 0; z < lvl.Length; z++)
for (ushort x = 0; x < lvl.Width; x++)
{
byte block = lvl.blocks[index];
block.BlockID = lvl.blocks[index];
block.ExtID = 0;
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++) {
above.BlockID = lvl.blocks[index + (lvl.Width * lvl.Length) * i];
above.ExtID = 0;
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 (!inShadow && p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, grass) == 2) {
buffer.Add(index, Block.Grass, 0);
ExtBlock grass = ExtBlock.FromIndex(lvl.Props[block.Index].GrassIndex);
if (!inShadow && p.level.DoBlockchange(p, x, (ushort)y, z, grass) == 2) {
buffer.Add(index, grass.BlockID, grass.ExtID);
totalFixed++;
}
} else if (block == Block.Grass) {
} else if (lvl.Props[block.Index].DirtIndex != Block.Invalid) {
for (int i = 1; i < (lvl.Height - y); i++) {
above.BlockID = lvl.blocks[index + (lvl.Width * lvl.Length) * i];
above.ExtID = 0;
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 (inShadow && p.level.DoBlockchange(p, (ushort)x, (ushort)y, (ushort)z, dirt) == 2) {
buffer.Add(index, Block.Dirt, 0);
totalFixed++;
}
}
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);
ExtBlock dirt = ExtBlock.FromIndex(lvl.Props[block.Index].DirtIndex);
if (inShadow && p.level.DoBlockchange(p, x, (ushort)y, z, dirt) == 2) {
buffer.Add(index, dirt.BlockID, dirt.ExtID);
totalFixed++;
}
}

View File

@ -154,7 +154,7 @@ namespace MCGalaxy {
bool PlaceBlock(ExtBlock old, ushort x, ushort y, ushort z, ExtBlock block) {
HandlePlace handler = level.placeHandlers[block.Index];
if (handler != null) {
handler(this, old, x, y, z);
handler(this, block, x, y, z);
return true;
}
return ChangeBlock(x, y, z, block) == 2;
@ -176,14 +176,17 @@ namespace MCGalaxy {
level.BlockDB.Cache.Add(this, x, y, z, flags, old, block);
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);
if (below == Block.Dirt && block.BlockID == Block.Air) {
level.Blockchange(this, x, (ushort)(y - 1), z, (ExtBlock)Block.Grass);
ushort grassIdx = level.Props[below.Index].GrassIndex;
if (grassIdx != Block.Invalid && block.BlockID == Block.Air) {
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;
}