diff --git a/src/main/java/thebetweenlands/common/block/terrain/BlockSpreadingDeath.java b/src/main/java/thebetweenlands/common/block/terrain/BlockSpreadingDeath.java index 62d73d98b..8890eaa1f 100644 --- a/src/main/java/thebetweenlands/common/block/terrain/BlockSpreadingDeath.java +++ b/src/main/java/thebetweenlands/common/block/terrain/BlockSpreadingDeath.java @@ -1,5 +1,8 @@ package thebetweenlands.common.block.terrain; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Random; import javax.annotation.Nullable; @@ -14,6 +17,10 @@ import net.minecraft.world.World; import net.minecraft.world.biome.Biome; import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.fml.common.network.NetworkRegistry.TargetPoint; +import thebetweenlands.common.TheBetweenlands; +import thebetweenlands.common.network.clientbound.MessageSyncDeathSpread; +import thebetweenlands.common.network.clientbound.MessageSyncDeathSpread.SpreadEntry; public abstract class BlockSpreadingDeath extends Block { public static final PropertyBool INACTIVE = PropertyBool.create("inactive"); @@ -61,6 +68,8 @@ public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state) { public void updateTick(World world, BlockPos pos, IBlockState state, Random rand) { if(!world.isRemote) { if(!state.getValue(INACTIVE) && this.shouldSpread(world, pos, state)) { + List spreadEntries = new ArrayList(); + boolean spread = false; for(int i = 0; i < 16; ++i) { BlockPos target = pos.add(rand.nextInt(3) - 1, rand.nextInt(3) - 1, rand.nextInt(3) - 1); @@ -71,6 +80,7 @@ public void updateTick(World world, BlockPos pos, IBlockState state, Random rand if(offsetState.getBlock() != this && this.canSpreadInto(world, pos, state, target, offsetState)) { this.spreadInto(world, pos, state, target, offsetState); if(this.getSpreadingBiome() != null) { + spreadEntries.add(new SpreadEntry(target.getX(), target.getZ(), Biome.getIdForBiome(this.getSpreadingBiome()))); this.convertBiome(world, target, this.getSpreadingBiome()); } spread = true; @@ -87,6 +97,7 @@ public void updateTick(World world, BlockPos pos, IBlockState state, Random rand if(offsetState.getBlock() != this && this.canSpreadInto(world, pos, state, target, offsetState)) { this.spreadInto(world, pos, state, target, offsetState); if(this.getSpreadingBiome() != null) { + spreadEntries.add(new SpreadEntry(target.getX(), target.getZ(), Biome.getIdForBiome(this.getSpreadingBiome()))); this.convertBiome(world, target, this.getSpreadingBiome()); } spread = true; @@ -95,6 +106,9 @@ public void updateTick(World world, BlockPos pos, IBlockState state, Random rand } } + if(spread) //send biome update packet + sendUpdatePacket(world, pos, spreadEntries); + int spreadTime = this.getScheduledSpreadTime(world, pos, state); if(spreadTime > 0) { world.scheduleUpdate(pos, this, spreadTime); @@ -106,6 +120,7 @@ public void updateTick(World world, BlockPos pos, IBlockState state, Random rand } if(this.getSpreadingBiome() != null && rand.nextInt(3) == 0 && world.getBiomeForCoordsBody(pos) != this.getSpreadingBiome()) { + sendUpdatePacket(world, pos, Arrays.asList(new SpreadEntry(pos.getX(), pos.getZ(), Biome.getIdForBiome(this.getSpreadingBiome())))); //replicate to clients this.convertBiome(world, pos, this.getSpreadingBiome()); } } @@ -136,18 +151,30 @@ public Biome getPreviousBiome() { return null; } + //send biome update packet + protected void sendUpdatePacket(World world, BlockPos pos, List entries) { + if(world.isRemote) { return; } + + MessageSyncDeathSpread message = new MessageSyncDeathSpread(entries); + TargetPoint point = new TargetPoint(world.provider.getDimension(), pos.getX(), pos.getY(), pos.getZ(), -1); + TheBetweenlands.networkWrapper.sendToAllTracking( + message, + point + ); + } + protected void checkAndRevertBiome(World world, BlockPos pos) { if(this.getPreviousBiome() != null && this.getSpreadingBiome() != null && world.getBiomeForCoordsBody(pos) == this.getSpreadingBiome()) { + sendUpdatePacket(world, pos, Arrays.asList(new SpreadEntry(pos.getX(), pos.getZ(), Biome.getIdForBiome(this.getPreviousBiome())))); //replicate to clients this.convertBiome(world, pos, this.getPreviousBiome()); } } protected void convertBiome(World world, BlockPos pos, Biome biome) { Chunk chunk = world.getChunk(pos); - byte[] biomes = chunk.getBiomeArray().clone(); int index = (pos.getZ() & 15) << 4 | (pos.getX() & 15); + byte[] biomes = chunk.getBiomeArray(); biomes[index] = (byte) (Biome.getIdForBiome(biome) & 255); - chunk.setBiomeArray(biomes); chunk.markDirty(); } } diff --git a/src/main/java/thebetweenlands/common/network/clientbound/MessageSyncDeathSpread.java b/src/main/java/thebetweenlands/common/network/clientbound/MessageSyncDeathSpread.java new file mode 100644 index 000000000..c67395d5c --- /dev/null +++ b/src/main/java/thebetweenlands/common/network/clientbound/MessageSyncDeathSpread.java @@ -0,0 +1,86 @@ +package thebetweenlands.common.network.clientbound; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.BlockPos.MutableBlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import thebetweenlands.common.network.MessageBase; + +public class MessageSyncDeathSpread extends MessageBase { + public static class SpreadEntry { + private int blockX; + private int blockZ; + private byte biomeId; + + public SpreadEntry(int blockX, int blockZ, int biomeId) { + this.blockX = blockX; + this.blockZ = blockZ; + this.biomeId = (byte)biomeId; + } + } + + private List entries; + + public MessageSyncDeathSpread() { } + + public MessageSyncDeathSpread(List entries) { + this.entries = entries; + } + + @Override + public void serialize(PacketBuffer buf) { + final int size = this.entries.size(); + buf.writeVarInt(size); + for(SpreadEntry entry : this.entries) { + buf.writeInt(entry.blockX); + buf.writeInt(entry.blockZ); + buf.writeByte(entry.biomeId); + } + } + + @Override + public void deserialize(PacketBuffer buf) { + final int size = buf.readVarInt(); + this.entries = new ArrayList(size); + for(int i = 0; i < size; ++i) { + final int blockX = buf.readInt(); + final int blockZ = buf.readInt(); + final byte biomeId = buf.readByte(); + this.entries.add(new SpreadEntry(blockX, blockZ, biomeId)); + } + } + + @Override + public IMessage process(MessageContext ctx) { + if(ctx.side == Side.CLIENT) { + this.handle(); + } + + return null; + } + + @SideOnly(Side.CLIENT) + private void handle() { + Minecraft mc = Minecraft.getMinecraft(); + World world = mc.world; + if(world != null) { + MutableBlockPos pos = new MutableBlockPos(); + for(SpreadEntry entry : this.entries) { + pos.setPos(entry.blockX, 0, entry.blockZ); + Chunk chunk = world.getChunk(pos); + final byte[] biomes = chunk.getBiomeArray(); + final int x = entry.blockX & 15; + final int z = entry.blockZ & 15; + biomes[z << 4 | x] = entry.biomeId; + } + } + } +} diff --git a/src/main/java/thebetweenlands/common/registries/MessageRegistry.java b/src/main/java/thebetweenlands/common/registries/MessageRegistry.java index 1939ab2b6..589fd1023 100644 --- a/src/main/java/thebetweenlands/common/registries/MessageRegistry.java +++ b/src/main/java/thebetweenlands/common/registries/MessageRegistry.java @@ -34,6 +34,7 @@ import thebetweenlands.common.network.clientbound.MessageSoundRipple; import thebetweenlands.common.network.clientbound.MessageSummonPeatMummyParticles; import thebetweenlands.common.network.clientbound.MessageSyncChunkStorage; +import thebetweenlands.common.network.clientbound.MessageSyncDeathSpread; import thebetweenlands.common.network.clientbound.MessageSyncDraetonLeakages; import thebetweenlands.common.network.clientbound.MessageSyncEntityCapabilities; import thebetweenlands.common.network.clientbound.MessageSyncEnvironmentEventData; @@ -97,6 +98,7 @@ public static void preInit() { registerMessage(MessageShockArrowHit.class, Side.CLIENT); registerMessage(MessageShockParticle.class, Side.CLIENT); registerMessage(MessageInfestWeedwoodBush.class, Side.CLIENT); + registerMessage(MessageSyncDeathSpread.class, Side.CLIENT); registerMessage(MessageEquipItem.class, Side.SERVER); registerMessage(MessageOpenPouch.class, Side.SERVER);