From 0583514827e000ef2a6a3e1e9c8edf3e6558ffa0 Mon Sep 17 00:00:00 2001 From: Irtimaled Date: Sat, 31 Jan 2015 02:19:05 +0000 Subject: [PATCH] Initial commit --- .gitignore | 1 + java/com/irtimaled/bbor/BoundingBox.java | 69 +++++ java/com/irtimaled/bbor/BoundingBoxCache.java | 17 ++ .../bbor/BoundingBoxDeserializer.java | 51 ++++ .../irtimaled/bbor/BoundingBoxMessage.java | 58 ++++ .../bbor/BoundingBoxMessageHandler.java | 22 ++ .../bbor/BoundingBoxOutlineReloaded.java | 45 +++ .../irtimaled/bbor/BoundingBoxSerializer.java | 111 +++++++ .../irtimaled/bbor/BoundingBoxSlimeChunk.java | 22 ++ .../irtimaled/bbor/BoundingBoxStructure.java | 22 ++ .../irtimaled/bbor/BoundingBoxVillage.java | 46 +++ java/com/irtimaled/bbor/ClientProxy.java | 283 ++++++++++++++++++ java/com/irtimaled/bbor/CommonProxy.java | 47 +++ java/com/irtimaled/bbor/ConfigManager.java | 64 ++++ .../irtimaled/bbor/DimensionProcessor.java | 224 ++++++++++++++ java/com/irtimaled/bbor/ServerProxy.java | 77 +++++ resources/mcmod.info | 17 ++ 17 files changed, 1176 insertions(+) create mode 100644 .gitignore create mode 100644 java/com/irtimaled/bbor/BoundingBox.java create mode 100644 java/com/irtimaled/bbor/BoundingBoxCache.java create mode 100644 java/com/irtimaled/bbor/BoundingBoxDeserializer.java create mode 100644 java/com/irtimaled/bbor/BoundingBoxMessage.java create mode 100644 java/com/irtimaled/bbor/BoundingBoxMessageHandler.java create mode 100644 java/com/irtimaled/bbor/BoundingBoxOutlineReloaded.java create mode 100644 java/com/irtimaled/bbor/BoundingBoxSerializer.java create mode 100644 java/com/irtimaled/bbor/BoundingBoxSlimeChunk.java create mode 100644 java/com/irtimaled/bbor/BoundingBoxStructure.java create mode 100644 java/com/irtimaled/bbor/BoundingBoxVillage.java create mode 100644 java/com/irtimaled/bbor/ClientProxy.java create mode 100644 java/com/irtimaled/bbor/CommonProxy.java create mode 100644 java/com/irtimaled/bbor/ConfigManager.java create mode 100644 java/com/irtimaled/bbor/DimensionProcessor.java create mode 100644 java/com/irtimaled/bbor/ServerProxy.java create mode 100644 resources/mcmod.info diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..e43b0f98 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/java/com/irtimaled/bbor/BoundingBox.java b/java/com/irtimaled/bbor/BoundingBox.java new file mode 100644 index 00000000..72b24e77 --- /dev/null +++ b/java/com/irtimaled/bbor/BoundingBox.java @@ -0,0 +1,69 @@ +package com.irtimaled.bbor; + +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; + +import java.awt.*; + +public abstract class BoundingBox { + private final Color color; + private final BlockPos minBlockPos; + private final BlockPos maxBlockPos; + + protected BoundingBox(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) { + this.minBlockPos = minBlockPos; + this.maxBlockPos = maxBlockPos; + this.color = color; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + minBlockPos.hashCode(); + result = prime * result + maxBlockPos.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BoundingBox other = (BoundingBox) obj; + if (!minBlockPos.equals(other.minBlockPos)) + return false; + if (!maxBlockPos.equals(other.maxBlockPos)) + return false; + return true; + } + + @Override + public String toString() { + return "(" + minBlockPos.toString() + "; " + maxBlockPos.toString() + ")"; + } + + public AxisAlignedBB toAxisAlignedBB() { + return AxisAlignedBB.fromBounds(minBlockPos.getX(), + minBlockPos.getY(), + minBlockPos.getZ(), + maxBlockPos.getX(), + maxBlockPos.getY(), + maxBlockPos.getZ()); + } + + public BlockPos getMinBlockPos() { + return minBlockPos; + } + + public BlockPos getMaxBlockPos() { + return maxBlockPos; + } + + public Color getColor() { + return color; + } +} \ No newline at end of file diff --git a/java/com/irtimaled/bbor/BoundingBoxCache.java b/java/com/irtimaled/bbor/BoundingBoxCache.java new file mode 100644 index 00000000..0c60ca0b --- /dev/null +++ b/java/com/irtimaled/bbor/BoundingBoxCache.java @@ -0,0 +1,17 @@ +package com.irtimaled.bbor; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class BoundingBoxCache { + + protected ConcurrentHashMap> cache = new ConcurrentHashMap>(); + + public Map> getBoundingBoxes() { + return cache; + } + + public synchronized void refresh() { + } +} diff --git a/java/com/irtimaled/bbor/BoundingBoxDeserializer.java b/java/com/irtimaled/bbor/BoundingBoxDeserializer.java new file mode 100644 index 00000000..37202ae4 --- /dev/null +++ b/java/com/irtimaled/bbor/BoundingBoxDeserializer.java @@ -0,0 +1,51 @@ +package com.irtimaled.bbor; + +import io.netty.buffer.ByteBuf; +import net.minecraft.util.BlockPos; +import net.minecraftforge.fml.common.network.ByteBufUtils; + +import java.awt.*; + +public class BoundingBoxDeserializer { + public static BoundingBox deserialize(ByteBuf buf) { + char type = (char) ByteBufUtils.readVarShort(buf); + switch (type) { + case 'V': + return deserializeVillage(buf); + case 'S': + return deserializeStructure(buf); + case 'C': + return deserializeSlimeChunk(buf); + } + return null; + } + + private static BoundingBox deserializeSlimeChunk(ByteBuf buf) { + BlockPos minBlockPos = deserializeBlockPos(buf); + BlockPos maxBlockPos = deserializeBlockPos(buf); + Color color = new Color(ByteBufUtils.readVarInt(buf, 5)); + return BoundingBoxSlimeChunk.from(minBlockPos, maxBlockPos, color); + } + + private static BoundingBox deserializeStructure(ByteBuf buf) { + BlockPos minBlockPos = deserializeBlockPos(buf); + BlockPos maxBlockPos = deserializeBlockPos(buf); + Color color = new Color(ByteBufUtils.readVarInt(buf, 5)); + return BoundingBoxStructure.from(minBlockPos, maxBlockPos, color); + } + + private static BoundingBox deserializeVillage(ByteBuf buf) { + BlockPos center = deserializeBlockPos(buf); + int radius = ByteBufUtils.readVarInt(buf, 5); + boolean spawnsIronGolems = ByteBufUtils.readVarShort(buf) == 1; + Color color = new Color(ByteBufUtils.readVarInt(buf, 5)); + return BoundingBoxVillage.from(center, radius, spawnsIronGolems, color); + } + + private static BlockPos deserializeBlockPos(ByteBuf buf) { + int x = ByteBufUtils.readVarInt(buf, 5); + int y = ByteBufUtils.readVarInt(buf, 5); + int z = ByteBufUtils.readVarInt(buf, 5); + return new BlockPos(x, y, z); + } +} \ No newline at end of file diff --git a/java/com/irtimaled/bbor/BoundingBoxMessage.java b/java/com/irtimaled/bbor/BoundingBoxMessage.java new file mode 100644 index 00000000..872d794b --- /dev/null +++ b/java/com/irtimaled/bbor/BoundingBoxMessage.java @@ -0,0 +1,58 @@ +package com.irtimaled.bbor; + +import io.netty.buffer.ByteBuf; +import net.minecraftforge.fml.common.network.ByteBufUtils; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; + +import java.util.HashSet; +import java.util.Set; + +public class BoundingBoxMessage implements IMessage { + private int dimension; + private BoundingBox key; + private Set boundingBoxes; + + public static BoundingBoxMessage from(int dimension, BoundingBox key, Set boundingBoxes) { + BoundingBoxMessage message = new BoundingBoxMessage(); + message.dimension = dimension; + message.key = key; + message.boundingBoxes = boundingBoxes; + return message; + } + + @Override + public void fromBytes(ByteBuf buf) { + dimension = ByteBufUtils.readVarShort(buf); + key = BoundingBoxDeserializer.deserialize(buf); + boundingBoxes = new HashSet(); + while (buf.isReadable()) { + BoundingBox boundingBox = BoundingBoxDeserializer.deserialize(buf); + boundingBoxes.add(boundingBox); + } + if (boundingBoxes.size() == 0) + boundingBoxes.add(key); + } + + @Override + public void toBytes(ByteBuf buf) { + ByteBufUtils.writeVarShort(buf, dimension); + BoundingBoxSerializer.serialize(key, buf); + if (boundingBoxes.size() > 1) { + for (BoundingBox boundingBox : boundingBoxes) { + BoundingBoxSerializer.serialize(boundingBox, buf); + } + } + } + + public int getDimension() { + return dimension; + } + + public BoundingBox getKey() { + return key; + } + + public Set getBoundingBoxes() { + return boundingBoxes; + } +} diff --git a/java/com/irtimaled/bbor/BoundingBoxMessageHandler.java b/java/com/irtimaled/bbor/BoundingBoxMessageHandler.java new file mode 100644 index 00000000..4be22a67 --- /dev/null +++ b/java/com/irtimaled/bbor/BoundingBoxMessageHandler.java @@ -0,0 +1,22 @@ +package com.irtimaled.bbor; + +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import java.util.Map; + +public class BoundingBoxMessageHandler implements IMessageHandler { + @Override + public IMessage onMessage(BoundingBoxMessage message, MessageContext ctx) { + + Map boundingBoxCacheMap = BoundingBoxOutlineReloaded.proxy.boundingBoxCacheMap; + int dimension = message.getDimension(); + if (!boundingBoxCacheMap.containsKey(dimension)) { + boundingBoxCacheMap.put(dimension, new BoundingBoxCache()); + } + + boundingBoxCacheMap.get(dimension).getBoundingBoxes().put(message.getKey(), message.getBoundingBoxes()); + return null; + } +} \ No newline at end of file diff --git a/java/com/irtimaled/bbor/BoundingBoxOutlineReloaded.java b/java/com/irtimaled/bbor/BoundingBoxOutlineReloaded.java new file mode 100644 index 00000000..481fc0ed --- /dev/null +++ b/java/com/irtimaled/bbor/BoundingBoxOutlineReloaded.java @@ -0,0 +1,45 @@ +package com.irtimaled.bbor; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.SidedProxy; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; + + +@Mod(modid = BoundingBoxOutlineReloaded.MODID, name = BoundingBoxOutlineReloaded.NAME, version = BoundingBoxOutlineReloaded.VERSION) +public class BoundingBoxOutlineReloaded { + + public static final String MODID = "bbor"; + public static final String NAME = "Bounding Box Outline Reloaded"; + public static final String VERSION = "1.0.0"; + + private ConfigManager configManager; + + public SimpleNetworkWrapper network; + + @Mod.Instance() + public static BoundingBoxOutlineReloaded instance; + + @SidedProxy(clientSide = "ClientProxy", serverSide = "ServerProxy") + public static CommonProxy proxy; + + + @EventHandler + public void preInit(FMLPreInitializationEvent evt) { + configManager = new ConfigManager(evt.getModConfigurationDirectory()); + } + + @EventHandler + public void load(FMLInitializationEvent evt) { + MinecraftForge.EVENT_BUS.register(proxy); + FMLCommonHandler.instance().bus().register(proxy); + + proxy.configManager = configManager; + proxy.init(); + } +} + diff --git a/java/com/irtimaled/bbor/BoundingBoxSerializer.java b/java/com/irtimaled/bbor/BoundingBoxSerializer.java new file mode 100644 index 00000000..d202cd36 --- /dev/null +++ b/java/com/irtimaled/bbor/BoundingBoxSerializer.java @@ -0,0 +1,111 @@ +package com.irtimaled.bbor; + +import io.netty.buffer.ByteBuf; +import net.minecraft.util.BlockPos; +import net.minecraftforge.fml.common.network.ByteBufUtils; + +import java.awt.*; + +public class BoundingBoxSerializer { + + public static void serialize(BoundingBox boundingBox, ByteBuf buf) { + if (boundingBox instanceof BoundingBoxSlimeChunk) { + serializeSlimeChunk((BoundingBoxSlimeChunk) boundingBox, buf); + } else if (boundingBox instanceof BoundingBoxVillage) { + serializeVillage((BoundingBoxVillage) boundingBox, buf); + } else if (boundingBox instanceof BoundingBoxStructure) { + serializeStructure((BoundingBoxStructure) boundingBox, buf); + } + } + + + private static void serializeVillage(BoundingBoxVillage boundingBox, ByteBuf buf) { + ByteBufUtils.writeVarShort(buf, 'V'); + serializeBlockPos(boundingBox.getCenter(), buf); + ByteBufUtils.writeVarInt(buf, boundingBox.getRadius(), 5); + ByteBufUtils.writeVarShort(buf, boundingBox.getSpawnsIronGolems() ? 1 : 0); + serializeColor(boundingBox.getColor(), buf); + } + + private static void serializeStructure(BoundingBoxStructure boundingBox, ByteBuf buf) { + ByteBufUtils.writeVarShort(buf, 'S'); + serializeCuboid(boundingBox, buf); + serializeColor(boundingBox.getColor(), buf); + } + + private static void serializeSlimeChunk(BoundingBoxSlimeChunk boundingBox, ByteBuf buf) { + ByteBufUtils.writeVarShort(buf, 'C'); + serializeCuboid(boundingBox, buf); + serializeColor(boundingBox.getColor(), buf); + } + + private static void serializeColor(Color color, ByteBuf buf) { + ByteBufUtils.writeVarInt(buf, color.getRGB(), 5); + } + + private static void serializeCuboid(BoundingBox boundingBox, ByteBuf buf) { + serializeBlockPos(boundingBox.getMinBlockPos(), buf); + serializeBlockPos(boundingBox.getMaxBlockPos(), buf); + } + + private static void serializeBlockPos(BlockPos blockPos, ByteBuf buf) { + ByteBufUtils.writeVarInt(buf, blockPos.getX(), 5); + ByteBufUtils.writeVarInt(buf, blockPos.getY(), 5); + ByteBufUtils.writeVarInt(buf, blockPos.getZ(), 5); + } + /* + + + public static void serialize(BoundingBox boundingBox, StringBuilder sb) { + if (boundingBox instanceof BoundingBoxSlimeChunk) { + serializeSlimeChunk((BoundingBoxSlimeChunk) boundingBox, sb); + } else if (boundingBox instanceof BoundingBoxVillage) { + serializeVillage((BoundingBoxVillage) boundingBox, sb); + } else if (boundingBox instanceof BoundingBoxStructure) { + serializeStructure((BoundingBoxStructure) boundingBox, sb); + } + } + + private static void serializeVillage(BoundingBoxVillage boundingBox, StringBuilder sb) { + sb.append("V/"); + serializeBlockPos(boundingBox.getCenter(), sb); + sb.append('/'); + sb.append(boundingBox.getRadius()); + sb.append('/'); + sb.append(boundingBox.getSpawnsIronGolems()); + sb.append('/'); + serializeColor(boundingBox.getColor(), sb); + } + + private static void serializeStructure(BoundingBoxStructure boundingBox, StringBuilder sb) { + sb.append("S/"); + serializeCuboid(boundingBox, sb); + sb.append('/'); + serializeColor(boundingBox.getColor(), sb); + } + + private static void serializeSlimeChunk(BoundingBoxSlimeChunk boundingBox, StringBuilder sb) { + sb.append("SC/"); + serializeCuboid(boundingBox, sb); + sb.append('/'); + serializeColor(boundingBox.getColor(), sb); + } + + private static void serializeColor(Color color, StringBuilder sb) { + sb.append(color.getRGB()); + } + + private static void serializeCuboid(BoundingBox boundingBox, StringBuilder sb) { + serializeBlockPos(boundingBox.getMinBlockPos(), sb); + sb.append('/'); + serializeBlockPos(boundingBox.getMaxBlockPos(), sb); + } + + private static void serializeBlockPos(BlockPos blockPos, StringBuilder sb) { + sb.append(blockPos.getX()); + sb.append(','); + sb.append(blockPos.getY()); + sb.append(','); + sb.append(blockPos.getZ()); + }*/ +} diff --git a/java/com/irtimaled/bbor/BoundingBoxSlimeChunk.java b/java/com/irtimaled/bbor/BoundingBoxSlimeChunk.java new file mode 100644 index 00000000..8ac1f800 --- /dev/null +++ b/java/com/irtimaled/bbor/BoundingBoxSlimeChunk.java @@ -0,0 +1,22 @@ +package com.irtimaled.bbor; + +import net.minecraft.util.BlockPos; +import net.minecraft.world.ChunkCoordIntPair; + +import java.awt.*; + +public class BoundingBoxSlimeChunk extends BoundingBox { + private BoundingBoxSlimeChunk(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) { + super(minBlockPos, maxBlockPos, color); + } + + public static BoundingBoxSlimeChunk from(ChunkCoordIntPair chunkCoordIntPair, Color color) { + BlockPos minBlockPos = new BlockPos(chunkCoordIntPair.getXStart(), 1, chunkCoordIntPair.getZStart()); + BlockPos maxBlockPos = new BlockPos(chunkCoordIntPair.getXEnd(), 38, chunkCoordIntPair.getZEnd()); + return new BoundingBoxSlimeChunk(minBlockPos, maxBlockPos, color); + } + + public static BoundingBoxSlimeChunk from(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) { + return new BoundingBoxSlimeChunk(minBlockPos, maxBlockPos, color); + } +} \ No newline at end of file diff --git a/java/com/irtimaled/bbor/BoundingBoxStructure.java b/java/com/irtimaled/bbor/BoundingBoxStructure.java new file mode 100644 index 00000000..e93b4184 --- /dev/null +++ b/java/com/irtimaled/bbor/BoundingBoxStructure.java @@ -0,0 +1,22 @@ +package com.irtimaled.bbor; + +import net.minecraft.util.BlockPos; +import net.minecraft.world.gen.structure.StructureBoundingBox; + +import java.awt.*; + +public class BoundingBoxStructure extends BoundingBox { + private BoundingBoxStructure(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) { + super(minBlockPos, maxBlockPos, color); + } + + public static BoundingBoxStructure from(StructureBoundingBox bb, Color color) { + BlockPos minBlockPos = new BlockPos(bb.minX, bb.minY, bb.minZ); + BlockPos maxBlockPos = new BlockPos(bb.maxX, bb.maxY, bb.maxZ); + return new BoundingBoxStructure(minBlockPos, maxBlockPos, color); + } + + public static BoundingBoxStructure from(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) { + return new BoundingBoxStructure(minBlockPos, maxBlockPos, color); + } +} \ No newline at end of file diff --git a/java/com/irtimaled/bbor/BoundingBoxVillage.java b/java/com/irtimaled/bbor/BoundingBoxVillage.java new file mode 100644 index 00000000..4af262ac --- /dev/null +++ b/java/com/irtimaled/bbor/BoundingBoxVillage.java @@ -0,0 +1,46 @@ +package com.irtimaled.bbor; + +import net.minecraft.util.BlockPos; + +import java.awt.*; + +public class BoundingBoxVillage extends BoundingBox { + private final BlockPos center; + private final Integer radius; + private final boolean spawnsIronGolems; + + protected BoundingBoxVillage(BlockPos center, Integer radius, Color color, boolean spawnsIronGolems, BlockPos minBlockPos, BlockPos maxBlockPos) { + super(minBlockPos, maxBlockPos, color); + this.center = center; + this.radius = radius; + this.spawnsIronGolems = spawnsIronGolems; + } + + + public static BoundingBox from(BlockPos center, Integer radius, boolean spawnsIronGolems, Color color) { + BlockPos minBlockPos = new BlockPos(center.getX() - radius, + center.getY() - 4, + center.getZ() - radius); + BlockPos maxBlockPos = new BlockPos(center.getX() + radius, + center.getY() + 4, + center.getZ() + radius); + return new BoundingBoxVillage(center, radius, color, spawnsIronGolems, minBlockPos, maxBlockPos); + } + + @Override + public String toString() { + return "(" + center.toString() + "; " + radius.toString() + ")"; + } + + public Integer getRadius() { + return radius; + } + + public BlockPos getCenter() { + return center; + } + + public boolean getSpawnsIronGolems() { + return spawnsIronGolems; + } +} \ No newline at end of file diff --git a/java/com/irtimaled/bbor/ClientProxy.java b/java/com/irtimaled/bbor/ClientProxy.java new file mode 100644 index 00000000..bcc6a611 --- /dev/null +++ b/java/com/irtimaled/bbor/ClientProxy.java @@ -0,0 +1,283 @@ +package com.irtimaled.bbor; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.client.registry.ClientRegistry; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent; +import net.minecraftforge.fml.relauncher.ReflectionHelper; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.glu.GLU; +import org.lwjgl.util.glu.Sphere; + +import java.awt.*; +import java.util.Map; +import java.util.Set; + +public class ClientProxy extends CommonProxy { + + @SubscribeEvent + public void onKeyInputEvent(InputEvent.KeyInputEvent evt) { + if (hotKey.isPressed()) { + active = !active; + } + } + + private boolean active; + private KeyBinding hotKey; + + @Override + public void init() { + super.init(); + hotKey = new KeyBinding("key.bbor.hotKey", Keyboard.KEY_B, "key.categories.bbor"); + ClientRegistry.registerKeyBinding(hotKey); + } + + + private double playerX; + private double playerY; + private double playerZ; + + + @SubscribeEvent + public void renderWorldLastEvent(RenderWorldLastEvent event) { + // determine current player location + EntityPlayer entityPlayer = Minecraft.getMinecraft().thePlayer; + playerX = entityPlayer.lastTickPosX + (entityPlayer.posX - entityPlayer.lastTickPosX) * (double) event.partialTicks; + playerY = entityPlayer.lastTickPosY + (entityPlayer.posY - entityPlayer.lastTickPosY) * (double) event.partialTicks; + playerZ = entityPlayer.lastTickPosZ + (entityPlayer.posZ - entityPlayer.lastTickPosZ) * (double) event.partialTicks; + + + if (this.active) { + int activeDimensionId = entityPlayer.worldObj.provider.getDimensionId(); + if (boundingBoxCacheMap.containsKey(activeDimensionId)) { + renderBBoxMap(boundingBoxCacheMap.get(activeDimensionId).getBoundingBoxes()); + } + } + } + + private void renderBBoxMap(Map> map) { + + + GL11.glEnable(GL11.GL_BLEND); + GL11.glLineWidth(3.0f); + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_CULL_FACE); + + if (configManager.alwaysVisible.getBoolean()) { + GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT); + } + + for (BoundingBox bb : map.keySet()) { + renderBoundingBoxes(map.get(bb)); + } + + GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); + GL11.glEnable(GL11.GL_CULL_FACE); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + + + if (configManager.showDebugInfo.getBoolean()) { + Minecraft mc = Minecraft.getMinecraft(); + ScaledResolution var5 = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight); + int screenWidth = var5.getScaledWidth(); + mc.entityRenderer.setupOverlayRendering(); + int count = 0; + for (BoundingBox bb : map.keySet()) { + count += map.get(bb).size(); + } + String debug = String.format("%d/%d", map.keySet().size(), count); + int width = screenWidth - mc.fontRendererObj.getStringWidth(debug); + + mc.fontRendererObj.drawStringWithShadow(debug, width - 2, 2, 16777215); + } + } + + private void renderBoundingBoxes(Set bbList) { + World world = Minecraft.getMinecraft().theWorld; + Set activeChunks = ReflectionHelper.getPrivateValue(World.class, world, 33); + for (BoundingBox bb : bbList) { + + if (activeChunks.contains(world.getChunkFromBlockCoords(bb.getMinBlockPos()).getChunkCoordIntPair()) || + activeChunks.contains(world.getChunkFromBlockCoords(bb.getMaxBlockPos()).getChunkCoordIntPair())) { + + if (bb instanceof BoundingBoxVillage) { + BoundingBoxVillage villageBB = (BoundingBoxVillage) bb; + if (configManager.renderVillageAsSphere.getBoolean()) { + renderBoundingBoxVillageAsSphere(villageBB); + } else { + renderBoundingBox(villageBB); + } + if (configManager.drawIronGolemSpawnArea.getBoolean() && + villageBB.getSpawnsIronGolems()) { + renderIronGolemSpawnArea(villageBB); + } + } else if (bb instanceof BoundingBoxSlimeChunk) { + renderSlimeChunk((BoundingBoxSlimeChunk) bb); + } else { + renderBoundingBox(bb); + } + } + } + } + + private void renderSlimeChunk(BoundingBoxSlimeChunk bb) { + AxisAlignedBB aaBB = bb.toAxisAlignedBB(); + Color color = bb.getColor(); + renderCuboid(aaBB, color); + + double maxY = configManager.slimeChunkMaxY.getInt(); + if ((maxY == 0) || (playerY < maxY)) { + maxY = playerY; + } + + if (maxY > 39) { + aaBB = new AxisAlignedBB(aaBB.minX, 39, aaBB.minZ, aaBB.maxX, maxY, aaBB.maxZ); + renderCuboid(aaBB, color, configManager.fill.getBoolean()); + } + } + + private void renderIronGolemSpawnArea(BoundingBoxVillage villageBB) { + BlockPos center = villageBB.getCenter(); + AxisAlignedBB abb = new AxisAlignedBB(new BlockPos(center.getX() - 8, + center.getY() - 3, + center.getZ() - 8), + new BlockPos(center.getX() + 8, + center.getY() + 4, + center.getZ() + 8)); + GL11.glLineWidth(2.0f); + renderCuboid(abb, villageBB.getColor(), false); + GL11.glLineWidth(3.0f); + } + + private void renderCuboid(AxisAlignedBB aaBB, Color color) { + renderCuboid(aaBB.addCoord(0, 1, 0), color, configManager.fill.getBoolean()); + } + + private void renderBoundingBox(BoundingBox bb) { + AxisAlignedBB aaBB = bb.toAxisAlignedBB(); + Color color = bb.getColor(); + renderCuboid(aaBB, color); + } + + private void renderBoundingBoxVillageAsSphere(BoundingBoxVillage bb) { + BlockPos center = bb.getCenter(); + int radius = bb.getRadius(); + Color color = bb.getColor(); + renderSphere(center, radius, color); + } + + private void renderCuboid(AxisAlignedBB aaBB, Color color, boolean fill) { + aaBB = offsetAxisAlignedBB(aaBB); + if (fill) { + GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); + renderCuboid(aaBB, 30, color); + GL11.glEnable(GL11.GL_POLYGON_OFFSET_LINE); + GL11.glPolygonOffset(-1.f, -1.f); + } + GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE); + renderCuboid(aaBB, 255, color); + } + + private void renderSphere(BlockPos center, int radius, Color color) { + int colorR = color.getRed(); + int colorG = color.getGreen(); + int colorB = color.getBlue(); + + double x = center.getX() - playerX; + double y = center.getY() - playerY; + double z = center.getZ() - playerZ; + GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_CONSTANT_COLOR); + GL11.glPointSize(2.5f); + GL11.glTranslated(x, y, z); + Sphere sphere = new Sphere(); + sphere.setDrawStyle(GLU.GLU_POINT); + sphere.setNormals(GLU.GLU_FLAT); + sphere.setOrientation(GLU.GLU_OUTSIDE); + GL11.glColor3f(colorR / 255.0f, colorG / 255.0f, colorB / 255.0f); + GL11.glRotatef(90f, 0, 0, 0); + sphere.draw(radius, 48, 48); + GL11.glRotatef(-90f, 0, 0, 0); + GL11.glTranslated(-x, -y, -z); + GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ZERO); + } + + private AxisAlignedBB offsetAxisAlignedBB(AxisAlignedBB axisAlignedBB) { + double expandBy = 0.005F; + return axisAlignedBB + .addCoord(1, 0, 1) + .expand(expandBy, expandBy, expandBy) + .offset(-playerX, -playerY, -playerZ); + } + + private void renderCuboid(AxisAlignedBB bb, int alphaChannel, Color color) { + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldRenderer = tessellator.getWorldRenderer(); + + int colorR = color.getRed(); + int colorG = color.getGreen(); + int colorB = color.getBlue(); + + worldRenderer.startDrawing(GL11.GL_QUADS); + worldRenderer.setColorRGBA(colorR, colorG, colorB, alphaChannel); + worldRenderer.addVertex(bb.minX, bb.minY, bb.minZ); + worldRenderer.addVertex(bb.maxX, bb.minY, bb.minZ); + worldRenderer.addVertex(bb.maxX, bb.minY, bb.maxZ); + worldRenderer.addVertex(bb.minX, bb.minY, bb.maxZ); + tessellator.draw(); + + if (bb.minY == bb.maxY) { + return; + } + + worldRenderer.startDrawing(GL11.GL_QUADS); + worldRenderer.setColorRGBA(colorR, colorG, colorB, alphaChannel); + worldRenderer.addVertex(bb.minX, bb.maxY, bb.minZ); + worldRenderer.addVertex(bb.maxX, bb.maxY, bb.minZ); + worldRenderer.addVertex(bb.maxX, bb.maxY, bb.maxZ); + worldRenderer.addVertex(bb.minX, bb.maxY, bb.maxZ); + tessellator.draw(); + + worldRenderer.startDrawing(GL11.GL_QUADS); + worldRenderer.setColorRGBA(colorR, colorG, colorB, alphaChannel); + worldRenderer.addVertex(bb.minX, bb.minY, bb.maxZ); + worldRenderer.addVertex(bb.minX, bb.maxY, bb.maxZ); + worldRenderer.addVertex(bb.maxX, bb.maxY, bb.maxZ); + worldRenderer.addVertex(bb.maxX, bb.minY, bb.maxZ); + tessellator.draw(); + + worldRenderer.startDrawing(GL11.GL_QUADS); + worldRenderer.setColorRGBA(colorR, colorG, colorB, alphaChannel); + worldRenderer.addVertex(bb.minX, bb.minY, bb.minZ); + worldRenderer.addVertex(bb.minX, bb.maxY, bb.minZ); + worldRenderer.addVertex(bb.maxX, bb.maxY, bb.minZ); + worldRenderer.addVertex(bb.maxX, bb.minY, bb.minZ); + tessellator.draw(); + + worldRenderer.startDrawing(GL11.GL_QUADS); + worldRenderer.setColorRGBA(colorR, colorG, colorB, alphaChannel); + worldRenderer.addVertex(bb.minX, bb.minY, bb.minZ); + worldRenderer.addVertex(bb.minX, bb.minY, bb.maxZ); + worldRenderer.addVertex(bb.minX, bb.maxY, bb.maxZ); + worldRenderer.addVertex(bb.minX, bb.maxY, bb.minZ); + tessellator.draw(); + + worldRenderer.startDrawing(GL11.GL_QUADS); + worldRenderer.setColorRGBA(colorR, colorG, colorB, alphaChannel); + worldRenderer.addVertex(bb.maxX, bb.minY, bb.minZ); + worldRenderer.addVertex(bb.maxX, bb.minY, bb.maxZ); + worldRenderer.addVertex(bb.maxX, bb.maxY, bb.maxZ); + worldRenderer.addVertex(bb.maxX, bb.maxY, bb.minZ); + tessellator.draw(); + } +} diff --git a/java/com/irtimaled/bbor/CommonProxy.java b/java/com/irtimaled/bbor/CommonProxy.java new file mode 100644 index 00000000..3a09c385 --- /dev/null +++ b/java/com/irtimaled/bbor/CommonProxy.java @@ -0,0 +1,47 @@ +package com.irtimaled.bbor; + +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.ChunkProviderServer; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.FMLLog; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; +import net.minecraftforge.fml.relauncher.Side; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class CommonProxy { + + public Map boundingBoxCacheMap = new ConcurrentHashMap(); + + public ConfigManager configManager; + protected SimpleNetworkWrapper network; + + public void init() { + network = NetworkRegistry.INSTANCE.newSimpleChannel("bbor"); + network.registerMessage(BoundingBoxMessageHandler.class, BoundingBoxMessage.class, 0, Side.CLIENT); + } + + @SubscribeEvent + public void worldEvent(WorldEvent.Load event) { + IChunkProvider chunkProvider = event.world.getChunkProvider(); + if (chunkProvider instanceof ChunkProviderServer) { + chunkProvider = ((ChunkProviderServer) chunkProvider).serverChunkGenerator; + long seed = event.world.getSeed(); + int dimensionId = event.world.provider.getDimensionId(); + FMLLog.info("create world dimension: %d, %s (chunkprovider: %s) (seed: %d)", dimensionId, event.world.getClass().toString(), chunkProvider.getClass().toString(), seed); + boundingBoxCacheMap.put(dimensionId, new DimensionProcessor(configManager, event.world, seed, dimensionId, chunkProvider)); + } + } + + @SubscribeEvent + public void chunkEvent(ChunkEvent.Load event) { + int dimensionId = event.world.provider.getDimensionId(); + if (boundingBoxCacheMap.containsKey(dimensionId)) { + boundingBoxCacheMap.get(dimensionId).refresh(); + } + } +} diff --git a/java/com/irtimaled/bbor/ConfigManager.java b/java/com/irtimaled/bbor/ConfigManager.java new file mode 100644 index 00000000..7005c757 --- /dev/null +++ b/java/com/irtimaled/bbor/ConfigManager.java @@ -0,0 +1,64 @@ +package com.irtimaled.bbor; + +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.common.config.Property; + +import java.io.File; + +public class ConfigManager { + public Configuration config; + + public Property showDebugInfo; + public Property fill; + public Property drawVillages; + public Property drawDesertTemples; + public Property drawJungleTemples; + public Property drawWitchHuts; + public Property drawStrongholds; + public Property drawMineShafts; + public Property drawNetherFortresses; + public Property drawOceanMonuments; + public Property alwaysVisible; + public Property renderVillageAsSphere; + public Property drawIronGolemSpawnArea; + public Property drawSlimeChunks; + public Property slimeChunkMaxY; + + private Property SetupBooleanProperty(Configuration config, String category, String configName, Boolean defaultValue, String comment) { + Property property = config.get(category, configName, defaultValue); + property.comment = comment; + property.set(property.getBoolean(defaultValue)); + return property; + } + + private Property SetupIntegerProperty(Configuration config, String category, String configName, int defaultValue, String comment) { + Property property = config.get(category, configName, defaultValue); + property.comment = comment; + property.set(property.getInt(defaultValue)); + return property; + } + + public ConfigManager(File configDir) { + config = new Configuration(new File(configDir, "BBOutlineReloaded.cfg")); + config.load(); + + showDebugInfo = SetupBooleanProperty(config, "general", "showDebugInfo", false, "If set to true debug information will be displayed. (default: false)"); + fill = SetupBooleanProperty(config, "general", "fill", false, "If set to true the bounding boxes are filled. (default: false)"); + alwaysVisible = SetupBooleanProperty(config, "general", "alwaysVisible", false, "If set to true boxes will be visible even through other blocks. (default: false)"); + + drawVillages = SetupBooleanProperty(config, "features", "drawVillages", true, "If set to true village bounding boxes are drawn. (default: true)"); + renderVillageAsSphere = SetupBooleanProperty(config, "features", "renderVillageAsSphere", true, "If set to true villages will be drawn as a sphere. (default:true)"); + drawIronGolemSpawnArea = SetupBooleanProperty(config, "features", "drawIronGolemSpawnArea", true, "If set to true the iron golem spawn area of the village will be drawn. (default:true)"); + drawDesertTemples = SetupBooleanProperty(config, "features", "drawDesertTemples", true, "If set to true desert temple bounding boxes are drawn. (default: true)"); + drawJungleTemples = SetupBooleanProperty(config, "features", "drawJungleTemples", true, "If set to true jungle temple bounding boxes are drawn. (default: true)"); + drawWitchHuts = SetupBooleanProperty(config, "features", "drawWitchHuts", true, "If set to true witch hut bounding boxes are drawn. (default: true)"); + drawStrongholds = SetupBooleanProperty(config, "features", "drawStrongholds", false, "If set to true stronghold bounding boxes are drawn. (default: false)"); + drawMineShafts = SetupBooleanProperty(config, "features", "drawMineShafts", false, "If set to true mineshaft bounding boxes are drawn. (default: false)"); + drawNetherFortresses = SetupBooleanProperty(config, "features", "drawNetherFortresses", true, "If set to true nether fortress bounding boxes are drawn. (default: true)"); + drawOceanMonuments = SetupBooleanProperty(config, "features", "drawOceanMonuments", true, "If set to true ocean monument bounding boxes are drawn. (default: true)"); + drawSlimeChunks = SetupBooleanProperty(config, "features", "drawSlimeChunks", true, "If set to true slime chunks bounding boxes are drawn. (default: true)"); + slimeChunkMaxY = SetupIntegerProperty(config, "features", "slimeChunkMaxY", 0, "The maximum top of the slime chunk bounding box. If set to 0 it will always track the player's feet. (default: 0)"); + + config.save(); + } +} \ No newline at end of file diff --git a/java/com/irtimaled/bbor/DimensionProcessor.java b/java/com/irtimaled/bbor/DimensionProcessor.java new file mode 100644 index 00000000..90100545 --- /dev/null +++ b/java/com/irtimaled/bbor/DimensionProcessor.java @@ -0,0 +1,224 @@ +package com.irtimaled.bbor; + +import net.minecraft.util.BlockPos; +import net.minecraft.village.Village; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.ChunkProviderGenerate; +import net.minecraft.world.gen.ChunkProviderHell; +import net.minecraft.world.gen.structure.ComponentScatteredFeaturePieces; +import net.minecraft.world.gen.structure.MapGenStructure; +import net.minecraft.world.gen.structure.StructureComponent; +import net.minecraft.world.gen.structure.StructureStart; +import net.minecraftforge.fml.common.FMLLog; +import net.minecraftforge.fml.relauncher.ReflectionHelper; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class DimensionProcessor extends BoundingBoxCache { + + private ConfigManager configManager; + private World world; + private long seed; + + public DimensionProcessor(ConfigManager configManager, World world, long seed, int dimensionId, IChunkProvider chunkProvider) { + this.configManager = configManager; + this.world = world; + this.seed = seed; + this.dimensionId = dimensionId; + this.chunkProvider = chunkProvider; + villageCache = new HashSet(); + slimeChunkCache = new HashSet(); + } + + private int dimensionId; + private IChunkProvider chunkProvider; + private Set villageCache; + private Set slimeChunkCache; + + private static Collection getStructures(T chunkProvider, int method) { + Class cpClass = (Class) chunkProvider.getClass(); + Object structureGenerator = ReflectionHelper.getPrivateValue(cpClass, chunkProvider, method); + if (structureGenerator instanceof MapGenStructure) { + Map structureMap = ReflectionHelper.getPrivateValue(MapGenStructure.class, (MapGenStructure) structureGenerator, 1); + return structureMap.values(); + } + return Collections.emptyList(); + } + + private static final int JUNGLE_TEMPLE = 1; + private static final int DESERT_TEMPLE = 2; + private static final int WITCH_HUT = 3; + private static final int OCEAN_MONUMENT = 4; + private static final int STRONGHOLD = 5; + private static final int MINE_SHAFT = 6; + private static final int NETHER_FORTRESS = 7; + + private Map> getStructures() { + + Map> structureMap = new HashMap>(); + if (chunkProvider instanceof ChunkProviderGenerate) { + + if (configManager.drawDesertTemples.getBoolean()) { + structureMap.put(DimensionProcessor.DESERT_TEMPLE, getStructuresWithComponent(getStructures(chunkProvider, 20), ComponentScatteredFeaturePieces.DesertPyramid.class)); + } + + if (configManager.drawJungleTemples.getBoolean()) { + structureMap.put(DimensionProcessor.JUNGLE_TEMPLE, getStructuresWithComponent(getStructures(chunkProvider, 20), ComponentScatteredFeaturePieces.JunglePyramid.class)); + } + + if (configManager.drawWitchHuts.getBoolean()) { + structureMap.put(DimensionProcessor.WITCH_HUT, getStructuresWithComponent(getStructures(chunkProvider, 20), ComponentScatteredFeaturePieces.SwampHut.class)); + } + + if (configManager.drawOceanMonuments.getBoolean()) { + structureMap.put(DimensionProcessor.OCEAN_MONUMENT, getStructures(chunkProvider, 22)); + } + + if (configManager.drawStrongholds.getBoolean()) { + structureMap.put(DimensionProcessor.STRONGHOLD, getStructures(chunkProvider, 17)); + } + + if (configManager.drawMineShafts.getBoolean()) { + structureMap.put(DimensionProcessor.MINE_SHAFT, getStructures(chunkProvider, 19)); + } + } else if (chunkProvider instanceof ChunkProviderHell) { + + if (configManager.drawNetherFortresses.getBoolean()) { + structureMap.put(DimensionProcessor.NETHER_FORTRESS, getStructures(chunkProvider, 22)); + } + } + + return structureMap; + } + + private Collection getStructuresWithComponent(Collection structures, Class structureComponent) { + Collection validStructures = new HashSet(); + for (StructureStart structure : structures) { + if (structure.getComponents().getFirst().getClass().equals(structureComponent)) { + validStructures.add(structure); + } + } + return validStructures; + } + + @Override + public synchronized void refresh() { + Map> structureMap = getStructures(); + for (Integer structureType : structureMap.keySet()) { + Color color = getStructureColor(structureType); + for (StructureStart structureStart : structureMap.get(structureType)) { + BoundingBox boundingBox = BoundingBoxStructure.from(structureStart.getBoundingBox(), color); + if (!cache.containsKey(boundingBox)) { + Set structureBoundingBoxes = new HashSet(); + Iterator structureComponents = structureStart.getComponents().iterator(); + while (structureComponents.hasNext()) { + StructureComponent structureComponent = (StructureComponent) structureComponents.next(); + structureBoundingBoxes.add(BoundingBoxStructure.from(structureComponent.getBoundingBox(), color)); + } + cache.put(boundingBox, structureBoundingBoxes); + FMLLog.info("[%d] new boundingBoxCacheMap entries: %d", dimensionId, structureBoundingBoxes.size()); + } + } + } + + if (configManager.drawSlimeChunks.getBoolean() && + dimensionId == 0) { + Set slimeChunkBoundingBoxes = new HashSet(); + Set activeChunks = ReflectionHelper.getPrivateValue(World.class, world, 33); + for (ChunkCoordIntPair chunk : activeChunks) { + if (isSlimeChunk(chunk.chunkXPos, chunk.chunkZPos)) { + slimeChunkBoundingBoxes.add(BoundingBoxSlimeChunk.from(chunk, Color.GREEN)); + } + } + + processDelta(slimeChunkCache, slimeChunkBoundingBoxes); + + slimeChunkCache = slimeChunkBoundingBoxes; + } + + if (configManager.drawVillages.getBoolean() && + (world.villageCollectionObj != null)) { + + Set villageBoundingBoxes = new HashSet(); + List villages = world.villageCollectionObj.getVillageList(); + int c = 0; + for (Village village : villages) { + BlockPos center = ReflectionHelper.getPrivateValue(Village.class, village, 3); + Integer radius = ReflectionHelper.getPrivateValue(Village.class, village, 4); + boolean spawnsIronGolems = village.getNumVillagers() >= 10 && + village.getNumVillageDoors() >= 21; + Color color = getVillageColor(c % 6); + villageBoundingBoxes.add(BoundingBoxVillage.from(center, radius, spawnsIronGolems, color)); + ++c; + } + processDelta(villageCache, villageBoundingBoxes); + + villageCache = villageBoundingBoxes; + } + } + + private void processDelta(Set oldBoundingBoxes, Set newBoundingBoxes) { + for (BoundingBox bb : oldBoundingBoxes) { + if (!newBoundingBoxes.contains(bb)) { + cache.remove(bb); + } else { + if (!cache.containsKey(bb)) { + Set boundingBoxes = new HashSet(); + boundingBoxes.add(bb); + cache.put(bb, boundingBoxes); + } + } + } + } + + private boolean isSlimeChunk(int chunkX, int chunkZ) { + Random r = new Random(seed + + (long) (chunkX * chunkX * 4987142) + + (long) (chunkX * 5947611) + + (long) (chunkZ * chunkZ) * 4392871L + + (long) (chunkZ * 389711) ^ 987234911L); + return r.nextInt(10) == 0; + } + + private Color getVillageColor(int c) { + switch (c) { + case 0: + return Color.RED; + case 1: + return Color.MAGENTA; + case 2: + return Color.BLUE; + case 3: + return Color.CYAN; + case 4: + return Color.GREEN; + case 5: + return Color.YELLOW; + } + return Color.WHITE; + } + + private Color getStructureColor(Integer structureType) { + switch (structureType) { + case DimensionProcessor.DESERT_TEMPLE: + return Color.ORANGE; + case DimensionProcessor.JUNGLE_TEMPLE: + return Color.GREEN; + case DimensionProcessor.WITCH_HUT: + return Color.BLUE; + case DimensionProcessor.MINE_SHAFT: + return Color.LIGHT_GRAY; + case DimensionProcessor.NETHER_FORTRESS: + return Color.RED; + case DimensionProcessor.OCEAN_MONUMENT: + return Color.CYAN; + case DimensionProcessor.STRONGHOLD: + return Color.YELLOW; + } + return Color.WHITE; + } +} \ No newline at end of file diff --git a/java/com/irtimaled/bbor/ServerProxy.java b/java/com/irtimaled/bbor/ServerProxy.java new file mode 100644 index 00000000..1c5e9237 --- /dev/null +++ b/java/com/irtimaled/bbor/ServerProxy.java @@ -0,0 +1,77 @@ +package com.irtimaled.bbor; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraftforge.fml.common.FMLLog; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class ServerProxy extends CommonProxy { + + public ConcurrentHashMap playerDimensions = + new ConcurrentHashMap(); + + private Map> playerBoundingBoxesCache = new HashMap>(); + + @SubscribeEvent + public void playerJoinedWorldEvent(net.minecraftforge.event.entity.EntityJoinWorldEvent evt) { + if (evt.entity instanceof EntityPlayerMP) { + EntityPlayerMP player = (EntityPlayerMP) evt.entity; + int dimension = player.dimension; + playerDimensions.put(player, dimension); + + sendToPlayer(player, boundingBoxCacheMap.get(dimension)); + } + } + + @SubscribeEvent + public void tickEvent(TickEvent event) { + for (EntityPlayerMP player : playerDimensions.keySet()) { + + MinecraftServer mc = MinecraftServer.getServer(); + if (!mc.getConfigurationManager().playerEntityList.contains(player)) { + playerDimensions.remove(player); + } else { + int dimension = playerDimensions.get(player); + if (boundingBoxCacheMap.containsKey(dimension)) { + sendToPlayer(player, boundingBoxCacheMap.get(dimension)); + } + } + } + } + + private void sendToPlayer(EntityPlayerMP player, BoundingBoxCache boundingBoxCache) { + Map> cacheSubset = getBoundingBoxMap(player, boundingBoxCache.getBoundingBoxes()); + + int dimension = player.dimension; + if (cacheSubset.keySet().size() > 0) { + FMLLog.info("send %d entries to %s (%d)", cacheSubset.keySet().size(), player.getDisplayNameString(), dimension); + } + + for (BoundingBox key : cacheSubset.keySet()) { + Set boundingBoxes = cacheSubset.get(key); + network.sendTo(BoundingBoxMessage.from(dimension, key, boundingBoxes), player); + + if (!playerBoundingBoxesCache.containsKey(player)) { + playerBoundingBoxesCache.put(player, new HashSet()); + } + playerBoundingBoxesCache.get(player).add(key); + } + } + + private Map> getBoundingBoxMap(EntityPlayerMP player, Map> boundingBoxMap) { + Map> cacheSubset = new HashMap>(); + for (BoundingBox key : boundingBoxMap.keySet()) { + if (!playerBoundingBoxesCache.containsKey(player) || !playerBoundingBoxesCache.get(player).contains(key)) { + cacheSubset.put(key, boundingBoxMap.get(key)); + } + } + return cacheSubset; + } +} \ No newline at end of file diff --git a/resources/mcmod.info b/resources/mcmod.info new file mode 100644 index 00000000..f330abb3 --- /dev/null +++ b/resources/mcmod.info @@ -0,0 +1,17 @@ +[ +{ + "modid": "bbor", + "name": "Bounding Box Outline Reloaded", + "description": "Shows the bounding boxes of structures and features.", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "", + "updateUrl": "", + "authorList": ["irtimaled"], + "credits": "Thanks to 4poc & KaboPC.", + "logoFile": "", + "screenshots": [], + "dependencies": [] +} +] +