]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/commitdiff
Move files ready for gradle builds
authorirtimaled <irtimaled@gmail.com>
Tue, 5 Feb 2019 20:21:33 +0000 (12:21 -0800)
committerirtimaled <irtimaled@gmail.com>
Wed, 6 Feb 2019 18:34:51 +0000 (10:34 -0800)
115 files changed:
java/com/irtimaled/bbor/Logger.java [deleted file]
java/com/irtimaled/bbor/ReflectionHelper.java [deleted file]
java/com/irtimaled/bbor/client/BoundingBoxOutlineReloaded.java [deleted file]
java/com/irtimaled/bbor/client/ClientBoundingBoxProvider.java [deleted file]
java/com/irtimaled/bbor/client/ClientDimensionCache.java [deleted file]
java/com/irtimaled/bbor/client/ClientProxy.java [deleted file]
java/com/irtimaled/bbor/client/ClientRenderer.java [deleted file]
java/com/irtimaled/bbor/client/NBTFileParser.java [deleted file]
java/com/irtimaled/bbor/client/PlayerData.java [deleted file]
java/com/irtimaled/bbor/client/renderers/Renderer.java [deleted file]
java/com/irtimaled/bbor/client/renderers/SlimeChunkRenderer.java [deleted file]
java/com/irtimaled/bbor/client/renderers/StructureRenderer.java [deleted file]
java/com/irtimaled/bbor/client/renderers/VillageRenderer.java [deleted file]
java/com/irtimaled/bbor/client/renderers/WorldSpawnRenderer.java [deleted file]
java/com/irtimaled/bbor/common/BoundingBoxCache.java [deleted file]
java/com/irtimaled/bbor/common/CommonProxy.java [deleted file]
java/com/irtimaled/bbor/common/DimensionCache.java [deleted file]
java/com/irtimaled/bbor/common/DimensionProcessor.java [deleted file]
java/com/irtimaled/bbor/common/IVillageEventHandler.java [deleted file]
java/com/irtimaled/bbor/common/StructureType.java [deleted file]
java/com/irtimaled/bbor/common/VillageColorCache.java [deleted file]
java/com/irtimaled/bbor/common/VillageProcessor.java [deleted file]
java/com/irtimaled/bbor/common/models/BoundingBox.java [deleted file]
java/com/irtimaled/bbor/common/models/BoundingBoxSlimeChunk.java [deleted file]
java/com/irtimaled/bbor/common/models/BoundingBoxStructure.java [deleted file]
java/com/irtimaled/bbor/common/models/BoundingBoxVillage.java [deleted file]
java/com/irtimaled/bbor/common/models/BoundingBoxWorldSpawn.java [deleted file]
java/com/irtimaled/bbor/common/models/WorldData.java [deleted file]
java/com/irtimaled/bbor/config/ConfigManager.java [deleted file]
java/com/irtimaled/bbor/config/Configuration.java [deleted file]
java/com/irtimaled/bbor/config/Setting.java [deleted file]
java/com/irtimaled/bbor/forge/ForgeClientProxy.java [deleted file]
java/com/irtimaled/bbor/forge/ForgeCommonProxy.java [deleted file]
java/com/irtimaled/bbor/forge/ForgeMod.java [deleted file]
java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessage.java [deleted file]
java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessageHandler.java [deleted file]
java/com/irtimaled/bbor/forge/messages/BoundingBoxDeserializer.java [deleted file]
java/com/irtimaled/bbor/forge/messages/BoundingBoxSerializer.java [deleted file]
java/com/irtimaled/bbor/forge/messages/InitializeClientMessage.java [deleted file]
java/com/irtimaled/bbor/forge/messages/InitializeClientMessageHandler.java [deleted file]
java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessage.java [deleted file]
java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessageHandler.java [deleted file]
java/com/irtimaled/bbor/litemod/LiteMod.java [deleted file]
java/com/irtimaled/bbor/litemod/mixins/MixinChunk.java [deleted file]
java/com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer.java [deleted file]
java/com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer.java [deleted file]
java/com/irtimaled/bbor/litemod/mixins/MixinKeyBinding.java [deleted file]
java/com/irtimaled/bbor/litemod/mixins/MixinNetworkManager.java [deleted file]
java/com/irtimaled/bbor/litemod/mixins/MixinWorldClient.java [deleted file]
patches/net.minecraft.client.Minecraft.java.patch [deleted file]
patches/net.minecraft.client.multiplayer.WorldClient.java.patch [deleted file]
patches/net.minecraft.client.renderer.EntityRenderer.java.patch [deleted file]
patches/net.minecraft.client.settings.KeyBinding.java.patch [deleted file]
patches/net.minecraft.network.NetworkManager.java.patch [deleted file]
patches/net.minecraft.server.integrated.IntegratedServer.java.patch [deleted file]
patches/net.minecraft.world.chunk.Chunk.java.patch [deleted file]
resources/litemod.json [deleted file]
resources/mcmod.info [deleted file]
resources/mixins.bbor.json [deleted file]
resources/mixins.bbor.refmap.json [deleted file]
resources/pack.mcmeta [deleted file]
src/main/java/com/irtimaled/bbor/Logger.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/ReflectionHelper.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/BoundingBoxOutlineReloaded.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/ClientBoundingBoxProvider.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/ClientDimensionCache.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/ClientProxy.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/ClientRenderer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/NBTFileParser.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/PlayerData.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/renderers/Renderer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/renderers/SlimeChunkRenderer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/renderers/StructureRenderer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/renderers/VillageRenderer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/client/renderers/WorldSpawnRenderer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/BoundingBoxCache.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/CommonProxy.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/DimensionCache.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/DimensionProcessor.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/IVillageEventHandler.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/StructureType.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/VillageColorCache.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/VillageProcessor.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/models/BoundingBox.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/models/BoundingBoxSlimeChunk.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/models/BoundingBoxStructure.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/models/BoundingBoxVillage.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/models/BoundingBoxWorldSpawn.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/common/models/WorldData.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/config/ConfigManager.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/config/Configuration.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/config/Setting.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/forge/ForgeClientProxy.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/forge/ForgeCommonProxy.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/forge/ForgeMod.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessage.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessageHandler.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/forge/messages/BoundingBoxDeserializer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/forge/messages/BoundingBoxSerializer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/forge/messages/InitializeClientMessage.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/forge/messages/InitializeClientMessageHandler.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessage.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessageHandler.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/litemod/LiteMod.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/litemod/mixins/MixinChunk.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/litemod/mixins/MixinKeyBinding.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/litemod/mixins/MixinNetworkManager.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/litemod/mixins/MixinWorldClient.java [new file with mode: 0644]
src/main/resources/litemod.json [new file with mode: 0644]
src/main/resources/mcmod.info [new file with mode: 0644]
src/main/resources/mixins.bbor.json [new file with mode: 0644]
src/main/resources/mixins.bbor.refmap.json [new file with mode: 0644]
src/main/resources/pack.mcmeta [new file with mode: 0644]

diff --git a/java/com/irtimaled/bbor/Logger.java b/java/com/irtimaled/bbor/Logger.java
deleted file mode 100644 (file)
index d19550b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.irtimaled.bbor;
-
-import org.apache.logging.log4j.LogManager;
-
-public class Logger {
-    private static final org.apache.logging.log4j.Logger logger = LogManager.getLogger();
-
-    public static void info(String s, Object... objects) {
-        if (objects.length == 0) {
-            logger.info(s);
-        } else {
-            logger.info(String.format(s, objects));
-        }
-    }
-}
diff --git a/java/com/irtimaled/bbor/ReflectionHelper.java b/java/com/irtimaled/bbor/ReflectionHelper.java
deleted file mode 100644 (file)
index 2bd0a41..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.irtimaled.bbor;
-
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.Map;
-
-public class ReflectionHelper {
-    public static <T, R> R getPrivateValue(Class<T> sourceClass, T instance, Class<R> resultClass) {
-        try {
-            Field f = getField(sourceClass, resultClass);
-            if (f != null) {
-                return (R) f.get(instance);
-            }
-        } catch (Exception ignored) {
-        }
-        return null;
-    }
-
-    private static Map<Class, Map<Class, Field>> fieldMap = new HashMap<>();
-
-    private static <T, R> Field getField(Class<T> sourceClass, Class<R> resultClass) {
-        Map<Class, Field> map = fieldMap.computeIfAbsent(sourceClass, k -> new HashMap<>());
-        Field field = map.get(resultClass);
-        if (field == null) {
-            field = getFieldUsingReflection(sourceClass, resultClass);
-            if (field != null) {
-                field.setAccessible(true);
-                map.put(resultClass, field);
-            }
-        }
-        return field;
-    }
-
-    private static <T, R> Field getFieldUsingReflection(Class<T> sourceClass, Class<R> resultClass) {
-        Field[] fields = sourceClass.getDeclaredFields();
-        for (Field field : fields) {
-            if (field.getType().equals(resultClass))
-                return field;
-        }
-        for (Field field : fields) {
-            if (resultClass.isAssignableFrom(field.getType()))
-                return field;
-        }
-        return null;
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/BoundingBoxOutlineReloaded.java b/java/com/irtimaled/bbor/client/BoundingBoxOutlineReloaded.java
deleted file mode 100644 (file)
index 06a2603..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.irtimaled.bbor.client;
-
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.client.Minecraft;
-import net.minecraft.network.NetworkManager;
-import net.minecraft.world.World;
-import net.minecraft.world.chunk.Chunk;
-
-import java.io.File;
-
-public class BoundingBoxOutlineReloaded {
-    private static ClientProxy proxy;
-
-    public static void init() {
-        ConfigManager.loadConfig(new File(Minecraft.getMinecraft().mcDataDir, "config"));
-        proxy = new ClientProxy();
-        proxy.init();
-    }
-
-    public static void chunkLoaded(Chunk chunk) {
-        proxy.chunkLoaded(chunk);
-    }
-
-    public static void worldLoaded(World world) {
-        proxy.worldLoaded(world);
-    }
-
-    public static void keyPressed() {
-        proxy.keyPressed();
-    }
-
-    public static void render(float partialTicks) {
-        proxy.tick();
-        proxy.render(partialTicks);
-    }
-
-    public static void playerConnectedToServer(NetworkManager networkManager) {
-        proxy.playerConnectedToServer(networkManager);
-    }
-
-    public static void playerDisconnectedFromServer() {
-        proxy.playerDisconnectedFromServer();
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/ClientBoundingBoxProvider.java b/java/com/irtimaled/bbor/client/ClientBoundingBoxProvider.java
deleted file mode 100644 (file)
index 423df09..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-package com.irtimaled.bbor.client;
-
-import com.irtimaled.bbor.common.BoundingBoxCache;
-import com.irtimaled.bbor.common.models.BoundingBox;
-import com.irtimaled.bbor.common.models.BoundingBoxSlimeChunk;
-import com.irtimaled.bbor.common.models.BoundingBoxWorldSpawn;
-import com.irtimaled.bbor.common.models.WorldData;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.multiplayer.WorldClient;
-import net.minecraft.util.math.BlockPos;
-import net.minecraft.util.math.ChunkPos;
-import net.minecraft.util.math.MathHelper;
-import net.minecraft.world.DimensionType;
-
-import java.awt.*;
-import java.util.HashSet;
-import java.util.Random;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-class ClientBoundingBoxProvider {
-    private final ClientDimensionCache dimensionCache;
-
-    ClientBoundingBoxProvider(ClientDimensionCache dimensionCache) {
-        this.dimensionCache = dimensionCache;
-    }
-
-    Set<BoundingBox> getBoundingBoxes(DimensionType dimensionType, Boolean outerBoxOnly, WorldClient world) {
-        Set<BoundingBox> boundingBoxes = getClientBoundingBoxes(dimensionType);
-        BoundingBoxCache boundingBoxCache = dimensionCache.getBoundingBoxes(dimensionType);
-        if (boundingBoxCache != null) {
-            if (outerBoxOnly) {
-                boundingBoxes.addAll(boundingBoxCache.getBoundingBoxes().keySet());
-            } else {
-                boundingBoxCache.getBoundingBoxes()
-                        .values()
-                        .forEach(boundingBoxes::addAll);
-            }
-        }
-
-        return boundingBoxes.stream()
-                .filter(bb -> world.isAreaLoaded(bb.getMinBlockPos(), bb.getMaxBlockPos()))
-                .collect(Collectors.toSet());
-    }
-
-    private Set<BoundingBox> getClientBoundingBoxes(DimensionType dimensionType) {
-        WorldData worldData = dimensionCache.getWorldData();
-
-        Set<BoundingBox> boundingBoxes = new HashSet<>();
-        if (worldData != null && dimensionType == DimensionType.OVERWORLD) {
-            if (ConfigManager.drawWorldSpawn.getBoolean()) {
-                boundingBoxes.add(getWorldSpawnBoundingBox(worldData.getSpawnX(), worldData.getSpawnZ()));
-                boundingBoxes.add(buildSpawnChunksBoundingBox(worldData.getSpawnX(), worldData.getSpawnZ()));
-            }
-            if (ConfigManager.drawLazySpawnChunks.getBoolean()) {
-                boundingBoxes.add(getLazySpawnChunksBoundingBox(worldData.getSpawnX(), worldData.getSpawnZ()));
-            }
-            if (ConfigManager.drawSlimeChunks.getBoolean()) {
-                boundingBoxes.addAll(this.getSlimeChunks());
-            }
-        }
-        return boundingBoxes;
-    }
-
-    private Set<BoundingBoxSlimeChunk> getSlimeChunks() {
-        Minecraft minecraft = Minecraft.getMinecraft();
-        int renderDistanceChunks = minecraft.gameSettings.renderDistanceChunks;
-        int playerChunkX = MathHelper.floor(minecraft.player.posX / 16.0D);
-        int playerChunkZ = MathHelper.floor(minecraft.player.posZ / 16.0D);
-        Set<BoundingBoxSlimeChunk> slimeChunks = new HashSet<>();
-        for (int chunkX = playerChunkX - renderDistanceChunks; chunkX <= playerChunkX + renderDistanceChunks; ++chunkX) {
-            for (int chunkZ = playerChunkZ - renderDistanceChunks; chunkZ <= playerChunkZ + renderDistanceChunks; ++chunkZ) {
-                if (isSlimeChunk(chunkX, chunkZ)) {
-                    ChunkPos chunk = new ChunkPos(chunkX, chunkZ);
-                    BlockPos minBlockPos = new BlockPos(chunk.getXStart(), 1, chunk.getZStart());
-                    BlockPos maxBlockPos = new BlockPos(chunk.getXEnd(), 38, chunk.getZEnd());
-                    if (minecraft.world.isAreaLoaded(minBlockPos, maxBlockPos)) {
-                        slimeChunks.add(BoundingBoxSlimeChunk.from(minBlockPos, maxBlockPos, Color.GREEN));
-                    }
-                }
-            }
-        }
-        return slimeChunks;
-    }
-
-    private boolean isSlimeChunk(int chunkX, int chunkZ) {
-        WorldData worldData = dimensionCache.getWorldData();
-        Random r = new Random(worldData.getSeed() +
-                (long) (chunkX * chunkX * 4987142) +
-                (long) (chunkX * 5947611) +
-                (long) (chunkZ * chunkZ) * 4392871L +
-                (long) (chunkZ * 389711) ^ 987234911L);
-        return r.nextInt(10) == 0;
-    }
-
-    private BoundingBox buildSpawnChunksBoundingBox(int spawnX, int spawnZ) {
-        return dimensionCache.getOrSetSpawnChunks(() -> buildSpawnChunksBoundingBox(spawnX, spawnZ, 12));
-    }
-
-    private BoundingBox getLazySpawnChunksBoundingBox(int spawnX, int spawnZ) {
-        return dimensionCache.getOrSetLazySpawnChunks(() -> buildSpawnChunksBoundingBox(spawnX, spawnZ, 16));
-    }
-
-    private BoundingBox buildSpawnChunksBoundingBox(int spawnX, int spawnZ, int size) {
-        double chunkSize = 16;
-        double midOffset = chunkSize * (size / 2);
-        double midX = Math.round((float) (spawnX / chunkSize)) * chunkSize;
-        double midZ = Math.round((float) (spawnZ / chunkSize)) * chunkSize;
-        BlockPos minBlockPos = new BlockPos(midX - midOffset, 0, midZ - midOffset);
-        if (spawnX / chunkSize % 0.5D == 0.0D && spawnZ / chunkSize % 0.5D == 0.0D) {
-            midX += chunkSize;
-            midZ += chunkSize;
-        }
-        BlockPos maxBlockPos = new BlockPos(midX + midOffset, 0, midZ + midOffset);
-        return BoundingBoxWorldSpawn.from(minBlockPos, maxBlockPos, Color.RED);
-    }
-
-    private BoundingBox getWorldSpawnBoundingBox(int spawnX, int spawnZ) {
-        return dimensionCache.getOrSetWorldSpawn(() -> buildWorldSpawnBoundingBox(spawnX, spawnZ));
-    }
-
-    private BoundingBox buildWorldSpawnBoundingBox(int spawnX, int spawnZ) {
-        BlockPos minBlockPos = new BlockPos(spawnX - 10, 0, spawnZ - 10);
-        BlockPos maxBlockPos = new BlockPos(spawnX + 10, 0, spawnZ + 10);
-
-        return BoundingBoxWorldSpawn.from(minBlockPos, maxBlockPos, Color.RED);
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/ClientDimensionCache.java b/java/com/irtimaled/bbor/client/ClientDimensionCache.java
deleted file mode 100644 (file)
index df7ec18..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.irtimaled.bbor.client;
-
-import com.irtimaled.bbor.common.DimensionCache;
-import com.irtimaled.bbor.common.models.BoundingBox;
-
-import java.util.function.Supplier;
-
-public class ClientDimensionCache extends DimensionCache {
-    private BoundingBox worldSpawnBoundingBox;
-    private BoundingBox spawnChunksBoundingBox;
-    private BoundingBox lazySpawnChunksBoundingBox;
-
-    @Override
-    public void setWorldData(long seed, int spawnX, int spawnZ) {
-        clearClientCache();
-        super.setWorldData(seed, spawnX, spawnZ);
-    }
-
-    @Override
-    public void clear() {
-        clearClientCache();
-        super.clear();
-    }
-
-    private void clearClientCache() {
-        worldSpawnBoundingBox = null;
-        spawnChunksBoundingBox = null;
-        lazySpawnChunksBoundingBox = null;
-    }
-
-    BoundingBox getOrSetSpawnChunks(Supplier<BoundingBox> defaultSupplier) {
-        if(spawnChunksBoundingBox == null) {
-            spawnChunksBoundingBox = defaultSupplier.get();
-        }
-        return spawnChunksBoundingBox;
-    }
-
-    BoundingBox getOrSetLazySpawnChunks(Supplier<BoundingBox> defaultSupplier) {
-        if(lazySpawnChunksBoundingBox == null) {
-            lazySpawnChunksBoundingBox = defaultSupplier.get();
-        }
-        return lazySpawnChunksBoundingBox;
-    }
-
-    BoundingBox getOrSetWorldSpawn(Supplier<BoundingBox> defaultSupplier) {
-        if(worldSpawnBoundingBox == null) {
-            worldSpawnBoundingBox = defaultSupplier.get();
-        }
-        return worldSpawnBoundingBox;
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/ClientProxy.java b/java/com/irtimaled/bbor/client/ClientProxy.java
deleted file mode 100644 (file)
index 22eb4ff..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.irtimaled.bbor.client;
-
-import com.irtimaled.bbor.common.CommonProxy;
-import com.irtimaled.bbor.common.VillageColorCache;
-import com.irtimaled.bbor.common.VillageProcessor;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.settings.KeyBinding;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.network.NetworkManager;
-import net.minecraft.world.DimensionType;
-import org.apache.commons.lang3.ArrayUtils;
-import org.lwjgl.input.Keyboard;
-
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-
-public class ClientProxy extends CommonProxy {
-    private boolean active;
-    private boolean outerBoxOnly;
-    private KeyBinding activeHotKey;
-    private KeyBinding outerBoxOnlyHotKey;
-    private ClientRenderer renderer;
-    private int remoteUserCount = 0;
-
-    public void keyPressed() {
-        if (activeHotKey.isPressed()) {
-            active = !active;
-            if (active)
-                PlayerData.setActiveY();
-        } else if (outerBoxOnlyHotKey.isPressed()) {
-            outerBoxOnly = !outerBoxOnly;
-        }
-    }
-
-    @Override
-    public void init() {
-        String category = "Bounding Box Outline Reloaded";
-        activeHotKey = new KeyBinding("Toggle On/Off", Keyboard.KEY_B, category);
-        outerBoxOnlyHotKey = new KeyBinding("Toggle Display Outer Box Only", Keyboard.KEY_O, category);
-        Minecraft.getMinecraft().gameSettings.keyBindings = ArrayUtils.addAll(Minecraft.getMinecraft().gameSettings.keyBindings, activeHotKey, outerBoxOnlyHotKey);
-        ClientDimensionCache clientDimensionCache = new ClientDimensionCache();
-        renderer = new ClientRenderer(clientDimensionCache);
-        dimensionCache = clientDimensionCache;
-    }
-
-    public void render(float partialTicks) {
-        EntityPlayer entityPlayer = Minecraft.getMinecraft().player;
-        PlayerData.setPlayerPosition(partialTicks, entityPlayer);
-
-        if (this.active) {
-            renderer.render(DimensionType.getById(entityPlayer.dimension), outerBoxOnly);
-        }
-    }
-
-    public void setRemoteUserCount(int remoteUserCount) {
-        this.remoteUserCount = remoteUserCount;
-    }
-
-    protected boolean hasRemoteUsers()    {
-        return remoteUserCount > 0;
-    }
-
-    @Override
-    public void tick() {
-        if (this.active || this.hasRemoteUsers()) {
-            super.tick();
-        }
-    }
-
-    public void playerConnectedToServer(NetworkManager networkManager) {
-        SocketAddress remoteAddress = networkManager.getRemoteAddress();
-        if (remoteAddress instanceof InetSocketAddress) {
-            InetSocketAddress socketAddress = (InetSocketAddress) remoteAddress;
-            NBTFileParser.loadLocalDatFiles(socketAddress.getHostName(), socketAddress.getPort(), dimensionCache);
-        }
-    }
-
-    public void playerDisconnectedFromServer() {
-        active = false;
-        villageProcessors.forEach(VillageProcessor::close);
-        villageProcessors.clear();
-
-        if (ConfigManager.keepCacheBetweenSessions.getBoolean()) return;
-        VillageColorCache.clear();
-        dimensionCache.clear();
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/ClientRenderer.java b/java/com/irtimaled/bbor/client/ClientRenderer.java
deleted file mode 100644 (file)
index 697c26b..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.irtimaled.bbor.client;
-
-import com.irtimaled.bbor.client.renderers.*;
-import com.irtimaled.bbor.common.models.*;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.client.Minecraft;
-import net.minecraft.world.DimensionType;
-import org.lwjgl.opengl.GL11;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-public class ClientRenderer {
-    private final ClientBoundingBoxProvider clientBoundingBoxProvider;
-    private static final Map<Class<? extends BoundingBox>, Renderer> boundingBoxRendererMap = new HashMap<>();
-
-    ClientRenderer(ClientDimensionCache dimensionCache) {
-        this.clientBoundingBoxProvider = new ClientBoundingBoxProvider(dimensionCache);
-        boundingBoxRendererMap.put(BoundingBoxVillage.class, new VillageRenderer());
-        boundingBoxRendererMap.put(BoundingBoxSlimeChunk.class, new SlimeChunkRenderer());
-        boundingBoxRendererMap.put(BoundingBoxWorldSpawn.class, new WorldSpawnRenderer());
-        boundingBoxRendererMap.put(BoundingBoxStructure.class, new StructureRenderer());
-    }
-
-    public void render(DimensionType dimensionType, Boolean outerBoxesOnly) {
-        Set<BoundingBox> boundingBoxes = clientBoundingBoxProvider.getBoundingBoxes(dimensionType, outerBoxesOnly, Minecraft.getMinecraft().world);
-        if (boundingBoxes == null || boundingBoxes.size() == 0)
-            return;
-
-        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-        GL11.glLineWidth(2.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 : boundingBoxes) {
-            Renderer renderer = boundingBoxRendererMap.get(bb.getClass());
-            if (renderer != null) {
-                renderer.render(bb);
-            }
-        }
-
-        GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
-        GL11.glEnable(GL11.GL_CULL_FACE);
-        GL11.glEnable(GL11.GL_TEXTURE_2D);
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/NBTFileParser.java b/java/com/irtimaled/bbor/client/NBTFileParser.java
deleted file mode 100644 (file)
index f647d9c..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-package com.irtimaled.bbor.client;
-
-import com.irtimaled.bbor.Logger;
-import com.irtimaled.bbor.common.BoundingBoxCache;
-import com.irtimaled.bbor.common.DimensionCache;
-import com.irtimaled.bbor.common.StructureType;
-import com.irtimaled.bbor.common.models.BoundingBox;
-import com.irtimaled.bbor.common.models.BoundingBoxStructure;
-import com.irtimaled.bbor.common.models.BoundingBoxVillage;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.nbt.CompressedStreamTools;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.nbt.NBTTagList;
-import net.minecraft.util.math.BlockPos;
-import net.minecraft.world.DimensionType;
-
-import java.awt.*;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-
-class NBTFileParser {
-    static void loadLocalDatFiles(String host, int port, DimensionCache dimensionCache) {
-        Logger.info("Looking for local structures (host:port=%s:%d)", host, port);
-        String path = String.format("BBOutlineReloaded%s%s%s%d", File.separator, host, File.separator, port);
-        File localStructuresFolder = new File(ConfigManager.configDir, path);
-        Logger.info("Looking for local structures (folder=%s)", localStructuresFolder.getAbsolutePath());
-        if (!localStructuresFolder.exists()) {
-            path = String.format("BBOutlineReloaded%s%s", File.separator, host);
-            localStructuresFolder = new File(ConfigManager.configDir, path);
-            Logger.info("Looking for local structures (folder=%s)", localStructuresFolder.getAbsolutePath());
-        }
-        if (!localStructuresFolder.exists()) {
-            path = String.format("BBOutlineReloaded%s%s,%d", File.separator, host, port);
-            localStructuresFolder = new File(ConfigManager.configDir, path);
-            Logger.info("Looking for local structures (folder=%s)", localStructuresFolder.getAbsolutePath());
-        }
-        if (!localStructuresFolder.exists()) {
-            Logger.info("No local structures folders found");
-            return;
-        }
-        loadWorldData(localStructuresFolder, dimensionCache);
-        populateBoundingBoxCache(localStructuresFolder, dimensionCache);
-    }
-
-    private static void loadWorldData(File localStructuresFolder, DimensionCache dimensionCache) {
-        File file = new File(localStructuresFolder, "level.dat");
-        NBTTagCompound nbt = loadNbtFile(file);
-        if (nbt == null)
-            return;
-
-        NBTTagCompound data = nbt.getCompoundTag("Data");
-        long seed = data.getLong("RandomSeed");
-        int spawnX = data.getInteger("SpawnX");
-        int spawnZ = data.getInteger("SpawnZ");
-        Logger.info("Loaded level.dat (seed: %d, spawn: %d,%d)", seed, spawnX, spawnZ);
-        dimensionCache.setWorldData(seed, spawnX, spawnZ);
-    }
-
-    private static void populateBoundingBoxCache(File localStructuresFolder, DimensionCache dimensionCache) {
-        dimensionCache.put(DimensionType.OVERWORLD, loadOverworldStructures(localStructuresFolder));
-        dimensionCache.put(DimensionType.NETHER, loadNetherStructures(localStructuresFolder));
-        dimensionCache.put(DimensionType.THE_END, loadEndStructures(localStructuresFolder));
-    }
-
-    private static BoundingBoxCache loadOverworldStructures(File localStructuresFolder) {
-        BoundingBoxCache cache = new BoundingBoxCache();
-        if (ConfigManager.drawDesertTemples.getBoolean()) {
-            loadStructure(localStructuresFolder, cache, "Temple.dat", StructureType.DesertTemple.getColor(), "TeDP");
-        }
-        if (ConfigManager.drawJungleTemples.getBoolean()) {
-            loadStructure(localStructuresFolder, cache, "Temple.dat", StructureType.JungleTemple.getColor(), "TeJP");
-        }
-        if (ConfigManager.drawWitchHuts.getBoolean()) {
-            loadStructure(localStructuresFolder, cache, "Temple.dat", StructureType.WitchHut.getColor(), "TeSH");
-        }
-        if (ConfigManager.drawOceanMonuments.getBoolean()) {
-            loadStructure(localStructuresFolder, cache, "Monument.dat", StructureType.OceanMonument.getColor(), "*");
-        }
-        if (ConfigManager.drawStrongholds.getBoolean()) {
-            loadStructure(localStructuresFolder, cache, "Stronghold.dat", StructureType.Stronghold.getColor(), "*");
-        }
-        if (ConfigManager.drawMansions.getBoolean()) {
-            loadStructure(localStructuresFolder, cache, "Mansion.dat", StructureType.Mansion.getColor(), "*");
-        }
-        if (ConfigManager.drawMineShafts.getBoolean()) {
-            loadStructure(localStructuresFolder, cache, "Mineshaft.dat", StructureType.MineShaft.getColor(), "*");
-        }
-        if (ConfigManager.drawVillages.getBoolean()) {
-            loadVillages(localStructuresFolder, cache, "Villages.dat");
-        }
-        return cache;
-    }
-
-    private static BoundingBoxCache loadNetherStructures(File localStructuresFolder) {
-        BoundingBoxCache cache = new BoundingBoxCache();
-        if (ConfigManager.drawNetherFortresses.getBoolean())
-            loadStructure(localStructuresFolder, cache, "Fortress.dat", StructureType.NetherFortress.getColor(), "*");
-        if (ConfigManager.drawVillages.getBoolean()) {
-            loadVillages(localStructuresFolder, cache, "villages_nether.dat");
-        }
-        return cache;
-    }
-
-    private static BoundingBoxCache loadEndStructures(File localStructuresFolder) {
-        BoundingBoxCache cache = new BoundingBoxCache();
-        if (ConfigManager.drawVillages.getBoolean()) {
-            loadVillages(localStructuresFolder, cache, "Villages_end.dat");
-        }
-        if (ConfigManager.drawEndCities.getBoolean()) {
-            loadStructure(localStructuresFolder, cache, "EndCity.dat", StructureType.EndCity.getColor(), "*");
-        }
-        return cache;
-    }
-
-    private static void loadStructure(File localStructuresFolder, BoundingBoxCache cache, String fileName, Color color, String id) {
-        File file = new File(localStructuresFolder, fileName);
-        NBTTagCompound nbt = loadNbtFile(file);
-        if (nbt == null)
-            return;
-
-        NBTTagCompound features = nbt.getCompoundTag("data")
-                .getCompoundTag("Features");
-        int loadedStructureCount = 0;
-        for (Object key : features.getKeySet()) {
-            NBTTagCompound feature = features.getCompoundTag((String) key);
-            BoundingBox structure = BoundingBoxStructure.from(feature.getIntArray("BB"), color);
-            Set<BoundingBox> boundingBoxes = new HashSet<>();
-            NBTTagCompound[] children = getChildCompoundTags(feature, "Children");
-            for (NBTTagCompound child : children) {
-                if (id.equals(child.getString("id")) || id.equals("*"))
-                    boundingBoxes.add(BoundingBoxStructure.from(child.getIntArray("BB"), color));
-            }
-            if (boundingBoxes.size() > 0)
-                ++loadedStructureCount;
-            cache.addBoundingBoxes(structure, boundingBoxes);
-        }
-
-        Logger.info("Loaded %s (%d structures with type %s)", fileName, loadedStructureCount, id);
-    }
-
-    private static void loadVillages(File localStructuresFolder, BoundingBoxCache cache, String fileName) {
-        File file = new File(localStructuresFolder, fileName);
-        NBTTagCompound nbt = loadNbtFile(file);
-        if (nbt == null)
-            return;
-
-        NBTTagCompound[] villages = getChildCompoundTags(nbt.getCompoundTag("data"), "Villages");
-        for (NBTTagCompound village : villages) {
-            BlockPos center = new BlockPos(village.getInteger("CX"), village.getInteger("CY"), village.getInteger("CZ"));
-            int radius = village.getInteger("Radius");
-            int population = village.getInteger("PopSize");
-            Set<BlockPos> doors = getDoors(village);
-            BoundingBox boundingBox = BoundingBoxVillage.from(center, radius, village.hashCode(), population, doors);
-            cache.addBoundingBox(boundingBox);
-        }
-
-        Logger.info("Loaded %s (%d villages)", fileName, villages.length);
-    }
-
-    private static Set<BlockPos> getDoors(NBTTagCompound village) {
-        Set<BlockPos> doors = new HashSet<>();
-        for (NBTTagCompound door : getChildCompoundTags(village, "Doors")) {
-            doors.add(new BlockPos(door.getInteger("X"), door.getInteger("Y"), door.getInteger("Z")));
-        }
-        return doors;
-    }
-
-    private static NBTTagCompound loadNbtFile(File file) {
-        if (!file.exists())
-            return null;
-        try {
-            return CompressedStreamTools.readCompressed(new FileInputStream(file));
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    private static NBTTagCompound[] getChildCompoundTags(NBTTagCompound parent, String key) {
-        NBTTagList tagList = parent.getTagList(key, 10);
-        NBTTagCompound[] result = new NBTTagCompound[tagList.tagCount()];
-        for (int index = 0; index < tagList.tagCount(); index++) {
-            result[index] = tagList.getCompoundTagAt(index);
-        }
-        return result;
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/PlayerData.java b/java/com/irtimaled/bbor/client/PlayerData.java
deleted file mode 100644 (file)
index 339d81c..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.irtimaled.bbor.client;
-
-import net.minecraft.entity.player.EntityPlayer;
-
-public class PlayerData {
-    private static double x;
-    private static double y;
-    private static double z;
-    private static double activeY;
-
-    static void setPlayerPosition(double partialTicks, EntityPlayer entityPlayer) {
-        x = entityPlayer.lastTickPosX + (entityPlayer.posX - entityPlayer.lastTickPosX) * partialTicks;
-        y = entityPlayer.lastTickPosY + (entityPlayer.posY - entityPlayer.lastTickPosY) * partialTicks;
-        z = entityPlayer.lastTickPosZ + (entityPlayer.posZ - entityPlayer.lastTickPosZ) * partialTicks;
-    }
-
-    static void setActiveY() {
-        activeY = y;
-    }
-
-    public static double getX() {
-        return x;
-    }
-
-    public static double getY() {
-        return y;
-    }
-
-    public static double getZ() {
-        return z;
-    }
-
-    public static double getMaxY(double configMaxY) {
-        if (configMaxY == -1) {
-            return activeY;
-        } else if ((configMaxY == 0) || (y < configMaxY)) {
-            return y;
-        }
-        return configMaxY;
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/renderers/Renderer.java b/java/com/irtimaled/bbor/client/renderers/Renderer.java
deleted file mode 100644 (file)
index 850c800..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-package com.irtimaled.bbor.client.renderers;
-
-import com.irtimaled.bbor.client.PlayerData;
-import com.irtimaled.bbor.common.models.BoundingBox;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.client.renderer.BufferBuilder;
-import net.minecraft.client.renderer.Tessellator;
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
-import net.minecraft.util.math.AxisAlignedBB;
-import org.lwjgl.opengl.GL11;
-
-import java.awt.*;
-
-public abstract class Renderer<T extends BoundingBox> {
-    public abstract void render(T boundingBox);
-
-    void renderBoundingBox(T boundingBox) {
-        renderCuboid(boundingBox.toAxisAlignedBB(), boundingBox.getColor(), fill());
-    }
-
-    boolean fill() {
-        return ConfigManager.fill.getBoolean();
-    }
-
-    void renderRectangle(AxisAlignedBB aaBB, double minY, double maxY, Color color, Boolean fill) {
-        aaBB = new AxisAlignedBB(aaBB.minX, minY, aaBB.minZ, aaBB.maxX, maxY, aaBB.maxZ);
-        renderCuboid(aaBB, color, fill);
-    }
-
-    void renderCuboid(AxisAlignedBB aaBB, Color color, boolean fill) {
-        aaBB = offsetAxisAlignedBB(aaBB);
-        if (fill) {
-            renderFilledCuboid(aaBB, color);
-        }
-        renderUnfilledCuboid(aaBB, color);
-    }
-
-    private AxisAlignedBB offsetAxisAlignedBB(AxisAlignedBB axisAlignedBB) {
-        double growXZ = 0.001F;
-        double growY = 0;
-        if (axisAlignedBB.minY != axisAlignedBB.maxY) {
-            growY = growXZ;
-        }
-        return axisAlignedBB
-                .grow(growXZ, growY, growXZ)
-                .offset(-PlayerData.getX(), -PlayerData.getY(), -PlayerData.getZ());
-    }
-
-    private void renderFilledCuboid(AxisAlignedBB aaBB, Color color) {
-        GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
-        GL11.glEnable(GL11.GL_BLEND);
-        renderCuboid(aaBB, 30, color);
-        GL11.glDisable(GL11.GL_BLEND);
-        GL11.glEnable(GL11.GL_POLYGON_OFFSET_LINE);
-        GL11.glPolygonOffset(-1.f, -1.f);
-    }
-
-    private void renderUnfilledCuboid(AxisAlignedBB aaBB, Color color) {
-        GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
-        renderCuboid(aaBB, 255, color);
-    }
-
-    private void renderCuboid(AxisAlignedBB bb, int alphaChannel, Color color) {
-        Tessellator tessellator = Tessellator.getInstance();
-        BufferBuilder worldRenderer = tessellator.getBuffer();
-
-        int colorR = color.getRed();
-        int colorG = color.getGreen();
-        int colorB = color.getBlue();
-
-        worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
-        worldRenderer.pos(bb.minX, bb.minY, bb.minZ)
-                .color(colorR, colorG, colorB, alphaChannel)
-                .endVertex();
-        worldRenderer.pos(bb.maxX, bb.minY, bb.minZ)
-                .color(colorR, colorG, colorB, alphaChannel)
-                .endVertex();
-        worldRenderer.pos(bb.maxX, bb.minY, bb.maxZ)
-                .color(colorR, colorG, colorB, alphaChannel)
-                .endVertex();
-        worldRenderer.pos(bb.minX, bb.minY, bb.maxZ)
-                .color(colorR, colorG, colorB, alphaChannel)
-                .endVertex();
-
-        if (bb.minY != bb.maxY) {
-
-            worldRenderer.pos(bb.minX, bb.maxY, bb.minZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.maxX, bb.maxY, bb.minZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.maxX, bb.maxY, bb.maxZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.minX, bb.maxY, bb.maxZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-
-            worldRenderer.pos(bb.minX, bb.minY, bb.maxZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.minX, bb.maxY, bb.maxZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.maxX, bb.maxY, bb.maxZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.maxX, bb.minY, bb.maxZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-
-            worldRenderer.pos(bb.minX, bb.minY, bb.minZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.minX, bb.maxY, bb.minZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.maxX, bb.maxY, bb.minZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.maxX, bb.minY, bb.minZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-
-            worldRenderer.pos(bb.minX, bb.minY, bb.minZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.minX, bb.minY, bb.maxZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.minX, bb.maxY, bb.maxZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.minX, bb.maxY, bb.minZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-
-            worldRenderer.pos(bb.maxX, bb.minY, bb.minZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.maxX, bb.minY, bb.maxZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.maxX, bb.maxY, bb.maxZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-            worldRenderer.pos(bb.maxX, bb.maxY, bb.minZ)
-                    .color(colorR, colorG, colorB, alphaChannel)
-                    .endVertex();
-        }
-        tessellator.draw();
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/renderers/SlimeChunkRenderer.java b/java/com/irtimaled/bbor/client/renderers/SlimeChunkRenderer.java
deleted file mode 100644 (file)
index 1ba3765..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.irtimaled.bbor.client.renderers;
-
-import com.irtimaled.bbor.common.models.BoundingBoxSlimeChunk;
-import com.irtimaled.bbor.client.PlayerData;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.util.math.AxisAlignedBB;
-
-import java.awt.*;
-
-public class SlimeChunkRenderer extends Renderer<BoundingBoxSlimeChunk> {
-    @Override
-    public void render(BoundingBoxSlimeChunk boundingBox) {
-        AxisAlignedBB aaBB = boundingBox.toAxisAlignedBB();
-        Color color = boundingBox.getColor();
-        renderCuboid(aaBB, color, fill());
-
-        double maxY = PlayerData.getMaxY(ConfigManager.slimeChunkMaxY.getInt());
-        if (maxY > 39) {
-            renderRectangle(aaBB, 39, maxY, color, fill());
-        }
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/renderers/StructureRenderer.java b/java/com/irtimaled/bbor/client/renderers/StructureRenderer.java
deleted file mode 100644 (file)
index e98cec8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.irtimaled.bbor.client.renderers;
-
-import com.irtimaled.bbor.common.models.BoundingBoxStructure;
-
-public class StructureRenderer extends Renderer<BoundingBoxStructure> {
-    @Override
-    public void render(BoundingBoxStructure boundingBox) {
-        renderBoundingBox(boundingBox);
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/renderers/VillageRenderer.java b/java/com/irtimaled/bbor/client/renderers/VillageRenderer.java
deleted file mode 100644 (file)
index d5bee1f..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-package com.irtimaled.bbor.client.renderers;
-
-import com.irtimaled.bbor.common.models.BoundingBoxVillage;
-import com.irtimaled.bbor.client.PlayerData;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.client.renderer.BufferBuilder;
-import net.minecraft.client.renderer.Tessellator;
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
-import net.minecraft.util.math.AxisAlignedBB;
-import net.minecraft.util.math.BlockPos;
-import org.lwjgl.opengl.GL11;
-
-import java.awt.*;
-import java.util.HashSet;
-import java.util.Set;
-
-public class VillageRenderer extends Renderer<BoundingBoxVillage> {
-    @Override
-    public void render(BoundingBoxVillage boundingBox) {
-        if (ConfigManager.renderVillageAsSphere.getBoolean()) {
-            renderBoundingBoxVillageAsSphere(boundingBox);
-        } else {
-            renderBoundingBox(boundingBox);
-        }
-        if (ConfigManager.drawIronGolemSpawnArea.getBoolean() &&
-                boundingBox.getSpawnsIronGolems()) {
-            renderIronGolemSpawnArea(boundingBox);
-        }
-        if (ConfigManager.drawVillageDoors.getBoolean()) {
-            renderVillageDoors(boundingBox);
-        }
-    }
-
-    private void renderIronGolemSpawnArea(BoundingBoxVillage boundingBox) {
-        BlockPos center = boundingBox.getCenter();
-        AxisAlignedBB abb = new AxisAlignedBB(new BlockPos(center.getX() - 8,
-                center.getY() - 3,
-                center.getZ() - 8),
-                new BlockPos(center.getX() + 8,
-                        center.getY() + 3,
-                        center.getZ() + 8))
-                .offset(boundingBox.getCenterOffsetX(), 0.0, boundingBox.getCenterOffsetZ());
-
-        renderCuboid(abb, boundingBox.getColor(), false);
-    }
-
-    private void renderVillageDoors(BoundingBoxVillage boundingBox) {
-        OffsetPoint center = new OffsetPoint(boundingBox.getCenter())
-                .add(boundingBox.getCenterOffsetX(), 0.0, boundingBox.getCenterOffsetZ());
-        Color color = boundingBox.getColor();
-        GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
-        Tessellator tessellator = Tessellator.getInstance();
-        BufferBuilder worldRenderer = tessellator.getBuffer();
-
-        int colorR = color.getRed();
-        int colorG = color.getGreen();
-        int colorB = color.getBlue();
-
-        worldRenderer.begin(GL11.GL_LINES, worldRenderer.getVertexFormat());
-        for (BlockPos door : boundingBox.getDoors()) {
-            OffsetPoint point = new OffsetPoint(door).add(0.5, 0, 0.5);
-
-            worldRenderer.pos(point.getX(), point.getY(), point.getZ()).color(colorR, colorG, colorB, 255).endVertex();
-            worldRenderer.pos(center.getX(), center.getY(), center.getZ()).color(colorR, colorG, colorB, 255).endVertex();
-        }
-        tessellator.draw();
-    }
-
-    private void renderBoundingBoxVillageAsSphere(BoundingBoxVillage boundingBox) {
-        OffsetPoint center = new OffsetPoint(boundingBox.getCenter())
-                .add(boundingBox.getCenterOffsetX(), 0.0, boundingBox.getCenterOffsetZ());
-        int radius = boundingBox.getRadius();
-        Color color = boundingBox.getColor();
-        renderSphere(center, radius, color);
-    }
-
-    private void renderSphere(OffsetPoint center, double radius, Color color) {
-        GL11.glEnable(GL11.GL_POINT_SMOOTH);
-        GL11.glPointSize(2f);
-
-        Tessellator tessellator = Tessellator.getInstance();
-        BufferBuilder worldRenderer = tessellator.getBuffer();
-        worldRenderer.begin(GL11.GL_POINTS, DefaultVertexFormats.POSITION_COLOR);
-        for (OffsetPoint point : buildPoints(center, radius)) {
-            worldRenderer.pos(point.getX(), point.getY(), point.getZ())
-                    .color(color.getRed(), color.getGreen(), color.getBlue(), 255)
-                    .endVertex();
-        }
-        tessellator.draw();
-    }
-
-    private class OffsetPoint {
-        private final double x;
-        private final double y;
-        private final double z;
-
-        OffsetPoint(double x, double y, double z) {
-            this.x = x;
-            this.y = y;
-            this.z = z;
-        }
-
-        OffsetPoint(BlockPos blockPos) {
-            this.x = blockPos.getX();
-            this.y = blockPos.getY();
-            this.z = blockPos.getZ();
-        }
-
-        double getX() {
-            return x - PlayerData.getX();
-        }
-
-        double getY() {
-            return y - PlayerData.getY();
-        }
-
-        double getZ() {
-            return z - PlayerData.getZ();
-        }
-
-        public OffsetPoint add(double x, double y, double z) {
-            return new OffsetPoint(this.x + x, this.y + y, this.z + z);
-        }
-    }
-
-    private Set<OffsetPoint> buildPoints(OffsetPoint center, double radius) {
-        Set<OffsetPoint> points = new HashSet<>(1200);
-
-        double tau = 6.283185307179586D;
-        double pi = tau / 2D;
-        double segment = tau / 48D;
-
-        for (double t = 0.0D; t < tau; t += segment)
-            for (double theta = 0.0D; theta < pi; theta += segment) {
-                double dx = radius * Math.sin(t) * Math.cos(theta);
-                double dz = radius * Math.sin(t) * Math.sin(theta);
-                double dy = radius * Math.cos(t);
-
-                points.add(center.add(dx, dy, dz));
-            }
-        return points;
-    }
-}
diff --git a/java/com/irtimaled/bbor/client/renderers/WorldSpawnRenderer.java b/java/com/irtimaled/bbor/client/renderers/WorldSpawnRenderer.java
deleted file mode 100644 (file)
index 98ac02d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.irtimaled.bbor.client.renderers;
-
-import com.irtimaled.bbor.common.models.BoundingBoxWorldSpawn;
-import com.irtimaled.bbor.client.PlayerData;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.util.math.AxisAlignedBB;
-
-import java.awt.*;
-
-public class WorldSpawnRenderer extends Renderer<BoundingBoxWorldSpawn> {
-    @Override
-    public void render(BoundingBoxWorldSpawn boundingBox) {
-        AxisAlignedBB aaBB = boundingBox.toAxisAlignedBB(false);
-        Color color = boundingBox.getColor();
-        double y = PlayerData.getMaxY(ConfigManager.worldSpawnMaxY.getInt()) + 0.001F;
-        renderRectangle(aaBB, y, y, color, false);
-    }
-}
\ No newline at end of file
diff --git a/java/com/irtimaled/bbor/common/BoundingBoxCache.java b/java/com/irtimaled/bbor/common/BoundingBoxCache.java
deleted file mode 100644 (file)
index 03026f1..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.irtimaled.bbor.common;
-
-import com.irtimaled.bbor.common.models.BoundingBox;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class BoundingBoxCache {
-    private Map<BoundingBox, Set<BoundingBox>> cache = new ConcurrentHashMap<>();
-
-    public Map<BoundingBox, Set<BoundingBox>> getBoundingBoxes() {
-        return cache;
-    }
-
-    public synchronized void refresh() {
-    }
-
-    public void close() {
-        cache.clear();
-    }
-
-    boolean isCached(BoundingBox key) {
-        return cache.containsKey(key);
-    }
-
-    public void addBoundingBoxes(BoundingBox key, Set<BoundingBox> boundingBoxes) {
-        cache.put(key, boundingBoxes);
-    }
-
-    public void addBoundingBox(BoundingBox key) {
-        Set<BoundingBox> boundingBoxes = new HashSet<>();
-        boundingBoxes.add(key);
-        addBoundingBoxes(key, boundingBoxes);
-    }
-
-    public void removeBoundingBox(BoundingBox key) {
-        if (cache.containsKey(key)) {
-            cache.remove(key);
-        }
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/CommonProxy.java b/java/com/irtimaled/bbor/common/CommonProxy.java
deleted file mode 100644 (file)
index 68e338b..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.irtimaled.bbor.common;
-
-import com.irtimaled.bbor.Logger;
-import com.irtimaled.bbor.ReflectionHelper;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.world.DimensionType;
-import net.minecraft.world.World;
-import net.minecraft.world.chunk.Chunk;
-import net.minecraft.world.chunk.IChunkProvider;
-import net.minecraft.world.gen.ChunkProviderServer;
-import net.minecraft.world.gen.IChunkGenerator;
-
-import java.util.HashSet;
-import java.util.Set;
-
-public class CommonProxy {
-    protected DimensionCache dimensionCache;
-    protected Set<VillageProcessor> villageProcessors = new HashSet<>();
-
-    private IVillageEventHandler eventHandler = null;
-
-    public void worldLoaded(World world) {
-        IChunkProvider chunkProvider = world.getChunkProvider();
-        if (chunkProvider instanceof ChunkProviderServer) {
-            IChunkGenerator chunkGenerator = ReflectionHelper.getPrivateValue(ChunkProviderServer.class, (ChunkProviderServer) chunkProvider, IChunkGenerator.class);
-            dimensionCache.setWorldData(world.getSeed(), world.getWorldInfo().getSpawnX(), world.getWorldInfo().getSpawnZ());
-            DimensionType dimensionType = world.provider.getDimensionType();
-            Logger.info("create world dimension: %s, %s (chunkprovider: %s) (seed: %d)", dimensionType, world.getClass().toString(), chunkGenerator.getClass().toString(), world.getSeed());
-            DimensionProcessor boundingBoxCache = new DimensionProcessor(dimensionType, chunkGenerator);
-            dimensionCache.put(dimensionType, boundingBoxCache);
-            if (ConfigManager.drawVillages.getBoolean()) {
-                villageProcessors.add(new VillageProcessor(world, dimensionType, eventHandler, boundingBoxCache));
-            }
-        }
-    }
-
-    public void chunkLoaded(Chunk chunk) {
-        DimensionType dimensionType = chunk.getWorld().provider.getDimensionType();
-        dimensionCache.refresh(dimensionType);
-    }
-
-    public void tick() {
-        villageProcessors.forEach(VillageProcessor::process);
-    }
-
-    public void init() {
-        dimensionCache = new DimensionCache();
-    }
-
-    public void setEventHandler(IVillageEventHandler eventHandler) {
-        this.eventHandler = eventHandler;
-    }
-
-    public DimensionCache getDimensionCache() {
-        return dimensionCache;
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/DimensionCache.java b/java/com/irtimaled/bbor/common/DimensionCache.java
deleted file mode 100644 (file)
index a6c8f24..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.irtimaled.bbor.common;
-
-import com.irtimaled.bbor.common.models.WorldData;
-import net.minecraft.world.DimensionType;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class DimensionCache {
-    private final Map<DimensionType, BoundingBoxCache> map = new ConcurrentHashMap<>();
-    private WorldData worldData;
-
-    void refresh(DimensionType dimensionType) {
-        if (map.containsKey(dimensionType)) {
-            map.get(dimensionType).refresh();
-        }
-    }
-
-    public void put(DimensionType dimensionType, BoundingBoxCache boundingBoxCache) {
-        map.put(dimensionType, boundingBoxCache);
-    }
-
-    public BoundingBoxCache getBoundingBoxes(DimensionType dimensionType) {
-        return map.get(dimensionType);
-    }
-
-    public void clear() {
-        worldData = null;
-        for (BoundingBoxCache cache : map.values()) {
-            cache.close();
-        }
-        map.clear();
-    }
-
-    public void setWorldData(long seed, int spawnX, int spawnZ) {
-        this.worldData = new WorldData(seed, spawnX, spawnZ);
-    }
-
-    public WorldData getWorldData() {
-        return worldData;
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/DimensionProcessor.java b/java/com/irtimaled/bbor/common/DimensionProcessor.java
deleted file mode 100644 (file)
index 7ea59c4..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-package com.irtimaled.bbor.common;
-
-import com.irtimaled.bbor.Logger;
-import com.irtimaled.bbor.ReflectionHelper;
-import com.irtimaled.bbor.common.models.BoundingBox;
-import com.irtimaled.bbor.common.models.BoundingBoxStructure;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.util.math.ChunkPos;
-import net.minecraft.world.DimensionType;
-import net.minecraft.world.gen.ChunkGeneratorEnd;
-import net.minecraft.world.gen.ChunkGeneratorHell;
-import net.minecraft.world.gen.ChunkGeneratorOverworld;
-import net.minecraft.world.gen.IChunkGenerator;
-import net.minecraft.world.gen.structure.*;
-
-import java.awt.*;
-import java.util.*;
-
-public class DimensionProcessor extends BoundingBoxCache {
-    DimensionProcessor(DimensionType dimensionType, IChunkGenerator chunkGenerator) {
-        this.dimensionType = dimensionType;
-        this.chunkGenerator = chunkGenerator;
-    }
-
-    private DimensionType dimensionType;
-    private IChunkGenerator chunkGenerator;
-
-    private boolean closed = false;
-
-    @Override
-    public void close() {
-        closed = true;
-        chunkGenerator = null;
-        super.close();
-    }
-
-    private static <T extends IChunkGenerator, R extends MapGenStructure> Collection<StructureStart> getStructures(T chunkGenerator, Class<R> generatorClass) {
-        Class<T> chunkGeneratorClass = (Class<T>) chunkGenerator.getClass();
-        R structureGenerator = ReflectionHelper.getPrivateValue(chunkGeneratorClass, chunkGenerator, generatorClass);
-        if (structureGenerator != null) {
-            Map<ChunkPos, StructureStart> structureMap = ReflectionHelper.getPrivateValue(MapGenStructure.class, structureGenerator, Map.class);
-            return structureMap.values();
-        }
-        return Collections.emptyList();
-    }
-
-    private Map<StructureType, Collection<StructureStart>> getStructures() {
-        Map<StructureType, Collection<StructureStart>> structureMap = new HashMap<>();
-        if (chunkGenerator instanceof ChunkGeneratorOverworld) {
-            if (ConfigManager.drawDesertTemples.getBoolean()) {
-                structureMap.put(StructureType.DesertTemple, getStructuresWithComponent(getStructures(chunkGenerator, MapGenScatteredFeature.class), ComponentScatteredFeaturePieces.DesertPyramid.class));
-            }
-
-            if (ConfigManager.drawJungleTemples.getBoolean()) {
-                structureMap.put(StructureType.JungleTemple, getStructuresWithComponent(getStructures(chunkGenerator, MapGenScatteredFeature.class), ComponentScatteredFeaturePieces.JunglePyramid.class));
-            }
-
-            if (ConfigManager.drawWitchHuts.getBoolean()) {
-                structureMap.put(StructureType.WitchHut, getStructuresWithComponent(getStructures(chunkGenerator, MapGenScatteredFeature.class), ComponentScatteredFeaturePieces.SwampHut.class));
-            }
-
-            if (ConfigManager.drawOceanMonuments.getBoolean()) {
-                structureMap.put(StructureType.OceanMonument, getStructures(chunkGenerator, StructureOceanMonument.class));
-            }
-
-            if (ConfigManager.drawStrongholds.getBoolean()) {
-                structureMap.put(StructureType.Stronghold, getStructures(chunkGenerator, MapGenStronghold.class));
-            }
-
-            if (ConfigManager.drawMansions.getBoolean()) {
-                structureMap.put(StructureType.Mansion, getStructures(chunkGenerator, WoodlandMansion.class));
-            }
-
-            if (ConfigManager.drawMineShafts.getBoolean()) {
-                structureMap.put(StructureType.MineShaft, getStructures(chunkGenerator, MapGenMineshaft.class));
-            }
-        } else if (chunkGenerator instanceof ChunkGeneratorHell) {
-            if (ConfigManager.drawNetherFortresses.getBoolean()) {
-                structureMap.put(StructureType.NetherFortress, getStructures(chunkGenerator, MapGenNetherBridge.class));
-            }
-        } else if (chunkGenerator instanceof ChunkGeneratorEnd) {
-            if (ConfigManager.drawEndCities.getBoolean()) {
-                structureMap.put(StructureType.EndCity, getStructures(chunkGenerator, MapGenEndCity.class));
-            }
-        }
-
-        return structureMap;
-    }
-
-    private Collection<StructureStart> getStructuresWithComponent(Collection<StructureStart> structures, Class structureComponent) {
-        Collection<StructureStart> validStructures = new HashSet<>();
-        for (StructureStart structure : structures) {
-            if (structure.getComponents().get(0).getClass().equals(structureComponent)) {
-                validStructures.add(structure);
-            }
-        }
-        return validStructures;
-    }
-
-    @Override
-    public synchronized void refresh() {
-        if (closed) return;
-
-        Map<StructureType, Collection<StructureStart>> structureMap = getStructures();
-        for (StructureType structureType : structureMap.keySet()) {
-            Color color = structureType.getColor();
-            for (StructureStart structureStart : structureMap.get(structureType)) {
-                if (structureStart.getBoundingBox() != null) {
-                    BoundingBox boundingBox = BoundingBoxStructure.from(structureStart.getBoundingBox(), color);
-                    if (!isCached(boundingBox)) {
-                        Set<BoundingBox> structureBoundingBoxes = new HashSet<>();
-                        for (StructureComponent structureComponent : structureStart.getComponents()) {
-                            structureBoundingBoxes.add(BoundingBoxStructure.from(structureComponent.getBoundingBox(), color));
-                        }
-                        addBoundingBoxes(boundingBox, structureBoundingBoxes);
-                        Logger.info("[%s] new dimensionCache entries: %d", dimensionType, structureBoundingBoxes.size());
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/IVillageEventHandler.java b/java/com/irtimaled/bbor/common/IVillageEventHandler.java
deleted file mode 100644 (file)
index b8df1c8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.irtimaled.bbor.common;
-
-import com.irtimaled.bbor.common.models.BoundingBox;
-import net.minecraft.world.DimensionType;
-
-public interface IVillageEventHandler {
-    void villageRemoved(DimensionType dimensionType, BoundingBox bb);
-}
diff --git a/java/com/irtimaled/bbor/common/StructureType.java b/java/com/irtimaled/bbor/common/StructureType.java
deleted file mode 100644 (file)
index 9f7e87a..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.irtimaled.bbor.common;
-
-import java.awt.*;
-
-public class StructureType {
-    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 static final int END_CITY = 8;
-    private static final int MANSION = 9;
-
-    public final static StructureType JungleTemple = new StructureType(JUNGLE_TEMPLE);
-    public final static StructureType DesertTemple = new StructureType(DESERT_TEMPLE);
-    public final static StructureType WitchHut = new StructureType(WITCH_HUT);
-    public final static StructureType OceanMonument = new StructureType(OCEAN_MONUMENT);
-    public final static StructureType Stronghold = new StructureType(STRONGHOLD);
-    public final static StructureType MineShaft = new StructureType(MINE_SHAFT);
-    public final static StructureType NetherFortress = new StructureType(NETHER_FORTRESS);
-    public final static StructureType EndCity = new StructureType(END_CITY);
-    public final static StructureType Mansion = new StructureType(MANSION);
-
-    private final int type;
-
-    private StructureType(int type) {
-        this.type = type;
-    }
-
-    public Color getColor() {
-        switch (type) {
-            case DESERT_TEMPLE:
-                return Color.ORANGE;
-            case JUNGLE_TEMPLE:
-                return Color.GREEN;
-            case WITCH_HUT:
-                return Color.BLUE;
-            case MINE_SHAFT:
-                return Color.LIGHT_GRAY;
-            case NETHER_FORTRESS:
-                return Color.RED;
-            case OCEAN_MONUMENT:
-                return Color.CYAN;
-            case STRONGHOLD:
-                return Color.YELLOW;
-            case END_CITY:
-                return Color.MAGENTA;
-            case MANSION:
-                return new Color(139, 69, 19);
-        }
-        return Color.WHITE;
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/VillageColorCache.java b/java/com/irtimaled/bbor/common/VillageColorCache.java
deleted file mode 100644 (file)
index d5071a7..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.irtimaled.bbor.common;
-
-import java.awt.*;
-import java.util.HashMap;
-import java.util.Map;
-
-public class VillageColorCache {
-    private static int colorIndex = -1;
-
-    public static void clear() {
-        colorIndex = -1;
-        villageColorCache.clear();
-    }
-
-    private static Color getNextColor() {
-        switch (++colorIndex % 6) {
-            case 0:
-                return Color.RED;
-            case 1:
-                return Color.GREEN;
-            case 2:
-                return Color.BLUE;
-            case 3:
-                return Color.MAGENTA;
-            case 4:
-                return Color.YELLOW;
-            case 5:
-                return Color.CYAN;
-        }
-        return Color.WHITE;
-    }
-
-    private static Map<Integer, Color> villageColorCache = new HashMap<>();
-
-    public static Color getColor(int villageId) {
-        return villageColorCache.computeIfAbsent(villageId, k -> getNextColor());
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/VillageProcessor.java b/java/com/irtimaled/bbor/common/VillageProcessor.java
deleted file mode 100644 (file)
index ce4cd7f..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.irtimaled.bbor.common;
-
-import com.irtimaled.bbor.common.models.BoundingBoxVillage;
-import net.minecraft.village.Village;
-import net.minecraft.village.VillageCollection;
-import net.minecraft.world.DimensionType;
-import net.minecraft.world.World;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class VillageProcessor {
-    private World world;
-    private DimensionType dimensionType;
-    private IVillageEventHandler eventHandler;
-    private BoundingBoxCache boundingBoxCache;
-    private Map<Integer, BoundingBoxVillage> villageCache = new HashMap<>();
-    private boolean closed = false;
-
-    VillageProcessor(World world, DimensionType dimensionType, IVillageEventHandler eventHandler, BoundingBoxCache boundingBoxCache) {
-        this.world = world;
-        this.dimensionType = dimensionType;
-        this.eventHandler = eventHandler;
-        this.boundingBoxCache = boundingBoxCache;
-    }
-
-    synchronized void process() {
-        if (closed) return;
-
-        Map<Integer, BoundingBoxVillage> oldVillages = new HashMap<>(villageCache);
-        Map<Integer, BoundingBoxVillage> newVillages = new HashMap<>();
-        VillageCollection villageCollection = world.getVillageCollection();
-        if (villageCollection != null) {
-            List<Village> villages = villageCollection.getVillageList();
-            for(int i = 0; i < villages.size(); i++) {
-                Village village = villages.get(i);
-                int villageId = village.hashCode();
-                BoundingBoxVillage newVillage = oldVillages.get(villageId);
-                if (newVillage != null && newVillage.matches(village)) {
-                    oldVillages.remove(villageId);
-                } else {
-                    newVillage = BoundingBoxVillage.from(village);
-                }
-                newVillages.put(villageId, newVillage);
-            }
-
-        }
-        for (BoundingBoxVillage village : oldVillages.values()) {
-            boundingBoxCache.removeBoundingBox(village);
-            if (eventHandler != null) {
-                eventHandler.villageRemoved(dimensionType, village);
-            }
-        }
-        for (BoundingBoxVillage village : newVillages.values()) {
-            boundingBoxCache.addBoundingBox(village);
-        }
-        villageCache = newVillages;
-    }
-
-    public void close() {
-        closed = true;
-        world = null;
-        eventHandler = null;
-        boundingBoxCache = null;
-        villageCache.clear();
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/models/BoundingBox.java b/java/com/irtimaled/bbor/common/models/BoundingBox.java
deleted file mode 100644 (file)
index c337dc7..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.irtimaled.bbor.common.models;
-
-import net.minecraft.util.math.AxisAlignedBB;
-import net.minecraft.util.math.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;
-        return minBlockPos.equals(other.minBlockPos) && maxBlockPos.equals(other.maxBlockPos);
-    }
-
-    @Override
-    public String toString() {
-        return "(" + minBlockPos.toString() + "; " + maxBlockPos.toString() + ")";
-    }
-
-    public AxisAlignedBB toAxisAlignedBB() {
-        return toAxisAlignedBB(true);
-    }
-
-    public AxisAlignedBB toAxisAlignedBB(boolean extendMaxByOne) {
-        AxisAlignedBB axisAlignedBB = new AxisAlignedBB(minBlockPos, maxBlockPos);
-        if (extendMaxByOne)
-            return axisAlignedBB.expand(1, 1, 1);
-        return axisAlignedBB;
-    }
-
-    public BlockPos getMinBlockPos() {
-        return minBlockPos;
-    }
-
-    public BlockPos getMaxBlockPos() {
-        return maxBlockPos;
-    }
-
-    public Color getColor() {
-        return color;
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/models/BoundingBoxSlimeChunk.java b/java/com/irtimaled/bbor/common/models/BoundingBoxSlimeChunk.java
deleted file mode 100644 (file)
index 93aa8f3..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.irtimaled.bbor.common.models;
-
-import net.minecraft.util.math.BlockPos;
-
-import java.awt.*;
-
-public class BoundingBoxSlimeChunk extends BoundingBox {
-    private BoundingBoxSlimeChunk(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
-        super(minBlockPos, maxBlockPos, color);
-    }
-
-    public static BoundingBoxSlimeChunk from(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
-        return new BoundingBoxSlimeChunk(minBlockPos, maxBlockPos, color);
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/models/BoundingBoxStructure.java b/java/com/irtimaled/bbor/common/models/BoundingBoxStructure.java
deleted file mode 100644 (file)
index 97f2602..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.irtimaled.bbor.common.models;
-
-import net.minecraft.util.math.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(int[] bb, Color color) {
-        BlockPos minBlockPos = new BlockPos(bb[0], bb[1], bb[2]);
-        BlockPos maxBlockPos = new BlockPos(bb[3], bb[4], bb[5]);
-        return new BoundingBoxStructure(minBlockPos, maxBlockPos, color);
-    }
-
-    public static BoundingBoxStructure from(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
-        return new BoundingBoxStructure(minBlockPos, maxBlockPos, color);
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/models/BoundingBoxVillage.java b/java/com/irtimaled/bbor/common/models/BoundingBoxVillage.java
deleted file mode 100644 (file)
index 427aa45..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-package com.irtimaled.bbor.common.models;
-
-import com.irtimaled.bbor.common.VillageColorCache;
-import net.minecraft.util.math.BlockPos;
-import net.minecraft.village.Village;
-import net.minecraft.village.VillageDoorInfo;
-
-import java.awt.*;
-import java.util.*;
-import java.util.List;
-
-public class BoundingBoxVillage extends BoundingBox {
-    private final BlockPos center;
-    private final Integer radius;
-    private final boolean spawnsIronGolems;
-    private Set<BlockPos> doors;
-    private Double centerOffsetX;
-    private Double centerOffsetZ;
-    private int villageHash;
-
-    private BoundingBoxVillage(BlockPos center, Integer radius, Color color, boolean spawnsIronGolems, Set<BlockPos> doors, BlockPos minBlockPos, BlockPos maxBlockPos) {
-        super(minBlockPos, maxBlockPos, color);
-        this.center = center;
-        this.radius = radius;
-        this.spawnsIronGolems = spawnsIronGolems;
-        this.doors = doors;
-        this.villageHash = computeHash(center, radius, spawnsIronGolems, doors);
-        calculateCenterOffsets(doors);
-    }
-
-    public static BoundingBoxVillage from(BlockPos center, Integer radius, Color color, boolean spawnsIronGolems, Set<BlockPos> doors) {
-        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, doors, minBlockPos, maxBlockPos);
-    }
-
-    public static BoundingBoxVillage from(BlockPos center, Integer radius, int villageId, int population, Set<BlockPos> doors) {
-        Boolean spawnsIronGolems = shouldSpawnIronGolems(population, doors.size());
-        Color color = VillageColorCache.getColor(villageId);
-        return from(center, radius, color, spawnsIronGolems, doors);
-    }
-
-    private static boolean shouldSpawnIronGolems(int population, int doorCount) {
-        return population >= 10 && doorCount >= 21;
-    }
-
-    public static BoundingBoxVillage from(Village village) {
-        BlockPos center = village.getCenter();
-        int radius = village.getVillageRadius();
-        Set<BlockPos> doors = getDoorsFromVillage(village);
-        return from(center, radius, village.hashCode(), village.getNumVillagers(), doors);
-    }
-
-    private static Set<BlockPos> getDoorsFromVillage(Village village) {
-        Set<BlockPos> doors = new HashSet<>();
-        List<VillageDoorInfo> doorInfoList = village.getVillageDoorInfoList();
-        for (int i = 0; i < doorInfoList.size(); i++) {
-            VillageDoorInfo doorInfo = doorInfoList.get(i);
-            doors.add(doorInfo.getDoorBlockPos());
-        }
-        return doors;
-    }
-
-    private void calculateCenterOffsets(Set<BlockPos> doors) {
-        boolean processedFirstDoor = false;
-        int minX = 0;
-        int maxX = 0;
-        int minZ = 0;
-        int maxZ = 0;
-        for (BlockPos door : doors) {
-            if (!processedFirstDoor ||
-                    (minX > door.getX()))
-                minX = door.getX();
-            if (!processedFirstDoor ||
-                    maxX < door.getX())
-                maxX = door.getX();
-            if (!processedFirstDoor ||
-                    minZ > door.getZ())
-                minZ = door.getZ();
-            if (!processedFirstDoor ||
-                    maxZ < door.getZ())
-                maxZ = door.getZ();
-
-            processedFirstDoor = true;
-        }
-        centerOffsetX = Math.abs(maxX - minX) % 2 == 0 ? 0.5 : (minX < 0 ? 0 : 1);
-        centerOffsetZ = Math.abs(maxZ - minZ) % 2 == 0 ? 0.5 : (minZ < 0 ? 0 : 1);
-    }
-
-    @Override
-    public String toString() {
-        return "(" + center.toString() + "; " + radius.toString() + ")";
-    }
-
-    public Integer getRadius() {
-        return radius;
-    }
-
-    public BlockPos getCenter() {
-        return center;
-    }
-
-    public Double getCenterOffsetX() {
-        return centerOffsetX;
-    }
-
-    public Double getCenterOffsetZ() {
-        return centerOffsetZ;
-    }
-
-    private static int computeHash(BlockPos center, Integer radius, boolean spawnsIronGolems, Set<BlockPos> doors) {
-        int result = (center.hashCode() * 31) + radius;
-        for (BlockPos door : doors) {
-            result = (31 * result) + door.hashCode();
-        }
-        if (spawnsIronGolems) {
-            result = 31 * result;
-        }
-        return result;
-    }
-
-    public boolean matches(Village village) {
-        return this.villageHash == computeHash(village.getCenter(),
-                village.getVillageRadius(),
-                shouldSpawnIronGolems(village.getNumVillagers(), village.getNumVillageDoors()),
-                getDoorsFromVillage(village));
-    }
-
-    @Override
-    public int hashCode() {
-        return (super.hashCode() * 31) + villageHash;
-    }
-
-    public boolean getSpawnsIronGolems() {
-        return spawnsIronGolems;
-    }
-
-    public Set<BlockPos> getDoors() {
-        return doors;
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/models/BoundingBoxWorldSpawn.java b/java/com/irtimaled/bbor/common/models/BoundingBoxWorldSpawn.java
deleted file mode 100644 (file)
index ad3a127..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.irtimaled.bbor.common.models;
-
-import net.minecraft.util.math.BlockPos;
-
-import java.awt.*;
-
-public class BoundingBoxWorldSpawn extends BoundingBox {
-    private BoundingBoxWorldSpawn(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
-        super(minBlockPos, maxBlockPos, color);
-    }
-
-    public static BoundingBoxWorldSpawn from(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
-        return new BoundingBoxWorldSpawn(minBlockPos, maxBlockPos, color);
-    }
-}
diff --git a/java/com/irtimaled/bbor/common/models/WorldData.java b/java/com/irtimaled/bbor/common/models/WorldData.java
deleted file mode 100644 (file)
index 1eb5dbb..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.irtimaled.bbor.common.models;
-
-public class WorldData {
-    private long seed;
-    private int spawnX;
-    private int spawnZ;
-
-    public WorldData(long seed, int spawnX, int spawnZ) {
-        this.seed = seed;
-        this.spawnX = spawnX;
-        this.spawnZ = spawnZ;
-    }
-
-    public long getSeed() {
-        return seed;
-    }
-
-    public int getSpawnX() {
-        return spawnX;
-    }
-
-    public int getSpawnZ() {
-        return spawnZ;
-    }
-}
diff --git a/java/com/irtimaled/bbor/config/ConfigManager.java b/java/com/irtimaled/bbor/config/ConfigManager.java
deleted file mode 100644 (file)
index 37227f9..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.irtimaled.bbor.config;
-
-import java.io.File;
-
-public class ConfigManager {
-    public static File configDir;
-
-    public static Setting fill;
-    public static Setting drawVillages;
-    public static Setting drawDesertTemples;
-    public static Setting drawJungleTemples;
-    public static Setting drawWitchHuts;
-    public static Setting drawStrongholds;
-    public static Setting drawMineShafts;
-    public static Setting drawNetherFortresses;
-    public static Setting drawOceanMonuments;
-    public static Setting alwaysVisible;
-    public static Setting renderVillageAsSphere;
-    public static Setting drawIronGolemSpawnArea;
-    public static Setting drawVillageDoors;
-    public static Setting drawSlimeChunks;
-    public static Setting slimeChunkMaxY;
-    public static Setting keepCacheBetweenSessions;
-    public static Setting drawWorldSpawn;
-    public static Setting worldSpawnMaxY;
-    public static Setting drawLazySpawnChunks;
-    public static Setting drawEndCities;
-    public static Setting drawMansions;
-
-    public static void loadConfig(File mcConfigDir) {
-        configDir = mcConfigDir;
-        Configuration config = new Configuration(new File(configDir, "BBOutlineReloaded.cfg"));
-        config.load();
-
-        fill = SetupBooleanProperty(config, "general", "fill", true, "If set to true the bounding boxes are filled. (default: true)");
-        alwaysVisible = SetupBooleanProperty(config, "general", "alwaysVisible", false, "If set to true boxes will be visible even through other blocks. (default: false)");
-        keepCacheBetweenSessions = SetupBooleanProperty(config, "general", "keepCacheBetweenSessions", false, "If set to true bounding box caches will be kept between sessions. (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)");
-        drawVillageDoors = SetupBooleanProperty(config, "features", "drawVillageDoors", false, "If set to true lines between the village centre and doors will be drawn. (default:false)");
-        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", -1, "The maximum top of the slime chunk bounding box. If set to -1 it will use the value when activated, if set to 0 it will always track the player's feet. (default: -1)");
-        drawWorldSpawn = SetupBooleanProperty(config, "features", "drawWorldSpawn", true, "If set to true world spawn and spawn chunks bounding boxes are drawn. (default: true)");
-        worldSpawnMaxY = SetupIntegerProperty(config, "features", "worldSpawnMaxY", -1, "The maximum top of the world spawn bounding boxes. If set to -1 it will use the value when activated, if set to 0 it will always track the players feet. (default: -1)");
-        drawLazySpawnChunks = SetupBooleanProperty(config, "features", "drawLazySpawnChunks", false, "If set to true the lazy spawn chunks bounding boxes will be drawn. (default: false)");
-        drawEndCities = SetupBooleanProperty(config, "features", "drawEndCities", true, "If set to true end city bounding boxes will be drawn. (default: true)");
-        drawMansions = SetupBooleanProperty(config, "features", "drawMansions", true, "If set to true woodland mansions will be drawn. (default: true)");
-        config.save();
-    }
-
-    private static Setting SetupBooleanProperty(Configuration config, String category, String settingName, Boolean defaultValue, String comment) {
-        Setting property = config.get(category, settingName, defaultValue);
-        property.comment = comment;
-        property.set(property.getBoolean(defaultValue));
-        return property;
-    }
-
-    private static Setting SetupIntegerProperty(Configuration config, String category, String settingName, int defaultValue, String comment) {
-        Setting property = config.get(category, settingName, defaultValue);
-        property.comment = comment;
-        property.set(property.getInt(defaultValue));
-        return property;
-    }
-}
diff --git a/java/com/irtimaled/bbor/config/Configuration.java b/java/com/irtimaled/bbor/config/Configuration.java
deleted file mode 100644 (file)
index 2048526..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.irtimaled.bbor.config;
-
-import com.google.common.io.Files;
-
-import java.io.*;
-import java.nio.charset.Charset;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class Configuration {
-    private final File file;
-
-    Configuration(File file) {
-        this.file = file;
-    }
-
-    void save() {
-        Writer writer = null;
-        try {
-            writer = new BufferedWriter(new OutputStreamWriter(
-                    new FileOutputStream(file), "utf-8"));
-            writer.write("# Configuration file\n");
-            for (String category : settingsGroup.keySet()) {
-                writer.write("\n");
-                writer.write(String.format("%s {\n", category));
-                Map<String, Setting> settings = settingsGroup.get(category);
-                Boolean first = true;
-                for (String settingName : settings.keySet()) {
-                    if (!first)
-                        writer.write("\n");
-                    first = false;
-                    Setting setting = settings.get(settingName);
-                    writer.write(String.format("    # %s\n", setting.comment));
-                    writer.write(String.format("    %s:%s=%s\n", setting.getType(), settingName, setting.getValue()));
-                }
-                writer.write("}\n");
-            }
-        } catch (IOException ignored) {
-        } finally {
-            try {
-                if (writer != null) {
-                    writer.close();
-                }
-            } catch (Exception ignored) {
-            }
-        }
-    }
-
-    private Map<String, Map<String, Setting>> settingsGroup = new HashMap<>();
-
-    void load() {
-        try {
-            List<String> lines = Files.readLines(file, Charset.forName("utf-8"));
-            String category = null;
-            String lastCommentLine = null;
-            for (String line : lines) {
-                String trimmedLine = line.trim();
-                if (trimmedLine.isEmpty()) {
-                    continue;
-                }
-                if (trimmedLine.startsWith("#")) {
-                    lastCommentLine = trimmedLine.substring(1).trim();
-                    continue;
-                }
-                if (trimmedLine.equals("}")) {
-                    category = null;
-                    continue;
-                }
-                if (category == null && trimmedLine.endsWith("{")) {
-                    category = trimmedLine.substring(0, trimmedLine.length() - 1).trim();
-                    settingsGroup.put(category, new HashMap<>());
-                    continue;
-                }
-                if (category != null) {
-                    String[] items = trimmedLine.split("[:=]");
-                    char type = items[0].charAt(0);
-                    String name = items[1];
-                    String stringValue = items[2];
-                    Object value = getTypedValue(type, stringValue);
-                    Setting setting = new Setting(value);
-                    setting.comment = lastCommentLine;
-                    settingsGroup.get(category).put(name, setting);
-                }
-            }
-        } catch (IOException ignored) {
-        }
-    }
-
-    private Object getTypedValue(char type, String stringValue) {
-        switch (type) {
-            case 'I':
-                return Integer.parseInt(stringValue);
-            case 'B':
-                return stringValue.equals("1") || stringValue.toLowerCase().equals("true");
-        }
-        return stringValue;
-    }
-
-    public Setting get(String category, String settingName, Object defaultValue) {
-        if (!settingsGroup.containsKey(category)) {
-            settingsGroup.put(category, new HashMap<>());
-        }
-        Map<String, Setting> settings = settingsGroup.get(category);
-        if (!settings.containsKey(settingName)) {
-            settings.put(settingName, new Setting(defaultValue));
-        }
-        return settings.get(settingName);
-    }
-}
diff --git a/java/com/irtimaled/bbor/config/Setting.java b/java/com/irtimaled/bbor/config/Setting.java
deleted file mode 100644 (file)
index ec7bbef..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.irtimaled.bbor.config;
-
-public class Setting {
-    private Object value;
-    String comment;
-
-    Setting(Object value) {
-        this.value = value;
-    }
-
-    public Boolean getBoolean(Boolean defaultValue) {
-        if (value instanceof Boolean)
-            return (Boolean) value;
-
-        return defaultValue;
-    }
-
-    int getInt(int defaultValue) {
-        if (value instanceof Integer)
-            return (Integer) value;
-
-        return defaultValue;
-    }
-
-    public void set(Object value) {
-        this.value = value;
-    }
-
-    public boolean getBoolean() {
-        return getBoolean(false);
-    }
-
-    public int getInt() {
-        return getInt(0);
-    }
-
-    String getType() {
-        if (value instanceof Integer)
-            return "I";
-        if (value instanceof Boolean)
-            return "B";
-        return "S";
-    }
-
-    Object getValue() {
-        return value;
-    }
-}
diff --git a/java/com/irtimaled/bbor/forge/ForgeClientProxy.java b/java/com/irtimaled/bbor/forge/ForgeClientProxy.java
deleted file mode 100644 (file)
index 0ec1a8b..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.irtimaled.bbor.forge;
-
-import com.irtimaled.bbor.client.ClientProxy;
-import net.minecraft.client.Minecraft;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraftforge.client.event.RenderWorldLastEvent;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import net.minecraftforge.fml.common.gameevent.InputEvent;
-import net.minecraftforge.fml.common.network.FMLNetworkEvent;
-
-public class ForgeClientProxy extends ForgeCommonProxy {
-    private ClientProxy proxy;
-
-    @Override
-    public ClientProxy getProxy() {
-        if (proxy == null) {
-            proxy = new ClientProxy();
-        }
-        return proxy;
-    }
-
-    @SubscribeEvent
-    public void onKeyInputEvent(InputEvent.KeyInputEvent evt) {
-        getProxy().keyPressed();
-    }
-
-    @Override
-    protected void onRegisteredPlayerCountChanged(int registeredPlayerCount) {
-        getProxy().setRemoteUserCount(registeredPlayerCount-1);
-    }
-
-    @Override
-    protected boolean isRemotePlayer(EntityPlayer player) {
-        if (Minecraft.getMinecraft().isSingleplayer()) {
-            EntityPlayer singlePlayer = Minecraft.getMinecraft().player;
-            return singlePlayer != null && player.getGameProfile() != singlePlayer.getGameProfile();
-        }
-        return true;
-    }
-
-    @SubscribeEvent
-    public void renderWorldLastEvent(RenderWorldLastEvent event) {
-        getProxy().render(event.getPartialTicks());
-    }
-
-    @SubscribeEvent
-    public void clientConnectionToServerEvent(FMLNetworkEvent.ClientConnectedToServerEvent evt) {
-        if (!evt.isLocal()) {
-            getProxy().playerConnectedToServer(evt.getManager());
-        }
-    }
-
-    @SubscribeEvent
-    public void clientDisconnectionFromServerEvent(FMLNetworkEvent.ClientDisconnectionFromServerEvent evt) {
-        getProxy().playerDisconnectedFromServer();
-    }
-}
diff --git a/java/com/irtimaled/bbor/forge/ForgeCommonProxy.java b/java/com/irtimaled/bbor/forge/ForgeCommonProxy.java
deleted file mode 100644 (file)
index 956275f..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-package com.irtimaled.bbor.forge;
-
-import com.irtimaled.bbor.Logger;
-import com.irtimaled.bbor.common.BoundingBoxCache;
-import com.irtimaled.bbor.common.CommonProxy;
-import com.irtimaled.bbor.common.DimensionCache;
-import com.irtimaled.bbor.common.IVillageEventHandler;
-import com.irtimaled.bbor.common.models.BoundingBox;
-import com.irtimaled.bbor.forge.messages.*;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.entity.player.EntityPlayerMP;
-import net.minecraft.network.NetHandlerPlayServer;
-import net.minecraft.server.MinecraftServer;
-import net.minecraft.world.DimensionType;
-import net.minecraft.world.World;
-import net.minecraftforge.event.world.ChunkEvent;
-import net.minecraftforge.event.world.WorldEvent;
-import net.minecraftforge.fml.common.FMLCommonHandler;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import net.minecraftforge.fml.common.gameevent.PlayerEvent;
-import net.minecraftforge.fml.common.gameevent.TickEvent;
-import net.minecraftforge.fml.common.network.FMLNetworkEvent;
-import net.minecraftforge.fml.common.network.NetworkRegistry;
-import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
-import net.minecraftforge.fml.relauncher.Side;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class ForgeCommonProxy implements IVillageEventHandler {
-    private Map<EntityPlayerMP, DimensionType> playerDimensions = new ConcurrentHashMap<>();
-    private Map<EntityPlayerMP, Set<BoundingBox>> playerBoundingBoxesCache = new HashMap<>();
-    private HashSet<EntityPlayerMP> registeredPlayers = new HashSet<>();
-
-    protected CommonProxy getProxy() {
-        if (commonProxy == null)
-            commonProxy = new CommonProxy();
-        return commonProxy;
-    }
-
-    @SubscribeEvent
-    public void packetRegistrationEvent(FMLNetworkEvent.CustomPacketRegistrationEvent event) {
-        if (event.getOperation().equals("REGISTER") &&
-                event.getRegistrations().contains("bbor") &&
-                event.getHandler() instanceof NetHandlerPlayServer) {
-            registeredPlayers.add(((NetHandlerPlayServer) event.getHandler()).player);
-            onRegisteredPlayerCountChanged(registeredPlayers.size());
-        }
-    }
-
-    protected SimpleNetworkWrapper network;
-    private CommonProxy commonProxy;
-
-    void init() {
-        CommonProxy proxy = getProxy();
-        proxy.setEventHandler(this);
-        proxy.init();
-        network = NetworkRegistry.INSTANCE.newSimpleChannel("bbor");
-        network.registerMessage(AddBoundingBoxMessageHandler.class, AddBoundingBoxMessage.class, 0, Side.CLIENT);
-        network.registerMessage(RemoveBoundingBoxMessageHandler.class, RemoveBoundingBoxMessage.class, 1, Side.CLIENT);
-        network.registerMessage(InitializeClientMessageHandler.class, InitializeClientMessage.class, 2, Side.CLIENT);
-    }
-
-    @SubscribeEvent
-    public void worldEvent(WorldEvent.Load event) {
-        World world = event.getWorld();
-        getProxy().worldLoaded(world);
-    }
-
-    @SubscribeEvent
-    public void chunkEvent(ChunkEvent.Load event) {
-        getProxy().chunkLoaded(event.getChunk());
-    }
-
-    @SubscribeEvent
-    public void playerChangedDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent evt) {
-        if (playerDimensions.containsKey(evt.player)) {
-            EntityPlayerMP player = (EntityPlayerMP) evt.player;
-            sendBoundingBoxes(player);
-        }
-    }
-
-    @SubscribeEvent
-    public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent evt) {
-        if (evt.player instanceof EntityPlayerMP &&
-                isRemotePlayer(evt.player)) {
-            EntityPlayerMP player = (EntityPlayerMP) evt.player;
-            initializeClient(player);
-            sendBoundingBoxes(player);
-        }
-    }
-
-    private void sendBoundingBoxes(EntityPlayerMP player) {
-        DimensionType dimensionType = DimensionType.getById(player.dimension);
-        playerDimensions.put(player, dimensionType);
-        sendToPlayer(player, getDimensionCache().getBoundingBoxes(dimensionType));
-    }
-
-    protected boolean isRemotePlayer(EntityPlayer player) {
-        return registeredPlayers.contains(player);
-    }
-
-    private void initializeClient(EntityPlayerMP player) {
-        network.sendTo(InitializeClientMessage.from(getDimensionCache().getWorldData()), player);
-    }
-
-    @SubscribeEvent
-    public void playerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent evt) {
-        if (isRemotePlayer(evt.player)) {
-            playerDimensions.remove(evt.player);
-            playerBoundingBoxesCache.remove(evt.player);
-            registeredPlayers.remove(evt.player);
-            onRegisteredPlayerCountChanged(registeredPlayers.size());
-        }
-    }
-
-    protected void onRegisteredPlayerCountChanged(int registeredPlayerCount) {
-    }
-
-    @SubscribeEvent
-    public void tickEvent(TickEvent event) {
-        for (EntityPlayerMP player : playerDimensions.keySet()) {
-            MinecraftServer mc = FMLCommonHandler.instance().getMinecraftServerInstance();
-            if (!mc.getPlayerList().getPlayers().contains(player)) {
-                playerDimensions.remove(player);
-            } else {
-                DimensionType dimensionType = playerDimensions.get(player);
-                sendToPlayer(player, getDimensionCache().getBoundingBoxes(dimensionType));
-            }
-        }
-        getProxy().tick();
-    }
-
-    private void sendToPlayer(EntityPlayerMP player, BoundingBoxCache boundingBoxCache) {
-        if (boundingBoxCache == null)
-            return;
-        Map<BoundingBox, Set<BoundingBox>> cacheSubset = getBoundingBoxMap(player, boundingBoxCache.getBoundingBoxes());
-
-        DimensionType dimensionType = DimensionType.getById(player.dimension);
-        if (cacheSubset.keySet().size() > 0) {
-            Logger.info("send %d entries to %s (%s)", cacheSubset.keySet().size(), player.getDisplayNameString(), dimensionType);
-        }
-
-        for (BoundingBox key : cacheSubset.keySet()) {
-            Set<BoundingBox> boundingBoxes = cacheSubset.get(key);
-            network.sendTo(AddBoundingBoxMessage.from(dimensionType, key, boundingBoxes), player);
-
-            if (!playerBoundingBoxesCache.containsKey(player)) {
-                playerBoundingBoxesCache.put(player, new HashSet<>());
-            }
-            playerBoundingBoxesCache.get(player).add(key);
-        }
-    }
-
-    private Map<BoundingBox, Set<BoundingBox>> getBoundingBoxMap(EntityPlayerMP player, Map<BoundingBox, Set<BoundingBox>> boundingBoxMap) {
-        Map<BoundingBox, Set<BoundingBox>> 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;
-    }
-
-    public void villageRemoved(DimensionType dimensionType, BoundingBox bb) {
-        RemoveBoundingBoxMessage message = RemoveBoundingBoxMessage.from(dimensionType, bb);
-        for (EntityPlayerMP player : playerDimensions.keySet()) {
-            if (DimensionType.getById(player.dimension) == dimensionType) {
-                Logger.info("remove 1 entry from %s (%s)", player.getDisplayNameString(), dimensionType);
-                network.sendTo(message, player);
-
-                if (playerBoundingBoxesCache.containsKey(player) &&
-                        playerBoundingBoxesCache.get(player).contains(bb)) {
-                    playerBoundingBoxesCache.get(player).remove(bb);
-                }
-            }
-        }
-    }
-
-    public void setWorldData(long seed, int spawnX, int spawnZ) {
-        getDimensionCache().setWorldData(seed, spawnX, spawnZ);
-    }
-
-    public void addBoundingBox(DimensionType dimensionType, BoundingBox key, Set<BoundingBox> boundingBoxes) {
-        DimensionCache dimensionCache = getDimensionCache();
-        BoundingBoxCache cache = dimensionCache.getBoundingBoxes(dimensionType);
-        if (cache == null) {
-            dimensionCache.put(dimensionType, cache = new BoundingBoxCache());
-        }
-        cache.addBoundingBoxes(key, boundingBoxes);
-    }
-
-    public void removeBoundingBox(DimensionType dimensionType, BoundingBox key) {
-        BoundingBoxCache cache = getDimensionCache().getBoundingBoxes(dimensionType);
-        if (cache != null) {
-            cache.removeBoundingBox(key);
-        }
-    }
-
-    private DimensionCache getDimensionCache() {
-        return getProxy().getDimensionCache();
-    }
-}
diff --git a/java/com/irtimaled/bbor/forge/ForgeMod.java b/java/com/irtimaled/bbor/forge/ForgeMod.java
deleted file mode 100644 (file)
index 3311a06..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.irtimaled.bbor.forge;
-
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraftforge.common.MinecraftForge;
-import net.minecraftforge.fml.common.Mod;
-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 = ForgeMod.MODID, name = ForgeMod.NAME, version = ForgeMod.VERSION, acceptedMinecraftVersions = ForgeMod.MCVERSION, acceptableRemoteVersions = "*")
-public class ForgeMod {
-    static final String MODID = "bbor";
-    static final String NAME = "BoundingBoxOutlineReloaded";
-    static final String VERSION = "1.0.3";
-    static final String MCVERSION = "1.12.2";
-
-    public SimpleNetworkWrapper network;
-
-    @Mod.Instance()
-    public static ForgeMod instance;
-
-    @SidedProxy(clientSide = "com.irtimaled.bbor.forge.ForgeClientProxy", serverSide = "com.irtimaled.bbor.forge.ForgeCommonProxy")
-    public static ForgeCommonProxy proxy;
-
-    @Mod.EventHandler
-    public void preInit(FMLPreInitializationEvent evt) {
-        ConfigManager.loadConfig(evt.getModConfigurationDirectory());
-    }
-
-    @Mod.EventHandler
-    public void load(FMLInitializationEvent evt) {
-        MinecraftForge.EVENT_BUS.register(proxy);
-        proxy.init();
-    }
-}
diff --git a/java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessage.java b/java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessage.java
deleted file mode 100644 (file)
index 26f5cb4..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.irtimaled.bbor.forge.messages;
-
-import com.irtimaled.bbor.common.models.BoundingBox;
-import io.netty.buffer.ByteBuf;
-import net.minecraft.world.DimensionType;
-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 AddBoundingBoxMessage implements IMessage {
-    private DimensionType dimensionType;
-    private BoundingBox key;
-    private Set<BoundingBox> boundingBoxes;
-
-    public static AddBoundingBoxMessage from(DimensionType dimensionType, BoundingBox key, Set<BoundingBox> boundingBoxes) {
-        AddBoundingBoxMessage message = new AddBoundingBoxMessage();
-        message.dimensionType = dimensionType;
-        message.key = key;
-        message.boundingBoxes = boundingBoxes;
-        return message;
-    }
-
-    @Override
-    public void fromBytes(ByteBuf buf) {
-        dimensionType = DimensionType.getById(ByteBufUtils.readVarInt(buf, 5));
-        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.writeVarInt(buf, dimensionType.getId(), 5);
-        BoundingBoxSerializer.serialize(key, buf);
-        if (boundingBoxes != null &&
-                boundingBoxes.size() > 1) {
-            for (BoundingBox boundingBox : boundingBoxes) {
-                BoundingBoxSerializer.serialize(boundingBox, buf);
-            }
-        }
-    }
-
-    public DimensionType getDimensionType() {
-        return dimensionType;
-    }
-
-    BoundingBox getKey() {
-        return key;
-    }
-
-    Set<BoundingBox> getBoundingBoxes() {
-        return boundingBoxes;
-    }
-}
diff --git a/java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessageHandler.java b/java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessageHandler.java
deleted file mode 100644 (file)
index 37e6027..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.irtimaled.bbor.forge.messages;
-
-import com.irtimaled.bbor.forge.ForgeMod;
-import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
-import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
-import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
-
-public class AddBoundingBoxMessageHandler implements IMessageHandler<AddBoundingBoxMessage, IMessage> {
-    @Override
-    public IMessage onMessage(AddBoundingBoxMessage message, MessageContext ctx) {
-        ForgeMod.proxy.addBoundingBox(message.getDimensionType(), message.getKey(), message.getBoundingBoxes());
-        return null;
-    }
-}
diff --git a/java/com/irtimaled/bbor/forge/messages/BoundingBoxDeserializer.java b/java/com/irtimaled/bbor/forge/messages/BoundingBoxDeserializer.java
deleted file mode 100644 (file)
index d044152..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.irtimaled.bbor.forge.messages;
-
-import com.irtimaled.bbor.common.models.BoundingBox;
-import com.irtimaled.bbor.common.models.BoundingBoxStructure;
-import com.irtimaled.bbor.common.models.BoundingBoxVillage;
-import io.netty.buffer.ByteBuf;
-import net.minecraft.util.math.BlockPos;
-import net.minecraftforge.fml.common.network.ByteBufUtils;
-
-import java.awt.*;
-import java.util.HashSet;
-import java.util.Set;
-
-class BoundingBoxDeserializer {
-    static BoundingBox deserialize(ByteBuf buf) {
-        char type = (char) ByteBufUtils.readVarShort(buf);
-        switch (type) {
-            case 'V':
-                return deserializeVillage(buf);
-            case 'S':
-                return deserializeStructure(buf);
-        }
-        return null;
-    }
-
-    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));
-        Set<BlockPos> doors = new HashSet<>();
-        while (buf.isReadable()) {
-            BlockPos door = deserializeBlockPos(buf);
-            doors.add(door);
-        }
-        return BoundingBoxVillage.from(center, radius, color, spawnsIronGolems, doors);
-    }
-
-    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);
-    }
-}
diff --git a/java/com/irtimaled/bbor/forge/messages/BoundingBoxSerializer.java b/java/com/irtimaled/bbor/forge/messages/BoundingBoxSerializer.java
deleted file mode 100644 (file)
index f0392f6..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.irtimaled.bbor.forge.messages;
-
-import com.irtimaled.bbor.common.models.BoundingBox;
-import com.irtimaled.bbor.common.models.BoundingBoxStructure;
-import com.irtimaled.bbor.common.models.BoundingBoxVillage;
-import io.netty.buffer.ByteBuf;
-import net.minecraft.util.math.BlockPos;
-import net.minecraftforge.fml.common.network.ByteBufUtils;
-
-import java.awt.*;
-
-class BoundingBoxSerializer {
-    static void serialize(BoundingBox boundingBox, ByteBuf buf) {
-        if (boundingBox instanceof BoundingBoxVillage) {
-            serializeVillage((BoundingBoxVillage) boundingBox, buf);
-        }
-        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);
-        for (BlockPos door : boundingBox.getDoors()) {
-            serializeBlockPos(door, buf);
-        }
-    }
-
-    private static void serializeStructure(BoundingBoxStructure boundingBox, ByteBuf buf) {
-        ByteBufUtils.writeVarShort(buf, 'S');
-        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);
-    }
-}
diff --git a/java/com/irtimaled/bbor/forge/messages/InitializeClientMessage.java b/java/com/irtimaled/bbor/forge/messages/InitializeClientMessage.java
deleted file mode 100644 (file)
index 684736a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.irtimaled.bbor.forge.messages;
-
-import com.irtimaled.bbor.common.models.WorldData;
-import io.netty.buffer.ByteBuf;
-import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
-
-public class InitializeClientMessage implements IMessage {
-    private WorldData worldData;
-
-    public static InitializeClientMessage from(WorldData worldData) {
-        InitializeClientMessage message = new InitializeClientMessage();
-        message.worldData = new WorldData(worldData.getSeed(), worldData.getSpawnX(), worldData.getSpawnZ());
-        return message;
-    }
-
-    @Override
-    public void fromBytes(ByteBuf buf) {
-        long seed = buf.readLong();
-        int spawnX = buf.readInt();
-        int spawnZ = buf.readInt();
-        worldData = new WorldData(seed, spawnX, spawnZ);
-    }
-
-    @Override
-    public void toBytes(ByteBuf buf) {
-        buf.writeLong(worldData.getSeed());
-        buf.writeInt(worldData.getSpawnX());
-        buf.writeInt(worldData.getSpawnZ());
-    }
-
-    WorldData getWorldData() {
-        return worldData;
-    }
-}
diff --git a/java/com/irtimaled/bbor/forge/messages/InitializeClientMessageHandler.java b/java/com/irtimaled/bbor/forge/messages/InitializeClientMessageHandler.java
deleted file mode 100644 (file)
index 176231a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.irtimaled.bbor.forge.messages;
-
-import com.irtimaled.bbor.common.models.WorldData;
-import com.irtimaled.bbor.forge.ForgeMod;
-import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
-import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
-import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
-
-public class InitializeClientMessageHandler implements IMessageHandler<InitializeClientMessage, IMessage> {
-    @Override
-    public IMessage onMessage(InitializeClientMessage message, MessageContext ctx) {
-        WorldData worldData = message.getWorldData();
-        ForgeMod.proxy.setWorldData(worldData.getSeed(), worldData.getSpawnX(), worldData.getSpawnZ());
-        return null;
-    }
-}
diff --git a/java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessage.java b/java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessage.java
deleted file mode 100644 (file)
index 283dbe1..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.irtimaled.bbor.forge.messages;
-
-import com.irtimaled.bbor.common.models.BoundingBox;
-import io.netty.buffer.ByteBuf;
-import net.minecraft.world.DimensionType;
-import net.minecraftforge.fml.common.network.ByteBufUtils;
-import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
-
-public class RemoveBoundingBoxMessage implements IMessage {
-    private DimensionType dimensionType;
-    private BoundingBox key;
-
-    public static RemoveBoundingBoxMessage from(DimensionType dimensionType, BoundingBox key) {
-        RemoveBoundingBoxMessage message = new RemoveBoundingBoxMessage();
-        message.dimensionType = dimensionType;
-        message.key = key;
-        return message;
-    }
-
-    @Override
-    public void fromBytes(ByteBuf buf) {
-        dimensionType = DimensionType.getById(ByteBufUtils.readVarInt(buf, 5));
-        key = BoundingBoxDeserializer.deserialize(buf);
-    }
-
-    @Override
-    public void toBytes(ByteBuf buf) {
-        ByteBufUtils.writeVarInt(buf, dimensionType.getId(), 5);
-        BoundingBoxSerializer.serialize(key, buf);
-    }
-
-    public DimensionType getDimensionType() {
-        return dimensionType;
-    }
-
-    BoundingBox getKey() {
-        return key;
-    }
-}
diff --git a/java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessageHandler.java b/java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessageHandler.java
deleted file mode 100644 (file)
index 58c972c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.irtimaled.bbor.forge.messages;
-
-import com.irtimaled.bbor.forge.ForgeMod;
-import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
-import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
-import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
-
-public class RemoveBoundingBoxMessageHandler implements IMessageHandler<RemoveBoundingBoxMessage, IMessage> {
-    @Override
-    public IMessage onMessage(RemoveBoundingBoxMessage message, MessageContext ctx) {
-        ForgeMod.proxy.removeBoundingBox(message.getDimensionType(), message.getKey());
-        return null;
-    }
-}
diff --git a/java/com/irtimaled/bbor/litemod/LiteMod.java b/java/com/irtimaled/bbor/litemod/LiteMod.java
deleted file mode 100755 (executable)
index bdd1f86..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.irtimaled.bbor.litemod;
-
-import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
-import com.mumfrey.liteloader.Tickable;
-import net.minecraft.client.Minecraft;
-
-import java.io.File;
-
-public class LiteMod implements Tickable  {
-    public LiteMod() {
-    }
-
-    @Override
-    public String getName() {
-        return "BoundingBoxOutlineReloaded";
-    }
-
-    @Override
-    public String getVersion() {
-        return "1.0.1";
-    }
-
-    @Override
-    public void init(File configPath) {
-        BoundingBoxOutlineReloaded.init();
-    }
-
-    @Override
-    public void upgradeSettings(String version, File configPath, File oldConfigPath) {
-    }
-
-    @Override
-    public void onTick(Minecraft minecraft, float partialTicks, boolean inGame, boolean clock) {
-        BoundingBoxOutlineReloaded.keyPressed();
-    }
-}
diff --git a/java/com/irtimaled/bbor/litemod/mixins/MixinChunk.java b/java/com/irtimaled/bbor/litemod/mixins/MixinChunk.java
deleted file mode 100644 (file)
index eadba89..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.irtimaled.bbor.litemod.mixins;
-
-import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
-import net.minecraft.world.chunk.Chunk;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-
-@Mixin(Chunk.class)
-public abstract class MixinChunk {
-    @Inject(method = "onLoad",
-            at = @At("RETURN"))
-    private void onLoaded(CallbackInfo ci) {
-        BoundingBoxOutlineReloaded.chunkLoaded((Chunk)(Object)this);
-    }
-}
\ No newline at end of file
diff --git a/java/com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer.java b/java/com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer.java
deleted file mode 100644 (file)
index 9833c42..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.irtimaled.bbor.litemod.mixins;
-
-import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
-import com.mumfrey.liteloader.client.overlays.IEntityRenderer;
-import net.minecraft.client.renderer.EntityRenderer;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-
-@Mixin(EntityRenderer.class)
-public abstract class MixinEntityRenderer implements IEntityRenderer {
-    @Inject(method = "renderWorldPass",
-            at = @At(shift = At.Shift.BEFORE,
-                    value = "INVOKE_STRING",
-                    target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V",
-                    args = "ldc=hand"))
-    private void onRenderHand(int pass, float partialTicks, long timeSlice, CallbackInfo ci) {
-        BoundingBoxOutlineReloaded.render(partialTicks);
-    }
-}
\ No newline at end of file
diff --git a/java/com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer.java b/java/com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer.java
deleted file mode 100755 (executable)
index e23c038..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.irtimaled.bbor.litemod.mixins;
-
-import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
-import net.minecraft.server.MinecraftServer;
-import net.minecraft.server.integrated.IntegratedServer;
-import net.minecraft.world.World;
-import net.minecraft.world.WorldType;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-
-@Mixin(IntegratedServer.class)
-public abstract class MixinIntegratedServer extends MinecraftServer {
-    public MixinIntegratedServer() {
-        super(null, null, null, null, null, null, null);
-    }
-
-    @Inject(method = "loadAllWorlds",
-            at = @At("RETURN"),
-            remap = false)
-    private void onLoadAllWorlds(String saveName, String worldNameIn, long seed, WorldType type, String generatorOptions, CallbackInfo ci) {
-        for (World world : this.worlds) {
-            BoundingBoxOutlineReloaded.worldLoaded(world);
-        }
-    }
-}
\ No newline at end of file
diff --git a/java/com/irtimaled/bbor/litemod/mixins/MixinKeyBinding.java b/java/com/irtimaled/bbor/litemod/mixins/MixinKeyBinding.java
deleted file mode 100644 (file)
index b7bd818..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.irtimaled.bbor.litemod.mixins;
-
-import net.minecraft.client.resources.I18n;
-import net.minecraft.client.settings.KeyBinding;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.Overwrite;
-import org.spongepowered.asm.mixin.Shadow;
-
-import java.util.Map;
-
-@Mixin(KeyBinding.class)
-public abstract class MixinKeyBinding implements Comparable<KeyBinding> {
-    @Shadow
-    private static Map<String, Integer> CATEGORY_ORDER;
-
-    @Shadow
-    private String keyDescription;
-
-    @Shadow
-    private String keyCategory;
-
-    @Overwrite()
-    public int compareTo(KeyBinding p_compareTo_1_) {
-        return this.keyCategory.equals(p_compareTo_1_.getKeyCategory()) ? I18n.format(this.keyDescription).compareTo(I18n.format(p_compareTo_1_.getKeyDescription())) : ((Integer) CATEGORY_ORDER.getOrDefault(this.keyCategory, 0)).compareTo(CATEGORY_ORDER.getOrDefault(p_compareTo_1_.getKeyCategory(), 0));
-    }
-}
diff --git a/java/com/irtimaled/bbor/litemod/mixins/MixinNetworkManager.java b/java/com/irtimaled/bbor/litemod/mixins/MixinNetworkManager.java
deleted file mode 100644 (file)
index e108bc2..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.irtimaled.bbor.litemod.mixins;
-
-import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
-import net.minecraft.network.NetworkManager;
-import net.minecraft.network.Packet;
-import net.minecraft.network.login.client.CPacketLoginStart;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-
-@Mixin(NetworkManager.class)
-public abstract class MixinNetworkManager {
-    @Inject(method = "sendPacket(Lnet/minecraft/network/Packet;)V",
-            at = @At("RETURN"))
-    private void onLoaded(Packet<?> packetIn, CallbackInfo ci) {
-        if (packetIn instanceof CPacketLoginStart) {
-            BoundingBoxOutlineReloaded.playerConnectedToServer((NetworkManager)(Object)this);
-        }
-    }
-}
\ No newline at end of file
diff --git a/java/com/irtimaled/bbor/litemod/mixins/MixinWorldClient.java b/java/com/irtimaled/bbor/litemod/mixins/MixinWorldClient.java
deleted file mode 100644 (file)
index e03412c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.irtimaled.bbor.litemod.mixins;
-
-import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
-import net.minecraft.client.multiplayer.WorldClient;
-import net.minecraft.world.World;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-
-@Mixin(WorldClient.class)
-public abstract class MixinWorldClient extends World {
-    public MixinWorldClient() {
-        super(null, null, null, null, true);
-    }
-
-    @Inject(method = "sendQuittingDisconnectingPacket",
-    at = @At("RETURN"))
-    private void onDisconnecting(CallbackInfo ci) {
-        BoundingBoxOutlineReloaded.playerDisconnectedFromServer();
-    }
-}
diff --git a/patches/net.minecraft.client.Minecraft.java.patch b/patches/net.minecraft.client.Minecraft.java.patch
deleted file mode 100644 (file)
index c87d6ab..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-diff -r -u a/net/minecraft/client/Minecraft.java b/net/minecraft/client/Minecraft.java
---- a/net/minecraft/client/Minecraft.java 2017-09-27 12:01:40.000000000 -0700
-+++ b/net/minecraft/client/Minecraft.java 2017-09-27 11:30:01.000000000 -0700
-@@ -643,6 +643,8 @@
-         }
-         this.renderGlobal.makeEntityOutlineShader();
-+
-+        com.irtimaled.bbor.BoundingBoxOutlineReloaded.init();
-     }
-     /**
-@@ -2276,6 +2278,8 @@
-             this.gameSettings.smoothCamera = !this.gameSettings.smoothCamera;
-         }
-+        com.irtimaled.bbor.BoundingBoxOutlineReloaded.keyPressed();
-+
-         for (int i = 0; i < 9; ++i)
-         {
-             boolean flag = this.gameSettings.keyBindSaveToolbar.isKeyDown();
diff --git a/patches/net.minecraft.client.multiplayer.WorldClient.java.patch b/patches/net.minecraft.client.multiplayer.WorldClient.java.patch
deleted file mode 100644 (file)
index 4cf1fa3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-diff -r -u a/net/minecraft/client/multiplayer/WorldClient.java b/net/minecraft/client/multiplayer/WorldClient.java
---- a/net/minecraft/client/multiplayer/WorldClient.java 2017-09-27 12:01:40.000000000 -0700
-+++ b/net/minecraft/client/multiplayer/WorldClient.java 2017-09-27 11:53:37.000000000 -0700
-@@ -320,6 +320,7 @@
-     public void sendQuittingDisconnectingPacket()
-     {
-         this.connection.getNetworkManager().closeChannel(new TextComponentString("Quitting"));
-+        com.irtimaled.bbor.BoundingBoxOutlineReloaded.playerDisconnectedFromServer();
-     }
-     /**
diff --git a/patches/net.minecraft.client.renderer.EntityRenderer.java.patch b/patches/net.minecraft.client.renderer.EntityRenderer.java.patch
deleted file mode 100644 (file)
index 64061ff..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -r -u a/net/minecraft/client/renderer/EntityRenderer.java b/net/minecraft/client/renderer/EntityRenderer.java
---- a/net/minecraft/client/renderer/EntityRenderer.java 2017-09-27 12:01:40.000000000 -0700
-+++ b/net/minecraft/client/renderer/EntityRenderer.java 2017-09-27 11:53:37.000000000 -0700
-@@ -1483,6 +1483,8 @@
-             this.renderCloudsCheck(renderglobal, partialTicks, pass, d0, d1, d2);
-         }
-+        com.irtimaled.bbor.BoundingBoxOutlineReloaded.render(partialTicks);
-+
-         this.mc.mcProfiler.endStartSection("hand");
-         if (this.renderHand)
diff --git a/patches/net.minecraft.client.settings.KeyBinding.java.patch b/patches/net.minecraft.client.settings.KeyBinding.java.patch
deleted file mode 100644 (file)
index 61d3792..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-diff -r -u a/net/minecraft/client/settings/KeyBinding.java b/net/minecraft/client/settings/KeyBinding.java
---- a/net/minecraft/client/settings/KeyBinding.java 2017-09-27 12:01:40.000000000 -0700
-+++ b/net/minecraft/client/settings/KeyBinding.java 2017-09-27 11:52:47.000000000 -0700
-@@ -184,5 +184,6 @@
-         CATEGORY_ORDER.put("key.categories.multiplayer", Integer.valueOf(5));
-         CATEGORY_ORDER.put("key.categories.ui", Integer.valueOf(6));
-         CATEGORY_ORDER.put("key.categories.misc", Integer.valueOf(7));
-+        CATEGORY_ORDER.put("Bounding Box Outline Reloaded", Integer.valueOf(0));
-     }
- }
diff --git a/patches/net.minecraft.network.NetworkManager.java.patch b/patches/net.minecraft.network.NetworkManager.java.patch
deleted file mode 100644 (file)
index bf165f8..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-diff -r -u a/net/minecraft/network/NetworkManager.java b/net/minecraft/network/NetworkManager.java
---- a/net/minecraft/network/NetworkManager.java 2017-09-27 12:01:41.000000000 -0700
-+++ b/net/minecraft/network/NetworkManager.java 2017-09-27 11:53:38.000000000 -0700
-@@ -32,6 +32,7 @@
- import java.util.concurrent.locks.ReentrantReadWriteLock;
- import javax.annotation.Nullable;
- import javax.crypto.SecretKey;
-+import net.minecraft.network.login.client.CPacketLoginStart;
- import net.minecraft.util.CryptManager;
- import net.minecraft.util.ITickable;
- import net.minecraft.util.LazyLoadBase;
-@@ -188,6 +189,10 @@
-                 this.readWriteLock.writeLock().unlock();
-             }
-         }
-+
-+        if (packetIn instanceof CPacketLoginStart) {
-+            com.irtimaled.bbor.BoundingBoxOutlineReloaded.playerConnectedToServer(this);
-+        }
-     }
-     public void sendPacket(Packet<?> packetIn, GenericFutureListener <? extends Future <? super Void >> listener, GenericFutureListener <? extends Future <? super Void >> ... listeners)
diff --git a/patches/net.minecraft.server.integrated.IntegratedServer.java.patch b/patches/net.minecraft.server.integrated.IntegratedServer.java.patch
deleted file mode 100644 (file)
index 1f36b77..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -r -u a/net/minecraft/server/integrated/IntegratedServer.java b/net/minecraft/server/integrated/IntegratedServer.java
---- a/net/minecraft/server/integrated/IntegratedServer.java 2017-09-27 12:01:41.000000000 -0700
-+++ b/net/minecraft/server/integrated/IntegratedServer.java 2017-09-27 11:37:50.000000000 -0700
-@@ -114,6 +114,8 @@
-                 this.worlds[i] = (WorldServer)(new WorldServerMulti(this, isavehandler, j, this.worlds[0], this.profiler)).init();
-             }
-+            com.irtimaled.bbor.BoundingBoxOutlineReloaded.worldLoaded(this.worlds[i]);
-+
-             this.worlds[i].addEventListener(new ServerWorldEventHandler(this, this.worlds[i]));
-         }
diff --git a/patches/net.minecraft.world.chunk.Chunk.java.patch b/patches/net.minecraft.world.chunk.Chunk.java.patch
deleted file mode 100644 (file)
index 52d41ba..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-diff -r -u a/net/minecraft/world/chunk/Chunk.java b/net/minecraft/world/chunk/Chunk.java
---- a/net/minecraft/world/chunk/Chunk.java  2017-09-27 12:01:41.000000000 -0700
-+++ b/net/minecraft/world/chunk/Chunk.java  2017-09-27 11:34:42.000000000 -0700
-@@ -935,6 +935,7 @@
-         {
-             this.world.loadEntities(classinheritancemultimap);
-         }
-+        com.irtimaled.bbor.BoundingBoxOutlineReloaded.chunkLoaded(this);
-     }
-     /**
diff --git a/resources/litemod.json b/resources/litemod.json
deleted file mode 100755 (executable)
index ad93565..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name": "bbor",
-  "displayName": "BoundingBoxOutlineReloaded",
-  "description": "Shows the bounding boxes of structures and features.",
-  "version": "1.0.1",
-  "author": "irtimaled",
-  "mcversion": "1.12.1",
-  "mixinConfigs": [
-    "mixins.bbor.json"
-  ]
-}
diff --git a/resources/mcmod.info b/resources/mcmod.info
deleted file mode 100644 (file)
index 39c6045..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-[
-{
-  "modid": "bbor",
-  "name": "Bounding Box Outline Reloaded",
-  "description": "Shows the bounding boxes of structures and features.",
-  "version": "${version}",
-  "mcversion": "${mcversion}",
-  "url": "http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-mods/2345401",
-  "updateUrl": "",
-  "authorList": ["irtimaled"],
-  "credits": "Thanks to 4poc & KaboPC.",
-  "logoFile": "",
-  "screenshots": [],
-  "dependencies": []
-}
-]
-
diff --git a/resources/mixins.bbor.json b/resources/mixins.bbor.json
deleted file mode 100644 (file)
index 8c7a41b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "required": true,
-  "minVersion": "0.7.3",
-  "compatibilityLevel": "JAVA_8",
-  "target": "@env(DEFAULT)",
-  "package": "com.irtimaled.bbor.litemod.mixins",
-  "refmap": "mixins.bbor.refmap.json",
-  "mixins": [
-    "MixinIntegratedServer",
-    "MixinEntityRenderer",
-    "MixinChunk",
-    "MixinNetworkManager",
-    "MixinWorldClient",
-    "MixinKeyBinding"
-  ],
-  "injectors": {
-    "defaultRequire": 1
-  }
-}
diff --git a/resources/mixins.bbor.refmap.json b/resources/mixins.bbor.refmap.json
deleted file mode 100644 (file)
index 56feab2..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "mappings": {
-    "com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer": {
-      "loadAllWorlds": "Lchd;a(Ljava/lang/String;Ljava/lang/String;JLamz;Ljava/lang/String;)V"
-    },
-    "com/irtimaled/bbor/litemod/mixins/MixinNetworkManager": {
-      "sendPacket(Lnet/minecraft/network/Packet;)V": "Lgw;a(Lht;)V"
-    },
-    "com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer": {
-      "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V": "Lrl;c(Ljava/lang/String;)V",
-      "renderWorldPass": "Lbuq;a(IFJ)V"
-    },
-    "com/irtimaled/bbor/litemod/mixins/MixinWorldClient": {
-      "sendQuittingDisconnectingPacket": "Lbsb;O()V"
-    },
-    "com/irtimaled/bbor/litemod/mixins/MixinChunk": {
-      "onLoad": "Laxw;c()V"
-    },
-    "com/irtimaled/bbor/litemod/mixins/MixinKeyBinding": {
-      "compareTo": "Lbhy;a(Lbhy;)I"
-    }
-  },
-  "data": {
-    "notch": {
-      "com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer": {
-        "loadAllWorlds": "Lchd;a(Ljava/lang/String;Ljava/lang/String;JLamz;Ljava/lang/String;)V"
-      },
-      "com/irtimaled/bbor/litemod/mixins/MixinNetworkManager": {
-        "sendPacket(Lnet/minecraft/network/Packet;)V": "Lgw;a(Lht;)V"
-      },
-      "com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer": {
-        "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V": "Lrl;c(Ljava/lang/String;)V",
-        "renderWorldPass": "Lbuq;a(IFJ)V"
-      },
-      "com/irtimaled/bbor/litemod/mixins/MixinWorldClient": {
-        "sendQuittingDisconnectingPacket": "Lbsb;O()V"
-      },
-      "com/irtimaled/bbor/litemod/mixins/MixinChunk": {
-        "onLoad": "Laxw;c()V"
-      },
-      "com/irtimaled/bbor/litemod/mixins/MixinKeyBinding": {
-        "compareTo": "Lbhy;a(Lbhy;)I"
-      }
-    },
-    "searge": {
-      "com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer": {
-        "loadAllWorlds": "Lnet/minecraft/server/integrated/IntegratedServer;func_71247_a(Ljava/lang/String;Ljava/lang/String;JLnet/minecraft/world/WorldType;Ljava/lang/String;)V"
-      },
-      "com/irtimaled/bbor/litemod/mixins/MixinNetworkManager": {
-        "sendPacket(Lnet/minecraft/network/Packet;)V": "Lnet/minecraft/network/NetworkManager;func_179290_a(Lnet/minecraft/network/Packet;)V"
-      },
-      "com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer": {
-        "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V": "Lnet/minecraft/profiler/Profiler;func_76318_c(Ljava/lang/String;)V",
-        "renderWorldPass": "Lnet/minecraft/client/renderer/EntityRenderer;func_175068_a(IFJ)V"
-      },
-      "com/irtimaled/bbor/litemod/mixins/MixinWorldClient": {
-        "sendQuittingDisconnectingPacket": "Lnet/minecraft/client/multiplayer/WorldClient;func_72882_A()V"
-      },
-      "com/irtimaled/bbor/litemod/mixins/MixinChunk": {
-        "onLoad": "Lnet/minecraft/world/chunk/Chunk;func_76631_c()V"
-      },
-      "com/irtimaled/bbor/litemod/mixins/MixinKeyBinding": {
-        "compareTo": "Lnet/minecraft/client/settings/KeyBinding;compareTo(Lnet/minecraft/client/settings/KeyBinding;)I"
-      }
-    }
-  }
-}
diff --git a/resources/pack.mcmeta b/resources/pack.mcmeta
deleted file mode 100644 (file)
index c00c642..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-    "pack": {
-        "description": "bbor resources",
-        "pack_format": 3,
-        "_comment": "A pack_format of 3 should be used starting with Minecraft 1.11. All resources, including language files, should be lowercase (eg: en_us.lang). A pack_format of 2 will load your mod resources with LegacyV2Adapter, which requires language files to have uppercase letters (eg: en_US.lang)."
-    }
-}
diff --git a/src/main/java/com/irtimaled/bbor/Logger.java b/src/main/java/com/irtimaled/bbor/Logger.java
new file mode 100644 (file)
index 0000000..d19550b
--- /dev/null
@@ -0,0 +1,15 @@
+package com.irtimaled.bbor;
+
+import org.apache.logging.log4j.LogManager;
+
+public class Logger {
+    private static final org.apache.logging.log4j.Logger logger = LogManager.getLogger();
+
+    public static void info(String s, Object... objects) {
+        if (objects.length == 0) {
+            logger.info(s);
+        } else {
+            logger.info(String.format(s, objects));
+        }
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/ReflectionHelper.java b/src/main/java/com/irtimaled/bbor/ReflectionHelper.java
new file mode 100644 (file)
index 0000000..2bd0a41
--- /dev/null
@@ -0,0 +1,46 @@
+package com.irtimaled.bbor;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ReflectionHelper {
+    public static <T, R> R getPrivateValue(Class<T> sourceClass, T instance, Class<R> resultClass) {
+        try {
+            Field f = getField(sourceClass, resultClass);
+            if (f != null) {
+                return (R) f.get(instance);
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
+
+    private static Map<Class, Map<Class, Field>> fieldMap = new HashMap<>();
+
+    private static <T, R> Field getField(Class<T> sourceClass, Class<R> resultClass) {
+        Map<Class, Field> map = fieldMap.computeIfAbsent(sourceClass, k -> new HashMap<>());
+        Field field = map.get(resultClass);
+        if (field == null) {
+            field = getFieldUsingReflection(sourceClass, resultClass);
+            if (field != null) {
+                field.setAccessible(true);
+                map.put(resultClass, field);
+            }
+        }
+        return field;
+    }
+
+    private static <T, R> Field getFieldUsingReflection(Class<T> sourceClass, Class<R> resultClass) {
+        Field[] fields = sourceClass.getDeclaredFields();
+        for (Field field : fields) {
+            if (field.getType().equals(resultClass))
+                return field;
+        }
+        for (Field field : fields) {
+            if (resultClass.isAssignableFrom(field.getType()))
+                return field;
+        }
+        return null;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/BoundingBoxOutlineReloaded.java b/src/main/java/com/irtimaled/bbor/client/BoundingBoxOutlineReloaded.java
new file mode 100644 (file)
index 0000000..06a2603
--- /dev/null
@@ -0,0 +1,44 @@
+package com.irtimaled.bbor.client;
+
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.client.Minecraft;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+
+import java.io.File;
+
+public class BoundingBoxOutlineReloaded {
+    private static ClientProxy proxy;
+
+    public static void init() {
+        ConfigManager.loadConfig(new File(Minecraft.getMinecraft().mcDataDir, "config"));
+        proxy = new ClientProxy();
+        proxy.init();
+    }
+
+    public static void chunkLoaded(Chunk chunk) {
+        proxy.chunkLoaded(chunk);
+    }
+
+    public static void worldLoaded(World world) {
+        proxy.worldLoaded(world);
+    }
+
+    public static void keyPressed() {
+        proxy.keyPressed();
+    }
+
+    public static void render(float partialTicks) {
+        proxy.tick();
+        proxy.render(partialTicks);
+    }
+
+    public static void playerConnectedToServer(NetworkManager networkManager) {
+        proxy.playerConnectedToServer(networkManager);
+    }
+
+    public static void playerDisconnectedFromServer() {
+        proxy.playerDisconnectedFromServer();
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/ClientBoundingBoxProvider.java b/src/main/java/com/irtimaled/bbor/client/ClientBoundingBoxProvider.java
new file mode 100644 (file)
index 0000000..423df09
--- /dev/null
@@ -0,0 +1,129 @@
+package com.irtimaled.bbor.client;
+
+import com.irtimaled.bbor.common.BoundingBoxCache;
+import com.irtimaled.bbor.common.models.BoundingBox;
+import com.irtimaled.bbor.common.models.BoundingBoxSlimeChunk;
+import com.irtimaled.bbor.common.models.BoundingBoxWorldSpawn;
+import com.irtimaled.bbor.common.models.WorldData;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.multiplayer.WorldClient;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.ChunkPos;
+import net.minecraft.util.math.MathHelper;
+import net.minecraft.world.DimensionType;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.Random;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+class ClientBoundingBoxProvider {
+    private final ClientDimensionCache dimensionCache;
+
+    ClientBoundingBoxProvider(ClientDimensionCache dimensionCache) {
+        this.dimensionCache = dimensionCache;
+    }
+
+    Set<BoundingBox> getBoundingBoxes(DimensionType dimensionType, Boolean outerBoxOnly, WorldClient world) {
+        Set<BoundingBox> boundingBoxes = getClientBoundingBoxes(dimensionType);
+        BoundingBoxCache boundingBoxCache = dimensionCache.getBoundingBoxes(dimensionType);
+        if (boundingBoxCache != null) {
+            if (outerBoxOnly) {
+                boundingBoxes.addAll(boundingBoxCache.getBoundingBoxes().keySet());
+            } else {
+                boundingBoxCache.getBoundingBoxes()
+                        .values()
+                        .forEach(boundingBoxes::addAll);
+            }
+        }
+
+        return boundingBoxes.stream()
+                .filter(bb -> world.isAreaLoaded(bb.getMinBlockPos(), bb.getMaxBlockPos()))
+                .collect(Collectors.toSet());
+    }
+
+    private Set<BoundingBox> getClientBoundingBoxes(DimensionType dimensionType) {
+        WorldData worldData = dimensionCache.getWorldData();
+
+        Set<BoundingBox> boundingBoxes = new HashSet<>();
+        if (worldData != null && dimensionType == DimensionType.OVERWORLD) {
+            if (ConfigManager.drawWorldSpawn.getBoolean()) {
+                boundingBoxes.add(getWorldSpawnBoundingBox(worldData.getSpawnX(), worldData.getSpawnZ()));
+                boundingBoxes.add(buildSpawnChunksBoundingBox(worldData.getSpawnX(), worldData.getSpawnZ()));
+            }
+            if (ConfigManager.drawLazySpawnChunks.getBoolean()) {
+                boundingBoxes.add(getLazySpawnChunksBoundingBox(worldData.getSpawnX(), worldData.getSpawnZ()));
+            }
+            if (ConfigManager.drawSlimeChunks.getBoolean()) {
+                boundingBoxes.addAll(this.getSlimeChunks());
+            }
+        }
+        return boundingBoxes;
+    }
+
+    private Set<BoundingBoxSlimeChunk> getSlimeChunks() {
+        Minecraft minecraft = Minecraft.getMinecraft();
+        int renderDistanceChunks = minecraft.gameSettings.renderDistanceChunks;
+        int playerChunkX = MathHelper.floor(minecraft.player.posX / 16.0D);
+        int playerChunkZ = MathHelper.floor(minecraft.player.posZ / 16.0D);
+        Set<BoundingBoxSlimeChunk> slimeChunks = new HashSet<>();
+        for (int chunkX = playerChunkX - renderDistanceChunks; chunkX <= playerChunkX + renderDistanceChunks; ++chunkX) {
+            for (int chunkZ = playerChunkZ - renderDistanceChunks; chunkZ <= playerChunkZ + renderDistanceChunks; ++chunkZ) {
+                if (isSlimeChunk(chunkX, chunkZ)) {
+                    ChunkPos chunk = new ChunkPos(chunkX, chunkZ);
+                    BlockPos minBlockPos = new BlockPos(chunk.getXStart(), 1, chunk.getZStart());
+                    BlockPos maxBlockPos = new BlockPos(chunk.getXEnd(), 38, chunk.getZEnd());
+                    if (minecraft.world.isAreaLoaded(minBlockPos, maxBlockPos)) {
+                        slimeChunks.add(BoundingBoxSlimeChunk.from(minBlockPos, maxBlockPos, Color.GREEN));
+                    }
+                }
+            }
+        }
+        return slimeChunks;
+    }
+
+    private boolean isSlimeChunk(int chunkX, int chunkZ) {
+        WorldData worldData = dimensionCache.getWorldData();
+        Random r = new Random(worldData.getSeed() +
+                (long) (chunkX * chunkX * 4987142) +
+                (long) (chunkX * 5947611) +
+                (long) (chunkZ * chunkZ) * 4392871L +
+                (long) (chunkZ * 389711) ^ 987234911L);
+        return r.nextInt(10) == 0;
+    }
+
+    private BoundingBox buildSpawnChunksBoundingBox(int spawnX, int spawnZ) {
+        return dimensionCache.getOrSetSpawnChunks(() -> buildSpawnChunksBoundingBox(spawnX, spawnZ, 12));
+    }
+
+    private BoundingBox getLazySpawnChunksBoundingBox(int spawnX, int spawnZ) {
+        return dimensionCache.getOrSetLazySpawnChunks(() -> buildSpawnChunksBoundingBox(spawnX, spawnZ, 16));
+    }
+
+    private BoundingBox buildSpawnChunksBoundingBox(int spawnX, int spawnZ, int size) {
+        double chunkSize = 16;
+        double midOffset = chunkSize * (size / 2);
+        double midX = Math.round((float) (spawnX / chunkSize)) * chunkSize;
+        double midZ = Math.round((float) (spawnZ / chunkSize)) * chunkSize;
+        BlockPos minBlockPos = new BlockPos(midX - midOffset, 0, midZ - midOffset);
+        if (spawnX / chunkSize % 0.5D == 0.0D && spawnZ / chunkSize % 0.5D == 0.0D) {
+            midX += chunkSize;
+            midZ += chunkSize;
+        }
+        BlockPos maxBlockPos = new BlockPos(midX + midOffset, 0, midZ + midOffset);
+        return BoundingBoxWorldSpawn.from(minBlockPos, maxBlockPos, Color.RED);
+    }
+
+    private BoundingBox getWorldSpawnBoundingBox(int spawnX, int spawnZ) {
+        return dimensionCache.getOrSetWorldSpawn(() -> buildWorldSpawnBoundingBox(spawnX, spawnZ));
+    }
+
+    private BoundingBox buildWorldSpawnBoundingBox(int spawnX, int spawnZ) {
+        BlockPos minBlockPos = new BlockPos(spawnX - 10, 0, spawnZ - 10);
+        BlockPos maxBlockPos = new BlockPos(spawnX + 10, 0, spawnZ + 10);
+
+        return BoundingBoxWorldSpawn.from(minBlockPos, maxBlockPos, Color.RED);
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/ClientDimensionCache.java b/src/main/java/com/irtimaled/bbor/client/ClientDimensionCache.java
new file mode 100644 (file)
index 0000000..df7ec18
--- /dev/null
@@ -0,0 +1,51 @@
+package com.irtimaled.bbor.client;
+
+import com.irtimaled.bbor.common.DimensionCache;
+import com.irtimaled.bbor.common.models.BoundingBox;
+
+import java.util.function.Supplier;
+
+public class ClientDimensionCache extends DimensionCache {
+    private BoundingBox worldSpawnBoundingBox;
+    private BoundingBox spawnChunksBoundingBox;
+    private BoundingBox lazySpawnChunksBoundingBox;
+
+    @Override
+    public void setWorldData(long seed, int spawnX, int spawnZ) {
+        clearClientCache();
+        super.setWorldData(seed, spawnX, spawnZ);
+    }
+
+    @Override
+    public void clear() {
+        clearClientCache();
+        super.clear();
+    }
+
+    private void clearClientCache() {
+        worldSpawnBoundingBox = null;
+        spawnChunksBoundingBox = null;
+        lazySpawnChunksBoundingBox = null;
+    }
+
+    BoundingBox getOrSetSpawnChunks(Supplier<BoundingBox> defaultSupplier) {
+        if(spawnChunksBoundingBox == null) {
+            spawnChunksBoundingBox = defaultSupplier.get();
+        }
+        return spawnChunksBoundingBox;
+    }
+
+    BoundingBox getOrSetLazySpawnChunks(Supplier<BoundingBox> defaultSupplier) {
+        if(lazySpawnChunksBoundingBox == null) {
+            lazySpawnChunksBoundingBox = defaultSupplier.get();
+        }
+        return lazySpawnChunksBoundingBox;
+    }
+
+    BoundingBox getOrSetWorldSpawn(Supplier<BoundingBox> defaultSupplier) {
+        if(worldSpawnBoundingBox == null) {
+            worldSpawnBoundingBox = defaultSupplier.get();
+        }
+        return worldSpawnBoundingBox;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/ClientProxy.java b/src/main/java/com/irtimaled/bbor/client/ClientProxy.java
new file mode 100644 (file)
index 0000000..22eb4ff
--- /dev/null
@@ -0,0 +1,88 @@
+package com.irtimaled.bbor.client;
+
+import com.irtimaled.bbor.common.CommonProxy;
+import com.irtimaled.bbor.common.VillageColorCache;
+import com.irtimaled.bbor.common.VillageProcessor;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.settings.KeyBinding;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.world.DimensionType;
+import org.apache.commons.lang3.ArrayUtils;
+import org.lwjgl.input.Keyboard;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+public class ClientProxy extends CommonProxy {
+    private boolean active;
+    private boolean outerBoxOnly;
+    private KeyBinding activeHotKey;
+    private KeyBinding outerBoxOnlyHotKey;
+    private ClientRenderer renderer;
+    private int remoteUserCount = 0;
+
+    public void keyPressed() {
+        if (activeHotKey.isPressed()) {
+            active = !active;
+            if (active)
+                PlayerData.setActiveY();
+        } else if (outerBoxOnlyHotKey.isPressed()) {
+            outerBoxOnly = !outerBoxOnly;
+        }
+    }
+
+    @Override
+    public void init() {
+        String category = "Bounding Box Outline Reloaded";
+        activeHotKey = new KeyBinding("Toggle On/Off", Keyboard.KEY_B, category);
+        outerBoxOnlyHotKey = new KeyBinding("Toggle Display Outer Box Only", Keyboard.KEY_O, category);
+        Minecraft.getMinecraft().gameSettings.keyBindings = ArrayUtils.addAll(Minecraft.getMinecraft().gameSettings.keyBindings, activeHotKey, outerBoxOnlyHotKey);
+        ClientDimensionCache clientDimensionCache = new ClientDimensionCache();
+        renderer = new ClientRenderer(clientDimensionCache);
+        dimensionCache = clientDimensionCache;
+    }
+
+    public void render(float partialTicks) {
+        EntityPlayer entityPlayer = Minecraft.getMinecraft().player;
+        PlayerData.setPlayerPosition(partialTicks, entityPlayer);
+
+        if (this.active) {
+            renderer.render(DimensionType.getById(entityPlayer.dimension), outerBoxOnly);
+        }
+    }
+
+    public void setRemoteUserCount(int remoteUserCount) {
+        this.remoteUserCount = remoteUserCount;
+    }
+
+    protected boolean hasRemoteUsers()    {
+        return remoteUserCount > 0;
+    }
+
+    @Override
+    public void tick() {
+        if (this.active || this.hasRemoteUsers()) {
+            super.tick();
+        }
+    }
+
+    public void playerConnectedToServer(NetworkManager networkManager) {
+        SocketAddress remoteAddress = networkManager.getRemoteAddress();
+        if (remoteAddress instanceof InetSocketAddress) {
+            InetSocketAddress socketAddress = (InetSocketAddress) remoteAddress;
+            NBTFileParser.loadLocalDatFiles(socketAddress.getHostName(), socketAddress.getPort(), dimensionCache);
+        }
+    }
+
+    public void playerDisconnectedFromServer() {
+        active = false;
+        villageProcessors.forEach(VillageProcessor::close);
+        villageProcessors.clear();
+
+        if (ConfigManager.keepCacheBetweenSessions.getBoolean()) return;
+        VillageColorCache.clear();
+        dimensionCache.clear();
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java b/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java
new file mode 100644 (file)
index 0000000..697c26b
--- /dev/null
@@ -0,0 +1,50 @@
+package com.irtimaled.bbor.client;
+
+import com.irtimaled.bbor.client.renderers.*;
+import com.irtimaled.bbor.common.models.*;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.client.Minecraft;
+import net.minecraft.world.DimensionType;
+import org.lwjgl.opengl.GL11;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class ClientRenderer {
+    private final ClientBoundingBoxProvider clientBoundingBoxProvider;
+    private static final Map<Class<? extends BoundingBox>, Renderer> boundingBoxRendererMap = new HashMap<>();
+
+    ClientRenderer(ClientDimensionCache dimensionCache) {
+        this.clientBoundingBoxProvider = new ClientBoundingBoxProvider(dimensionCache);
+        boundingBoxRendererMap.put(BoundingBoxVillage.class, new VillageRenderer());
+        boundingBoxRendererMap.put(BoundingBoxSlimeChunk.class, new SlimeChunkRenderer());
+        boundingBoxRendererMap.put(BoundingBoxWorldSpawn.class, new WorldSpawnRenderer());
+        boundingBoxRendererMap.put(BoundingBoxStructure.class, new StructureRenderer());
+    }
+
+    public void render(DimensionType dimensionType, Boolean outerBoxesOnly) {
+        Set<BoundingBox> boundingBoxes = clientBoundingBoxProvider.getBoundingBoxes(dimensionType, outerBoxesOnly, Minecraft.getMinecraft().world);
+        if (boundingBoxes == null || boundingBoxes.size() == 0)
+            return;
+
+        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+        GL11.glLineWidth(2.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 : boundingBoxes) {
+            Renderer renderer = boundingBoxRendererMap.get(bb.getClass());
+            if (renderer != null) {
+                renderer.render(bb);
+            }
+        }
+
+        GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
+        GL11.glEnable(GL11.GL_CULL_FACE);
+        GL11.glEnable(GL11.GL_TEXTURE_2D);
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/NBTFileParser.java b/src/main/java/com/irtimaled/bbor/client/NBTFileParser.java
new file mode 100644 (file)
index 0000000..f647d9c
--- /dev/null
@@ -0,0 +1,189 @@
+package com.irtimaled.bbor.client;
+
+import com.irtimaled.bbor.Logger;
+import com.irtimaled.bbor.common.BoundingBoxCache;
+import com.irtimaled.bbor.common.DimensionCache;
+import com.irtimaled.bbor.common.StructureType;
+import com.irtimaled.bbor.common.models.BoundingBox;
+import com.irtimaled.bbor.common.models.BoundingBoxStructure;
+import com.irtimaled.bbor.common.models.BoundingBoxVillage;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.nbt.CompressedStreamTools;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.DimensionType;
+
+import java.awt.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+class NBTFileParser {
+    static void loadLocalDatFiles(String host, int port, DimensionCache dimensionCache) {
+        Logger.info("Looking for local structures (host:port=%s:%d)", host, port);
+        String path = String.format("BBOutlineReloaded%s%s%s%d", File.separator, host, File.separator, port);
+        File localStructuresFolder = new File(ConfigManager.configDir, path);
+        Logger.info("Looking for local structures (folder=%s)", localStructuresFolder.getAbsolutePath());
+        if (!localStructuresFolder.exists()) {
+            path = String.format("BBOutlineReloaded%s%s", File.separator, host);
+            localStructuresFolder = new File(ConfigManager.configDir, path);
+            Logger.info("Looking for local structures (folder=%s)", localStructuresFolder.getAbsolutePath());
+        }
+        if (!localStructuresFolder.exists()) {
+            path = String.format("BBOutlineReloaded%s%s,%d", File.separator, host, port);
+            localStructuresFolder = new File(ConfigManager.configDir, path);
+            Logger.info("Looking for local structures (folder=%s)", localStructuresFolder.getAbsolutePath());
+        }
+        if (!localStructuresFolder.exists()) {
+            Logger.info("No local structures folders found");
+            return;
+        }
+        loadWorldData(localStructuresFolder, dimensionCache);
+        populateBoundingBoxCache(localStructuresFolder, dimensionCache);
+    }
+
+    private static void loadWorldData(File localStructuresFolder, DimensionCache dimensionCache) {
+        File file = new File(localStructuresFolder, "level.dat");
+        NBTTagCompound nbt = loadNbtFile(file);
+        if (nbt == null)
+            return;
+
+        NBTTagCompound data = nbt.getCompoundTag("Data");
+        long seed = data.getLong("RandomSeed");
+        int spawnX = data.getInteger("SpawnX");
+        int spawnZ = data.getInteger("SpawnZ");
+        Logger.info("Loaded level.dat (seed: %d, spawn: %d,%d)", seed, spawnX, spawnZ);
+        dimensionCache.setWorldData(seed, spawnX, spawnZ);
+    }
+
+    private static void populateBoundingBoxCache(File localStructuresFolder, DimensionCache dimensionCache) {
+        dimensionCache.put(DimensionType.OVERWORLD, loadOverworldStructures(localStructuresFolder));
+        dimensionCache.put(DimensionType.NETHER, loadNetherStructures(localStructuresFolder));
+        dimensionCache.put(DimensionType.THE_END, loadEndStructures(localStructuresFolder));
+    }
+
+    private static BoundingBoxCache loadOverworldStructures(File localStructuresFolder) {
+        BoundingBoxCache cache = new BoundingBoxCache();
+        if (ConfigManager.drawDesertTemples.getBoolean()) {
+            loadStructure(localStructuresFolder, cache, "Temple.dat", StructureType.DesertTemple.getColor(), "TeDP");
+        }
+        if (ConfigManager.drawJungleTemples.getBoolean()) {
+            loadStructure(localStructuresFolder, cache, "Temple.dat", StructureType.JungleTemple.getColor(), "TeJP");
+        }
+        if (ConfigManager.drawWitchHuts.getBoolean()) {
+            loadStructure(localStructuresFolder, cache, "Temple.dat", StructureType.WitchHut.getColor(), "TeSH");
+        }
+        if (ConfigManager.drawOceanMonuments.getBoolean()) {
+            loadStructure(localStructuresFolder, cache, "Monument.dat", StructureType.OceanMonument.getColor(), "*");
+        }
+        if (ConfigManager.drawStrongholds.getBoolean()) {
+            loadStructure(localStructuresFolder, cache, "Stronghold.dat", StructureType.Stronghold.getColor(), "*");
+        }
+        if (ConfigManager.drawMansions.getBoolean()) {
+            loadStructure(localStructuresFolder, cache, "Mansion.dat", StructureType.Mansion.getColor(), "*");
+        }
+        if (ConfigManager.drawMineShafts.getBoolean()) {
+            loadStructure(localStructuresFolder, cache, "Mineshaft.dat", StructureType.MineShaft.getColor(), "*");
+        }
+        if (ConfigManager.drawVillages.getBoolean()) {
+            loadVillages(localStructuresFolder, cache, "Villages.dat");
+        }
+        return cache;
+    }
+
+    private static BoundingBoxCache loadNetherStructures(File localStructuresFolder) {
+        BoundingBoxCache cache = new BoundingBoxCache();
+        if (ConfigManager.drawNetherFortresses.getBoolean())
+            loadStructure(localStructuresFolder, cache, "Fortress.dat", StructureType.NetherFortress.getColor(), "*");
+        if (ConfigManager.drawVillages.getBoolean()) {
+            loadVillages(localStructuresFolder, cache, "villages_nether.dat");
+        }
+        return cache;
+    }
+
+    private static BoundingBoxCache loadEndStructures(File localStructuresFolder) {
+        BoundingBoxCache cache = new BoundingBoxCache();
+        if (ConfigManager.drawVillages.getBoolean()) {
+            loadVillages(localStructuresFolder, cache, "Villages_end.dat");
+        }
+        if (ConfigManager.drawEndCities.getBoolean()) {
+            loadStructure(localStructuresFolder, cache, "EndCity.dat", StructureType.EndCity.getColor(), "*");
+        }
+        return cache;
+    }
+
+    private static void loadStructure(File localStructuresFolder, BoundingBoxCache cache, String fileName, Color color, String id) {
+        File file = new File(localStructuresFolder, fileName);
+        NBTTagCompound nbt = loadNbtFile(file);
+        if (nbt == null)
+            return;
+
+        NBTTagCompound features = nbt.getCompoundTag("data")
+                .getCompoundTag("Features");
+        int loadedStructureCount = 0;
+        for (Object key : features.getKeySet()) {
+            NBTTagCompound feature = features.getCompoundTag((String) key);
+            BoundingBox structure = BoundingBoxStructure.from(feature.getIntArray("BB"), color);
+            Set<BoundingBox> boundingBoxes = new HashSet<>();
+            NBTTagCompound[] children = getChildCompoundTags(feature, "Children");
+            for (NBTTagCompound child : children) {
+                if (id.equals(child.getString("id")) || id.equals("*"))
+                    boundingBoxes.add(BoundingBoxStructure.from(child.getIntArray("BB"), color));
+            }
+            if (boundingBoxes.size() > 0)
+                ++loadedStructureCount;
+            cache.addBoundingBoxes(structure, boundingBoxes);
+        }
+
+        Logger.info("Loaded %s (%d structures with type %s)", fileName, loadedStructureCount, id);
+    }
+
+    private static void loadVillages(File localStructuresFolder, BoundingBoxCache cache, String fileName) {
+        File file = new File(localStructuresFolder, fileName);
+        NBTTagCompound nbt = loadNbtFile(file);
+        if (nbt == null)
+            return;
+
+        NBTTagCompound[] villages = getChildCompoundTags(nbt.getCompoundTag("data"), "Villages");
+        for (NBTTagCompound village : villages) {
+            BlockPos center = new BlockPos(village.getInteger("CX"), village.getInteger("CY"), village.getInteger("CZ"));
+            int radius = village.getInteger("Radius");
+            int population = village.getInteger("PopSize");
+            Set<BlockPos> doors = getDoors(village);
+            BoundingBox boundingBox = BoundingBoxVillage.from(center, radius, village.hashCode(), population, doors);
+            cache.addBoundingBox(boundingBox);
+        }
+
+        Logger.info("Loaded %s (%d villages)", fileName, villages.length);
+    }
+
+    private static Set<BlockPos> getDoors(NBTTagCompound village) {
+        Set<BlockPos> doors = new HashSet<>();
+        for (NBTTagCompound door : getChildCompoundTags(village, "Doors")) {
+            doors.add(new BlockPos(door.getInteger("X"), door.getInteger("Y"), door.getInteger("Z")));
+        }
+        return doors;
+    }
+
+    private static NBTTagCompound loadNbtFile(File file) {
+        if (!file.exists())
+            return null;
+        try {
+            return CompressedStreamTools.readCompressed(new FileInputStream(file));
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+    private static NBTTagCompound[] getChildCompoundTags(NBTTagCompound parent, String key) {
+        NBTTagList tagList = parent.getTagList(key, 10);
+        NBTTagCompound[] result = new NBTTagCompound[tagList.tagCount()];
+        for (int index = 0; index < tagList.tagCount(); index++) {
+            result[index] = tagList.getCompoundTagAt(index);
+        }
+        return result;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/PlayerData.java b/src/main/java/com/irtimaled/bbor/client/PlayerData.java
new file mode 100644 (file)
index 0000000..339d81c
--- /dev/null
@@ -0,0 +1,41 @@
+package com.irtimaled.bbor.client;
+
+import net.minecraft.entity.player.EntityPlayer;
+
+public class PlayerData {
+    private static double x;
+    private static double y;
+    private static double z;
+    private static double activeY;
+
+    static void setPlayerPosition(double partialTicks, EntityPlayer entityPlayer) {
+        x = entityPlayer.lastTickPosX + (entityPlayer.posX - entityPlayer.lastTickPosX) * partialTicks;
+        y = entityPlayer.lastTickPosY + (entityPlayer.posY - entityPlayer.lastTickPosY) * partialTicks;
+        z = entityPlayer.lastTickPosZ + (entityPlayer.posZ - entityPlayer.lastTickPosZ) * partialTicks;
+    }
+
+    static void setActiveY() {
+        activeY = y;
+    }
+
+    public static double getX() {
+        return x;
+    }
+
+    public static double getY() {
+        return y;
+    }
+
+    public static double getZ() {
+        return z;
+    }
+
+    public static double getMaxY(double configMaxY) {
+        if (configMaxY == -1) {
+            return activeY;
+        } else if ((configMaxY == 0) || (y < configMaxY)) {
+            return y;
+        }
+        return configMaxY;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/renderers/Renderer.java b/src/main/java/com/irtimaled/bbor/client/renderers/Renderer.java
new file mode 100644 (file)
index 0000000..850c800
--- /dev/null
@@ -0,0 +1,154 @@
+package com.irtimaled.bbor.client.renderers;
+
+import com.irtimaled.bbor.client.PlayerData;
+import com.irtimaled.bbor.common.models.BoundingBox;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.client.renderer.BufferBuilder;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.util.math.AxisAlignedBB;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+
+public abstract class Renderer<T extends BoundingBox> {
+    public abstract void render(T boundingBox);
+
+    void renderBoundingBox(T boundingBox) {
+        renderCuboid(boundingBox.toAxisAlignedBB(), boundingBox.getColor(), fill());
+    }
+
+    boolean fill() {
+        return ConfigManager.fill.getBoolean();
+    }
+
+    void renderRectangle(AxisAlignedBB aaBB, double minY, double maxY, Color color, Boolean fill) {
+        aaBB = new AxisAlignedBB(aaBB.minX, minY, aaBB.minZ, aaBB.maxX, maxY, aaBB.maxZ);
+        renderCuboid(aaBB, color, fill);
+    }
+
+    void renderCuboid(AxisAlignedBB aaBB, Color color, boolean fill) {
+        aaBB = offsetAxisAlignedBB(aaBB);
+        if (fill) {
+            renderFilledCuboid(aaBB, color);
+        }
+        renderUnfilledCuboid(aaBB, color);
+    }
+
+    private AxisAlignedBB offsetAxisAlignedBB(AxisAlignedBB axisAlignedBB) {
+        double growXZ = 0.001F;
+        double growY = 0;
+        if (axisAlignedBB.minY != axisAlignedBB.maxY) {
+            growY = growXZ;
+        }
+        return axisAlignedBB
+                .grow(growXZ, growY, growXZ)
+                .offset(-PlayerData.getX(), -PlayerData.getY(), -PlayerData.getZ());
+    }
+
+    private void renderFilledCuboid(AxisAlignedBB aaBB, Color color) {
+        GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
+        GL11.glEnable(GL11.GL_BLEND);
+        renderCuboid(aaBB, 30, color);
+        GL11.glDisable(GL11.GL_BLEND);
+        GL11.glEnable(GL11.GL_POLYGON_OFFSET_LINE);
+        GL11.glPolygonOffset(-1.f, -1.f);
+    }
+
+    private void renderUnfilledCuboid(AxisAlignedBB aaBB, Color color) {
+        GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
+        renderCuboid(aaBB, 255, color);
+    }
+
+    private void renderCuboid(AxisAlignedBB bb, int alphaChannel, Color color) {
+        Tessellator tessellator = Tessellator.getInstance();
+        BufferBuilder worldRenderer = tessellator.getBuffer();
+
+        int colorR = color.getRed();
+        int colorG = color.getGreen();
+        int colorB = color.getBlue();
+
+        worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
+        worldRenderer.pos(bb.minX, bb.minY, bb.minZ)
+                .color(colorR, colorG, colorB, alphaChannel)
+                .endVertex();
+        worldRenderer.pos(bb.maxX, bb.minY, bb.minZ)
+                .color(colorR, colorG, colorB, alphaChannel)
+                .endVertex();
+        worldRenderer.pos(bb.maxX, bb.minY, bb.maxZ)
+                .color(colorR, colorG, colorB, alphaChannel)
+                .endVertex();
+        worldRenderer.pos(bb.minX, bb.minY, bb.maxZ)
+                .color(colorR, colorG, colorB, alphaChannel)
+                .endVertex();
+
+        if (bb.minY != bb.maxY) {
+
+            worldRenderer.pos(bb.minX, bb.maxY, bb.minZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.maxX, bb.maxY, bb.minZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.maxX, bb.maxY, bb.maxZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.minX, bb.maxY, bb.maxZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+
+            worldRenderer.pos(bb.minX, bb.minY, bb.maxZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.minX, bb.maxY, bb.maxZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.maxX, bb.maxY, bb.maxZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.maxX, bb.minY, bb.maxZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+
+            worldRenderer.pos(bb.minX, bb.minY, bb.minZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.minX, bb.maxY, bb.minZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.maxX, bb.maxY, bb.minZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.maxX, bb.minY, bb.minZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+
+            worldRenderer.pos(bb.minX, bb.minY, bb.minZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.minX, bb.minY, bb.maxZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.minX, bb.maxY, bb.maxZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.minX, bb.maxY, bb.minZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+
+            worldRenderer.pos(bb.maxX, bb.minY, bb.minZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.maxX, bb.minY, bb.maxZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.maxX, bb.maxY, bb.maxZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+            worldRenderer.pos(bb.maxX, bb.maxY, bb.minZ)
+                    .color(colorR, colorG, colorB, alphaChannel)
+                    .endVertex();
+        }
+        tessellator.draw();
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/renderers/SlimeChunkRenderer.java b/src/main/java/com/irtimaled/bbor/client/renderers/SlimeChunkRenderer.java
new file mode 100644 (file)
index 0000000..1ba3765
--- /dev/null
@@ -0,0 +1,22 @@
+package com.irtimaled.bbor.client.renderers;
+
+import com.irtimaled.bbor.common.models.BoundingBoxSlimeChunk;
+import com.irtimaled.bbor.client.PlayerData;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.util.math.AxisAlignedBB;
+
+import java.awt.*;
+
+public class SlimeChunkRenderer extends Renderer<BoundingBoxSlimeChunk> {
+    @Override
+    public void render(BoundingBoxSlimeChunk boundingBox) {
+        AxisAlignedBB aaBB = boundingBox.toAxisAlignedBB();
+        Color color = boundingBox.getColor();
+        renderCuboid(aaBB, color, fill());
+
+        double maxY = PlayerData.getMaxY(ConfigManager.slimeChunkMaxY.getInt());
+        if (maxY > 39) {
+            renderRectangle(aaBB, 39, maxY, color, fill());
+        }
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/renderers/StructureRenderer.java b/src/main/java/com/irtimaled/bbor/client/renderers/StructureRenderer.java
new file mode 100644 (file)
index 0000000..e98cec8
--- /dev/null
@@ -0,0 +1,10 @@
+package com.irtimaled.bbor.client.renderers;
+
+import com.irtimaled.bbor.common.models.BoundingBoxStructure;
+
+public class StructureRenderer extends Renderer<BoundingBoxStructure> {
+    @Override
+    public void render(BoundingBoxStructure boundingBox) {
+        renderBoundingBox(boundingBox);
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/renderers/VillageRenderer.java b/src/main/java/com/irtimaled/bbor/client/renderers/VillageRenderer.java
new file mode 100644 (file)
index 0000000..d5bee1f
--- /dev/null
@@ -0,0 +1,143 @@
+package com.irtimaled.bbor.client.renderers;
+
+import com.irtimaled.bbor.common.models.BoundingBoxVillage;
+import com.irtimaled.bbor.client.PlayerData;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.client.renderer.BufferBuilder;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.util.math.AxisAlignedBB;
+import net.minecraft.util.math.BlockPos;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
+
+public class VillageRenderer extends Renderer<BoundingBoxVillage> {
+    @Override
+    public void render(BoundingBoxVillage boundingBox) {
+        if (ConfigManager.renderVillageAsSphere.getBoolean()) {
+            renderBoundingBoxVillageAsSphere(boundingBox);
+        } else {
+            renderBoundingBox(boundingBox);
+        }
+        if (ConfigManager.drawIronGolemSpawnArea.getBoolean() &&
+                boundingBox.getSpawnsIronGolems()) {
+            renderIronGolemSpawnArea(boundingBox);
+        }
+        if (ConfigManager.drawVillageDoors.getBoolean()) {
+            renderVillageDoors(boundingBox);
+        }
+    }
+
+    private void renderIronGolemSpawnArea(BoundingBoxVillage boundingBox) {
+        BlockPos center = boundingBox.getCenter();
+        AxisAlignedBB abb = new AxisAlignedBB(new BlockPos(center.getX() - 8,
+                center.getY() - 3,
+                center.getZ() - 8),
+                new BlockPos(center.getX() + 8,
+                        center.getY() + 3,
+                        center.getZ() + 8))
+                .offset(boundingBox.getCenterOffsetX(), 0.0, boundingBox.getCenterOffsetZ());
+
+        renderCuboid(abb, boundingBox.getColor(), false);
+    }
+
+    private void renderVillageDoors(BoundingBoxVillage boundingBox) {
+        OffsetPoint center = new OffsetPoint(boundingBox.getCenter())
+                .add(boundingBox.getCenterOffsetX(), 0.0, boundingBox.getCenterOffsetZ());
+        Color color = boundingBox.getColor();
+        GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
+        Tessellator tessellator = Tessellator.getInstance();
+        BufferBuilder worldRenderer = tessellator.getBuffer();
+
+        int colorR = color.getRed();
+        int colorG = color.getGreen();
+        int colorB = color.getBlue();
+
+        worldRenderer.begin(GL11.GL_LINES, worldRenderer.getVertexFormat());
+        for (BlockPos door : boundingBox.getDoors()) {
+            OffsetPoint point = new OffsetPoint(door).add(0.5, 0, 0.5);
+
+            worldRenderer.pos(point.getX(), point.getY(), point.getZ()).color(colorR, colorG, colorB, 255).endVertex();
+            worldRenderer.pos(center.getX(), center.getY(), center.getZ()).color(colorR, colorG, colorB, 255).endVertex();
+        }
+        tessellator.draw();
+    }
+
+    private void renderBoundingBoxVillageAsSphere(BoundingBoxVillage boundingBox) {
+        OffsetPoint center = new OffsetPoint(boundingBox.getCenter())
+                .add(boundingBox.getCenterOffsetX(), 0.0, boundingBox.getCenterOffsetZ());
+        int radius = boundingBox.getRadius();
+        Color color = boundingBox.getColor();
+        renderSphere(center, radius, color);
+    }
+
+    private void renderSphere(OffsetPoint center, double radius, Color color) {
+        GL11.glEnable(GL11.GL_POINT_SMOOTH);
+        GL11.glPointSize(2f);
+
+        Tessellator tessellator = Tessellator.getInstance();
+        BufferBuilder worldRenderer = tessellator.getBuffer();
+        worldRenderer.begin(GL11.GL_POINTS, DefaultVertexFormats.POSITION_COLOR);
+        for (OffsetPoint point : buildPoints(center, radius)) {
+            worldRenderer.pos(point.getX(), point.getY(), point.getZ())
+                    .color(color.getRed(), color.getGreen(), color.getBlue(), 255)
+                    .endVertex();
+        }
+        tessellator.draw();
+    }
+
+    private class OffsetPoint {
+        private final double x;
+        private final double y;
+        private final double z;
+
+        OffsetPoint(double x, double y, double z) {
+            this.x = x;
+            this.y = y;
+            this.z = z;
+        }
+
+        OffsetPoint(BlockPos blockPos) {
+            this.x = blockPos.getX();
+            this.y = blockPos.getY();
+            this.z = blockPos.getZ();
+        }
+
+        double getX() {
+            return x - PlayerData.getX();
+        }
+
+        double getY() {
+            return y - PlayerData.getY();
+        }
+
+        double getZ() {
+            return z - PlayerData.getZ();
+        }
+
+        public OffsetPoint add(double x, double y, double z) {
+            return new OffsetPoint(this.x + x, this.y + y, this.z + z);
+        }
+    }
+
+    private Set<OffsetPoint> buildPoints(OffsetPoint center, double radius) {
+        Set<OffsetPoint> points = new HashSet<>(1200);
+
+        double tau = 6.283185307179586D;
+        double pi = tau / 2D;
+        double segment = tau / 48D;
+
+        for (double t = 0.0D; t < tau; t += segment)
+            for (double theta = 0.0D; theta < pi; theta += segment) {
+                double dx = radius * Math.sin(t) * Math.cos(theta);
+                double dz = radius * Math.sin(t) * Math.sin(theta);
+                double dy = radius * Math.cos(t);
+
+                points.add(center.add(dx, dy, dz));
+            }
+        return points;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/client/renderers/WorldSpawnRenderer.java b/src/main/java/com/irtimaled/bbor/client/renderers/WorldSpawnRenderer.java
new file mode 100644 (file)
index 0000000..98ac02d
--- /dev/null
@@ -0,0 +1,18 @@
+package com.irtimaled.bbor.client.renderers;
+
+import com.irtimaled.bbor.common.models.BoundingBoxWorldSpawn;
+import com.irtimaled.bbor.client.PlayerData;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.util.math.AxisAlignedBB;
+
+import java.awt.*;
+
+public class WorldSpawnRenderer extends Renderer<BoundingBoxWorldSpawn> {
+    @Override
+    public void render(BoundingBoxWorldSpawn boundingBox) {
+        AxisAlignedBB aaBB = boundingBox.toAxisAlignedBB(false);
+        Color color = boundingBox.getColor();
+        double y = PlayerData.getMaxY(ConfigManager.worldSpawnMaxY.getInt()) + 0.001F;
+        renderRectangle(aaBB, y, y, color, false);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/irtimaled/bbor/common/BoundingBoxCache.java b/src/main/java/com/irtimaled/bbor/common/BoundingBoxCache.java
new file mode 100644 (file)
index 0000000..03026f1
--- /dev/null
@@ -0,0 +1,43 @@
+package com.irtimaled.bbor.common;
+
+import com.irtimaled.bbor.common.models.BoundingBox;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class BoundingBoxCache {
+    private Map<BoundingBox, Set<BoundingBox>> cache = new ConcurrentHashMap<>();
+
+    public Map<BoundingBox, Set<BoundingBox>> getBoundingBoxes() {
+        return cache;
+    }
+
+    public synchronized void refresh() {
+    }
+
+    public void close() {
+        cache.clear();
+    }
+
+    boolean isCached(BoundingBox key) {
+        return cache.containsKey(key);
+    }
+
+    public void addBoundingBoxes(BoundingBox key, Set<BoundingBox> boundingBoxes) {
+        cache.put(key, boundingBoxes);
+    }
+
+    public void addBoundingBox(BoundingBox key) {
+        Set<BoundingBox> boundingBoxes = new HashSet<>();
+        boundingBoxes.add(key);
+        addBoundingBoxes(key, boundingBoxes);
+    }
+
+    public void removeBoundingBox(BoundingBox key) {
+        if (cache.containsKey(key)) {
+            cache.remove(key);
+        }
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/CommonProxy.java b/src/main/java/com/irtimaled/bbor/common/CommonProxy.java
new file mode 100644 (file)
index 0000000..68e338b
--- /dev/null
@@ -0,0 +1,57 @@
+package com.irtimaled.bbor.common;
+
+import com.irtimaled.bbor.Logger;
+import com.irtimaled.bbor.ReflectionHelper;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.world.DimensionType;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraft.world.chunk.IChunkProvider;
+import net.minecraft.world.gen.ChunkProviderServer;
+import net.minecraft.world.gen.IChunkGenerator;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class CommonProxy {
+    protected DimensionCache dimensionCache;
+    protected Set<VillageProcessor> villageProcessors = new HashSet<>();
+
+    private IVillageEventHandler eventHandler = null;
+
+    public void worldLoaded(World world) {
+        IChunkProvider chunkProvider = world.getChunkProvider();
+        if (chunkProvider instanceof ChunkProviderServer) {
+            IChunkGenerator chunkGenerator = ReflectionHelper.getPrivateValue(ChunkProviderServer.class, (ChunkProviderServer) chunkProvider, IChunkGenerator.class);
+            dimensionCache.setWorldData(world.getSeed(), world.getWorldInfo().getSpawnX(), world.getWorldInfo().getSpawnZ());
+            DimensionType dimensionType = world.provider.getDimensionType();
+            Logger.info("create world dimension: %s, %s (chunkprovider: %s) (seed: %d)", dimensionType, world.getClass().toString(), chunkGenerator.getClass().toString(), world.getSeed());
+            DimensionProcessor boundingBoxCache = new DimensionProcessor(dimensionType, chunkGenerator);
+            dimensionCache.put(dimensionType, boundingBoxCache);
+            if (ConfigManager.drawVillages.getBoolean()) {
+                villageProcessors.add(new VillageProcessor(world, dimensionType, eventHandler, boundingBoxCache));
+            }
+        }
+    }
+
+    public void chunkLoaded(Chunk chunk) {
+        DimensionType dimensionType = chunk.getWorld().provider.getDimensionType();
+        dimensionCache.refresh(dimensionType);
+    }
+
+    public void tick() {
+        villageProcessors.forEach(VillageProcessor::process);
+    }
+
+    public void init() {
+        dimensionCache = new DimensionCache();
+    }
+
+    public void setEventHandler(IVillageEventHandler eventHandler) {
+        this.eventHandler = eventHandler;
+    }
+
+    public DimensionCache getDimensionCache() {
+        return dimensionCache;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/DimensionCache.java b/src/main/java/com/irtimaled/bbor/common/DimensionCache.java
new file mode 100644 (file)
index 0000000..a6c8f24
--- /dev/null
@@ -0,0 +1,42 @@
+package com.irtimaled.bbor.common;
+
+import com.irtimaled.bbor.common.models.WorldData;
+import net.minecraft.world.DimensionType;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class DimensionCache {
+    private final Map<DimensionType, BoundingBoxCache> map = new ConcurrentHashMap<>();
+    private WorldData worldData;
+
+    void refresh(DimensionType dimensionType) {
+        if (map.containsKey(dimensionType)) {
+            map.get(dimensionType).refresh();
+        }
+    }
+
+    public void put(DimensionType dimensionType, BoundingBoxCache boundingBoxCache) {
+        map.put(dimensionType, boundingBoxCache);
+    }
+
+    public BoundingBoxCache getBoundingBoxes(DimensionType dimensionType) {
+        return map.get(dimensionType);
+    }
+
+    public void clear() {
+        worldData = null;
+        for (BoundingBoxCache cache : map.values()) {
+            cache.close();
+        }
+        map.clear();
+    }
+
+    public void setWorldData(long seed, int spawnX, int spawnZ) {
+        this.worldData = new WorldData(seed, spawnX, spawnZ);
+    }
+
+    public WorldData getWorldData() {
+        return worldData;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/DimensionProcessor.java b/src/main/java/com/irtimaled/bbor/common/DimensionProcessor.java
new file mode 100644 (file)
index 0000000..7ea59c4
--- /dev/null
@@ -0,0 +1,122 @@
+package com.irtimaled.bbor.common;
+
+import com.irtimaled.bbor.Logger;
+import com.irtimaled.bbor.ReflectionHelper;
+import com.irtimaled.bbor.common.models.BoundingBox;
+import com.irtimaled.bbor.common.models.BoundingBoxStructure;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.util.math.ChunkPos;
+import net.minecraft.world.DimensionType;
+import net.minecraft.world.gen.ChunkGeneratorEnd;
+import net.minecraft.world.gen.ChunkGeneratorHell;
+import net.minecraft.world.gen.ChunkGeneratorOverworld;
+import net.minecraft.world.gen.IChunkGenerator;
+import net.minecraft.world.gen.structure.*;
+
+import java.awt.*;
+import java.util.*;
+
+public class DimensionProcessor extends BoundingBoxCache {
+    DimensionProcessor(DimensionType dimensionType, IChunkGenerator chunkGenerator) {
+        this.dimensionType = dimensionType;
+        this.chunkGenerator = chunkGenerator;
+    }
+
+    private DimensionType dimensionType;
+    private IChunkGenerator chunkGenerator;
+
+    private boolean closed = false;
+
+    @Override
+    public void close() {
+        closed = true;
+        chunkGenerator = null;
+        super.close();
+    }
+
+    private static <T extends IChunkGenerator, R extends MapGenStructure> Collection<StructureStart> getStructures(T chunkGenerator, Class<R> generatorClass) {
+        Class<T> chunkGeneratorClass = (Class<T>) chunkGenerator.getClass();
+        R structureGenerator = ReflectionHelper.getPrivateValue(chunkGeneratorClass, chunkGenerator, generatorClass);
+        if (structureGenerator != null) {
+            Map<ChunkPos, StructureStart> structureMap = ReflectionHelper.getPrivateValue(MapGenStructure.class, structureGenerator, Map.class);
+            return structureMap.values();
+        }
+        return Collections.emptyList();
+    }
+
+    private Map<StructureType, Collection<StructureStart>> getStructures() {
+        Map<StructureType, Collection<StructureStart>> structureMap = new HashMap<>();
+        if (chunkGenerator instanceof ChunkGeneratorOverworld) {
+            if (ConfigManager.drawDesertTemples.getBoolean()) {
+                structureMap.put(StructureType.DesertTemple, getStructuresWithComponent(getStructures(chunkGenerator, MapGenScatteredFeature.class), ComponentScatteredFeaturePieces.DesertPyramid.class));
+            }
+
+            if (ConfigManager.drawJungleTemples.getBoolean()) {
+                structureMap.put(StructureType.JungleTemple, getStructuresWithComponent(getStructures(chunkGenerator, MapGenScatteredFeature.class), ComponentScatteredFeaturePieces.JunglePyramid.class));
+            }
+
+            if (ConfigManager.drawWitchHuts.getBoolean()) {
+                structureMap.put(StructureType.WitchHut, getStructuresWithComponent(getStructures(chunkGenerator, MapGenScatteredFeature.class), ComponentScatteredFeaturePieces.SwampHut.class));
+            }
+
+            if (ConfigManager.drawOceanMonuments.getBoolean()) {
+                structureMap.put(StructureType.OceanMonument, getStructures(chunkGenerator, StructureOceanMonument.class));
+            }
+
+            if (ConfigManager.drawStrongholds.getBoolean()) {
+                structureMap.put(StructureType.Stronghold, getStructures(chunkGenerator, MapGenStronghold.class));
+            }
+
+            if (ConfigManager.drawMansions.getBoolean()) {
+                structureMap.put(StructureType.Mansion, getStructures(chunkGenerator, WoodlandMansion.class));
+            }
+
+            if (ConfigManager.drawMineShafts.getBoolean()) {
+                structureMap.put(StructureType.MineShaft, getStructures(chunkGenerator, MapGenMineshaft.class));
+            }
+        } else if (chunkGenerator instanceof ChunkGeneratorHell) {
+            if (ConfigManager.drawNetherFortresses.getBoolean()) {
+                structureMap.put(StructureType.NetherFortress, getStructures(chunkGenerator, MapGenNetherBridge.class));
+            }
+        } else if (chunkGenerator instanceof ChunkGeneratorEnd) {
+            if (ConfigManager.drawEndCities.getBoolean()) {
+                structureMap.put(StructureType.EndCity, getStructures(chunkGenerator, MapGenEndCity.class));
+            }
+        }
+
+        return structureMap;
+    }
+
+    private Collection<StructureStart> getStructuresWithComponent(Collection<StructureStart> structures, Class structureComponent) {
+        Collection<StructureStart> validStructures = new HashSet<>();
+        for (StructureStart structure : structures) {
+            if (structure.getComponents().get(0).getClass().equals(structureComponent)) {
+                validStructures.add(structure);
+            }
+        }
+        return validStructures;
+    }
+
+    @Override
+    public synchronized void refresh() {
+        if (closed) return;
+
+        Map<StructureType, Collection<StructureStart>> structureMap = getStructures();
+        for (StructureType structureType : structureMap.keySet()) {
+            Color color = structureType.getColor();
+            for (StructureStart structureStart : structureMap.get(structureType)) {
+                if (structureStart.getBoundingBox() != null) {
+                    BoundingBox boundingBox = BoundingBoxStructure.from(structureStart.getBoundingBox(), color);
+                    if (!isCached(boundingBox)) {
+                        Set<BoundingBox> structureBoundingBoxes = new HashSet<>();
+                        for (StructureComponent structureComponent : structureStart.getComponents()) {
+                            structureBoundingBoxes.add(BoundingBoxStructure.from(structureComponent.getBoundingBox(), color));
+                        }
+                        addBoundingBoxes(boundingBox, structureBoundingBoxes);
+                        Logger.info("[%s] new dimensionCache entries: %d", dimensionType, structureBoundingBoxes.size());
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/IVillageEventHandler.java b/src/main/java/com/irtimaled/bbor/common/IVillageEventHandler.java
new file mode 100644 (file)
index 0000000..b8df1c8
--- /dev/null
@@ -0,0 +1,8 @@
+package com.irtimaled.bbor.common;
+
+import com.irtimaled.bbor.common.models.BoundingBox;
+import net.minecraft.world.DimensionType;
+
+public interface IVillageEventHandler {
+    void villageRemoved(DimensionType dimensionType, BoundingBox bb);
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/StructureType.java b/src/main/java/com/irtimaled/bbor/common/StructureType.java
new file mode 100644 (file)
index 0000000..9f7e87a
--- /dev/null
@@ -0,0 +1,55 @@
+package com.irtimaled.bbor.common;
+
+import java.awt.*;
+
+public class StructureType {
+    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 static final int END_CITY = 8;
+    private static final int MANSION = 9;
+
+    public final static StructureType JungleTemple = new StructureType(JUNGLE_TEMPLE);
+    public final static StructureType DesertTemple = new StructureType(DESERT_TEMPLE);
+    public final static StructureType WitchHut = new StructureType(WITCH_HUT);
+    public final static StructureType OceanMonument = new StructureType(OCEAN_MONUMENT);
+    public final static StructureType Stronghold = new StructureType(STRONGHOLD);
+    public final static StructureType MineShaft = new StructureType(MINE_SHAFT);
+    public final static StructureType NetherFortress = new StructureType(NETHER_FORTRESS);
+    public final static StructureType EndCity = new StructureType(END_CITY);
+    public final static StructureType Mansion = new StructureType(MANSION);
+
+    private final int type;
+
+    private StructureType(int type) {
+        this.type = type;
+    }
+
+    public Color getColor() {
+        switch (type) {
+            case DESERT_TEMPLE:
+                return Color.ORANGE;
+            case JUNGLE_TEMPLE:
+                return Color.GREEN;
+            case WITCH_HUT:
+                return Color.BLUE;
+            case MINE_SHAFT:
+                return Color.LIGHT_GRAY;
+            case NETHER_FORTRESS:
+                return Color.RED;
+            case OCEAN_MONUMENT:
+                return Color.CYAN;
+            case STRONGHOLD:
+                return Color.YELLOW;
+            case END_CITY:
+                return Color.MAGENTA;
+            case MANSION:
+                return new Color(139, 69, 19);
+        }
+        return Color.WHITE;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/VillageColorCache.java b/src/main/java/com/irtimaled/bbor/common/VillageColorCache.java
new file mode 100644 (file)
index 0000000..d5071a7
--- /dev/null
@@ -0,0 +1,38 @@
+package com.irtimaled.bbor.common;
+
+import java.awt.*;
+import java.util.HashMap;
+import java.util.Map;
+
+public class VillageColorCache {
+    private static int colorIndex = -1;
+
+    public static void clear() {
+        colorIndex = -1;
+        villageColorCache.clear();
+    }
+
+    private static Color getNextColor() {
+        switch (++colorIndex % 6) {
+            case 0:
+                return Color.RED;
+            case 1:
+                return Color.GREEN;
+            case 2:
+                return Color.BLUE;
+            case 3:
+                return Color.MAGENTA;
+            case 4:
+                return Color.YELLOW;
+            case 5:
+                return Color.CYAN;
+        }
+        return Color.WHITE;
+    }
+
+    private static Map<Integer, Color> villageColorCache = new HashMap<>();
+
+    public static Color getColor(int villageId) {
+        return villageColorCache.computeIfAbsent(villageId, k -> getNextColor());
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/VillageProcessor.java b/src/main/java/com/irtimaled/bbor/common/VillageProcessor.java
new file mode 100644 (file)
index 0000000..ce4cd7f
--- /dev/null
@@ -0,0 +1,68 @@
+package com.irtimaled.bbor.common;
+
+import com.irtimaled.bbor.common.models.BoundingBoxVillage;
+import net.minecraft.village.Village;
+import net.minecraft.village.VillageCollection;
+import net.minecraft.world.DimensionType;
+import net.minecraft.world.World;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class VillageProcessor {
+    private World world;
+    private DimensionType dimensionType;
+    private IVillageEventHandler eventHandler;
+    private BoundingBoxCache boundingBoxCache;
+    private Map<Integer, BoundingBoxVillage> villageCache = new HashMap<>();
+    private boolean closed = false;
+
+    VillageProcessor(World world, DimensionType dimensionType, IVillageEventHandler eventHandler, BoundingBoxCache boundingBoxCache) {
+        this.world = world;
+        this.dimensionType = dimensionType;
+        this.eventHandler = eventHandler;
+        this.boundingBoxCache = boundingBoxCache;
+    }
+
+    synchronized void process() {
+        if (closed) return;
+
+        Map<Integer, BoundingBoxVillage> oldVillages = new HashMap<>(villageCache);
+        Map<Integer, BoundingBoxVillage> newVillages = new HashMap<>();
+        VillageCollection villageCollection = world.getVillageCollection();
+        if (villageCollection != null) {
+            List<Village> villages = villageCollection.getVillageList();
+            for(int i = 0; i < villages.size(); i++) {
+                Village village = villages.get(i);
+                int villageId = village.hashCode();
+                BoundingBoxVillage newVillage = oldVillages.get(villageId);
+                if (newVillage != null && newVillage.matches(village)) {
+                    oldVillages.remove(villageId);
+                } else {
+                    newVillage = BoundingBoxVillage.from(village);
+                }
+                newVillages.put(villageId, newVillage);
+            }
+
+        }
+        for (BoundingBoxVillage village : oldVillages.values()) {
+            boundingBoxCache.removeBoundingBox(village);
+            if (eventHandler != null) {
+                eventHandler.villageRemoved(dimensionType, village);
+            }
+        }
+        for (BoundingBoxVillage village : newVillages.values()) {
+            boundingBoxCache.addBoundingBox(village);
+        }
+        villageCache = newVillages;
+    }
+
+    public void close() {
+        closed = true;
+        world = null;
+        eventHandler = null;
+        boundingBoxCache = null;
+        villageCache.clear();
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/models/BoundingBox.java b/src/main/java/com/irtimaled/bbor/common/models/BoundingBox.java
new file mode 100644 (file)
index 0000000..c337dc7
--- /dev/null
@@ -0,0 +1,67 @@
+package com.irtimaled.bbor.common.models;
+
+import net.minecraft.util.math.AxisAlignedBB;
+import net.minecraft.util.math.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;
+        return minBlockPos.equals(other.minBlockPos) && maxBlockPos.equals(other.maxBlockPos);
+    }
+
+    @Override
+    public String toString() {
+        return "(" + minBlockPos.toString() + "; " + maxBlockPos.toString() + ")";
+    }
+
+    public AxisAlignedBB toAxisAlignedBB() {
+        return toAxisAlignedBB(true);
+    }
+
+    public AxisAlignedBB toAxisAlignedBB(boolean extendMaxByOne) {
+        AxisAlignedBB axisAlignedBB = new AxisAlignedBB(minBlockPos, maxBlockPos);
+        if (extendMaxByOne)
+            return axisAlignedBB.expand(1, 1, 1);
+        return axisAlignedBB;
+    }
+
+    public BlockPos getMinBlockPos() {
+        return minBlockPos;
+    }
+
+    public BlockPos getMaxBlockPos() {
+        return maxBlockPos;
+    }
+
+    public Color getColor() {
+        return color;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/models/BoundingBoxSlimeChunk.java b/src/main/java/com/irtimaled/bbor/common/models/BoundingBoxSlimeChunk.java
new file mode 100644 (file)
index 0000000..93aa8f3
--- /dev/null
@@ -0,0 +1,15 @@
+package com.irtimaled.bbor.common.models;
+
+import net.minecraft.util.math.BlockPos;
+
+import java.awt.*;
+
+public class BoundingBoxSlimeChunk extends BoundingBox {
+    private BoundingBoxSlimeChunk(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
+        super(minBlockPos, maxBlockPos, color);
+    }
+
+    public static BoundingBoxSlimeChunk from(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
+        return new BoundingBoxSlimeChunk(minBlockPos, maxBlockPos, color);
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/models/BoundingBoxStructure.java b/src/main/java/com/irtimaled/bbor/common/models/BoundingBoxStructure.java
new file mode 100644 (file)
index 0000000..97f2602
--- /dev/null
@@ -0,0 +1,28 @@
+package com.irtimaled.bbor.common.models;
+
+import net.minecraft.util.math.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(int[] bb, Color color) {
+        BlockPos minBlockPos = new BlockPos(bb[0], bb[1], bb[2]);
+        BlockPos maxBlockPos = new BlockPos(bb[3], bb[4], bb[5]);
+        return new BoundingBoxStructure(minBlockPos, maxBlockPos, color);
+    }
+
+    public static BoundingBoxStructure from(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
+        return new BoundingBoxStructure(minBlockPos, maxBlockPos, color);
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/models/BoundingBoxVillage.java b/src/main/java/com/irtimaled/bbor/common/models/BoundingBoxVillage.java
new file mode 100644 (file)
index 0000000..427aa45
--- /dev/null
@@ -0,0 +1,145 @@
+package com.irtimaled.bbor.common.models;
+
+import com.irtimaled.bbor.common.VillageColorCache;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.village.Village;
+import net.minecraft.village.VillageDoorInfo;
+
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+public class BoundingBoxVillage extends BoundingBox {
+    private final BlockPos center;
+    private final Integer radius;
+    private final boolean spawnsIronGolems;
+    private Set<BlockPos> doors;
+    private Double centerOffsetX;
+    private Double centerOffsetZ;
+    private int villageHash;
+
+    private BoundingBoxVillage(BlockPos center, Integer radius, Color color, boolean spawnsIronGolems, Set<BlockPos> doors, BlockPos minBlockPos, BlockPos maxBlockPos) {
+        super(minBlockPos, maxBlockPos, color);
+        this.center = center;
+        this.radius = radius;
+        this.spawnsIronGolems = spawnsIronGolems;
+        this.doors = doors;
+        this.villageHash = computeHash(center, radius, spawnsIronGolems, doors);
+        calculateCenterOffsets(doors);
+    }
+
+    public static BoundingBoxVillage from(BlockPos center, Integer radius, Color color, boolean spawnsIronGolems, Set<BlockPos> doors) {
+        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, doors, minBlockPos, maxBlockPos);
+    }
+
+    public static BoundingBoxVillage from(BlockPos center, Integer radius, int villageId, int population, Set<BlockPos> doors) {
+        Boolean spawnsIronGolems = shouldSpawnIronGolems(population, doors.size());
+        Color color = VillageColorCache.getColor(villageId);
+        return from(center, radius, color, spawnsIronGolems, doors);
+    }
+
+    private static boolean shouldSpawnIronGolems(int population, int doorCount) {
+        return population >= 10 && doorCount >= 21;
+    }
+
+    public static BoundingBoxVillage from(Village village) {
+        BlockPos center = village.getCenter();
+        int radius = village.getVillageRadius();
+        Set<BlockPos> doors = getDoorsFromVillage(village);
+        return from(center, radius, village.hashCode(), village.getNumVillagers(), doors);
+    }
+
+    private static Set<BlockPos> getDoorsFromVillage(Village village) {
+        Set<BlockPos> doors = new HashSet<>();
+        List<VillageDoorInfo> doorInfoList = village.getVillageDoorInfoList();
+        for (int i = 0; i < doorInfoList.size(); i++) {
+            VillageDoorInfo doorInfo = doorInfoList.get(i);
+            doors.add(doorInfo.getDoorBlockPos());
+        }
+        return doors;
+    }
+
+    private void calculateCenterOffsets(Set<BlockPos> doors) {
+        boolean processedFirstDoor = false;
+        int minX = 0;
+        int maxX = 0;
+        int minZ = 0;
+        int maxZ = 0;
+        for (BlockPos door : doors) {
+            if (!processedFirstDoor ||
+                    (minX > door.getX()))
+                minX = door.getX();
+            if (!processedFirstDoor ||
+                    maxX < door.getX())
+                maxX = door.getX();
+            if (!processedFirstDoor ||
+                    minZ > door.getZ())
+                minZ = door.getZ();
+            if (!processedFirstDoor ||
+                    maxZ < door.getZ())
+                maxZ = door.getZ();
+
+            processedFirstDoor = true;
+        }
+        centerOffsetX = Math.abs(maxX - minX) % 2 == 0 ? 0.5 : (minX < 0 ? 0 : 1);
+        centerOffsetZ = Math.abs(maxZ - minZ) % 2 == 0 ? 0.5 : (minZ < 0 ? 0 : 1);
+    }
+
+    @Override
+    public String toString() {
+        return "(" + center.toString() + "; " + radius.toString() + ")";
+    }
+
+    public Integer getRadius() {
+        return radius;
+    }
+
+    public BlockPos getCenter() {
+        return center;
+    }
+
+    public Double getCenterOffsetX() {
+        return centerOffsetX;
+    }
+
+    public Double getCenterOffsetZ() {
+        return centerOffsetZ;
+    }
+
+    private static int computeHash(BlockPos center, Integer radius, boolean spawnsIronGolems, Set<BlockPos> doors) {
+        int result = (center.hashCode() * 31) + radius;
+        for (BlockPos door : doors) {
+            result = (31 * result) + door.hashCode();
+        }
+        if (spawnsIronGolems) {
+            result = 31 * result;
+        }
+        return result;
+    }
+
+    public boolean matches(Village village) {
+        return this.villageHash == computeHash(village.getCenter(),
+                village.getVillageRadius(),
+                shouldSpawnIronGolems(village.getNumVillagers(), village.getNumVillageDoors()),
+                getDoorsFromVillage(village));
+    }
+
+    @Override
+    public int hashCode() {
+        return (super.hashCode() * 31) + villageHash;
+    }
+
+    public boolean getSpawnsIronGolems() {
+        return spawnsIronGolems;
+    }
+
+    public Set<BlockPos> getDoors() {
+        return doors;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/models/BoundingBoxWorldSpawn.java b/src/main/java/com/irtimaled/bbor/common/models/BoundingBoxWorldSpawn.java
new file mode 100644 (file)
index 0000000..ad3a127
--- /dev/null
@@ -0,0 +1,15 @@
+package com.irtimaled.bbor.common.models;
+
+import net.minecraft.util.math.BlockPos;
+
+import java.awt.*;
+
+public class BoundingBoxWorldSpawn extends BoundingBox {
+    private BoundingBoxWorldSpawn(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
+        super(minBlockPos, maxBlockPos, color);
+    }
+
+    public static BoundingBoxWorldSpawn from(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
+        return new BoundingBoxWorldSpawn(minBlockPos, maxBlockPos, color);
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/common/models/WorldData.java b/src/main/java/com/irtimaled/bbor/common/models/WorldData.java
new file mode 100644 (file)
index 0000000..1eb5dbb
--- /dev/null
@@ -0,0 +1,25 @@
+package com.irtimaled.bbor.common.models;
+
+public class WorldData {
+    private long seed;
+    private int spawnX;
+    private int spawnZ;
+
+    public WorldData(long seed, int spawnX, int spawnZ) {
+        this.seed = seed;
+        this.spawnX = spawnX;
+        this.spawnZ = spawnZ;
+    }
+
+    public long getSeed() {
+        return seed;
+    }
+
+    public int getSpawnX() {
+        return spawnX;
+    }
+
+    public int getSpawnZ() {
+        return spawnZ;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/config/ConfigManager.java b/src/main/java/com/irtimaled/bbor/config/ConfigManager.java
new file mode 100644 (file)
index 0000000..37227f9
--- /dev/null
@@ -0,0 +1,72 @@
+package com.irtimaled.bbor.config;
+
+import java.io.File;
+
+public class ConfigManager {
+    public static File configDir;
+
+    public static Setting fill;
+    public static Setting drawVillages;
+    public static Setting drawDesertTemples;
+    public static Setting drawJungleTemples;
+    public static Setting drawWitchHuts;
+    public static Setting drawStrongholds;
+    public static Setting drawMineShafts;
+    public static Setting drawNetherFortresses;
+    public static Setting drawOceanMonuments;
+    public static Setting alwaysVisible;
+    public static Setting renderVillageAsSphere;
+    public static Setting drawIronGolemSpawnArea;
+    public static Setting drawVillageDoors;
+    public static Setting drawSlimeChunks;
+    public static Setting slimeChunkMaxY;
+    public static Setting keepCacheBetweenSessions;
+    public static Setting drawWorldSpawn;
+    public static Setting worldSpawnMaxY;
+    public static Setting drawLazySpawnChunks;
+    public static Setting drawEndCities;
+    public static Setting drawMansions;
+
+    public static void loadConfig(File mcConfigDir) {
+        configDir = mcConfigDir;
+        Configuration config = new Configuration(new File(configDir, "BBOutlineReloaded.cfg"));
+        config.load();
+
+        fill = SetupBooleanProperty(config, "general", "fill", true, "If set to true the bounding boxes are filled. (default: true)");
+        alwaysVisible = SetupBooleanProperty(config, "general", "alwaysVisible", false, "If set to true boxes will be visible even through other blocks. (default: false)");
+        keepCacheBetweenSessions = SetupBooleanProperty(config, "general", "keepCacheBetweenSessions", false, "If set to true bounding box caches will be kept between sessions. (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)");
+        drawVillageDoors = SetupBooleanProperty(config, "features", "drawVillageDoors", false, "If set to true lines between the village centre and doors will be drawn. (default:false)");
+        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", -1, "The maximum top of the slime chunk bounding box. If set to -1 it will use the value when activated, if set to 0 it will always track the player's feet. (default: -1)");
+        drawWorldSpawn = SetupBooleanProperty(config, "features", "drawWorldSpawn", true, "If set to true world spawn and spawn chunks bounding boxes are drawn. (default: true)");
+        worldSpawnMaxY = SetupIntegerProperty(config, "features", "worldSpawnMaxY", -1, "The maximum top of the world spawn bounding boxes. If set to -1 it will use the value when activated, if set to 0 it will always track the players feet. (default: -1)");
+        drawLazySpawnChunks = SetupBooleanProperty(config, "features", "drawLazySpawnChunks", false, "If set to true the lazy spawn chunks bounding boxes will be drawn. (default: false)");
+        drawEndCities = SetupBooleanProperty(config, "features", "drawEndCities", true, "If set to true end city bounding boxes will be drawn. (default: true)");
+        drawMansions = SetupBooleanProperty(config, "features", "drawMansions", true, "If set to true woodland mansions will be drawn. (default: true)");
+        config.save();
+    }
+
+    private static Setting SetupBooleanProperty(Configuration config, String category, String settingName, Boolean defaultValue, String comment) {
+        Setting property = config.get(category, settingName, defaultValue);
+        property.comment = comment;
+        property.set(property.getBoolean(defaultValue));
+        return property;
+    }
+
+    private static Setting SetupIntegerProperty(Configuration config, String category, String settingName, int defaultValue, String comment) {
+        Setting property = config.get(category, settingName, defaultValue);
+        property.comment = comment;
+        property.set(property.getInt(defaultValue));
+        return property;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/config/Configuration.java b/src/main/java/com/irtimaled/bbor/config/Configuration.java
new file mode 100644 (file)
index 0000000..2048526
--- /dev/null
@@ -0,0 +1,110 @@
+package com.irtimaled.bbor.config;
+
+import com.google.common.io.Files;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Configuration {
+    private final File file;
+
+    Configuration(File file) {
+        this.file = file;
+    }
+
+    void save() {
+        Writer writer = null;
+        try {
+            writer = new BufferedWriter(new OutputStreamWriter(
+                    new FileOutputStream(file), "utf-8"));
+            writer.write("# Configuration file\n");
+            for (String category : settingsGroup.keySet()) {
+                writer.write("\n");
+                writer.write(String.format("%s {\n", category));
+                Map<String, Setting> settings = settingsGroup.get(category);
+                Boolean first = true;
+                for (String settingName : settings.keySet()) {
+                    if (!first)
+                        writer.write("\n");
+                    first = false;
+                    Setting setting = settings.get(settingName);
+                    writer.write(String.format("    # %s\n", setting.comment));
+                    writer.write(String.format("    %s:%s=%s\n", setting.getType(), settingName, setting.getValue()));
+                }
+                writer.write("}\n");
+            }
+        } catch (IOException ignored) {
+        } finally {
+            try {
+                if (writer != null) {
+                    writer.close();
+                }
+            } catch (Exception ignored) {
+            }
+        }
+    }
+
+    private Map<String, Map<String, Setting>> settingsGroup = new HashMap<>();
+
+    void load() {
+        try {
+            List<String> lines = Files.readLines(file, Charset.forName("utf-8"));
+            String category = null;
+            String lastCommentLine = null;
+            for (String line : lines) {
+                String trimmedLine = line.trim();
+                if (trimmedLine.isEmpty()) {
+                    continue;
+                }
+                if (trimmedLine.startsWith("#")) {
+                    lastCommentLine = trimmedLine.substring(1).trim();
+                    continue;
+                }
+                if (trimmedLine.equals("}")) {
+                    category = null;
+                    continue;
+                }
+                if (category == null && trimmedLine.endsWith("{")) {
+                    category = trimmedLine.substring(0, trimmedLine.length() - 1).trim();
+                    settingsGroup.put(category, new HashMap<>());
+                    continue;
+                }
+                if (category != null) {
+                    String[] items = trimmedLine.split("[:=]");
+                    char type = items[0].charAt(0);
+                    String name = items[1];
+                    String stringValue = items[2];
+                    Object value = getTypedValue(type, stringValue);
+                    Setting setting = new Setting(value);
+                    setting.comment = lastCommentLine;
+                    settingsGroup.get(category).put(name, setting);
+                }
+            }
+        } catch (IOException ignored) {
+        }
+    }
+
+    private Object getTypedValue(char type, String stringValue) {
+        switch (type) {
+            case 'I':
+                return Integer.parseInt(stringValue);
+            case 'B':
+                return stringValue.equals("1") || stringValue.toLowerCase().equals("true");
+        }
+        return stringValue;
+    }
+
+    public Setting get(String category, String settingName, Object defaultValue) {
+        if (!settingsGroup.containsKey(category)) {
+            settingsGroup.put(category, new HashMap<>());
+        }
+        Map<String, Setting> settings = settingsGroup.get(category);
+        if (!settings.containsKey(settingName)) {
+            settings.put(settingName, new Setting(defaultValue));
+        }
+        return settings.get(settingName);
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/config/Setting.java b/src/main/java/com/irtimaled/bbor/config/Setting.java
new file mode 100644 (file)
index 0000000..ec7bbef
--- /dev/null
@@ -0,0 +1,48 @@
+package com.irtimaled.bbor.config;
+
+public class Setting {
+    private Object value;
+    String comment;
+
+    Setting(Object value) {
+        this.value = value;
+    }
+
+    public Boolean getBoolean(Boolean defaultValue) {
+        if (value instanceof Boolean)
+            return (Boolean) value;
+
+        return defaultValue;
+    }
+
+    int getInt(int defaultValue) {
+        if (value instanceof Integer)
+            return (Integer) value;
+
+        return defaultValue;
+    }
+
+    public void set(Object value) {
+        this.value = value;
+    }
+
+    public boolean getBoolean() {
+        return getBoolean(false);
+    }
+
+    public int getInt() {
+        return getInt(0);
+    }
+
+    String getType() {
+        if (value instanceof Integer)
+            return "I";
+        if (value instanceof Boolean)
+            return "B";
+        return "S";
+    }
+
+    Object getValue() {
+        return value;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/forge/ForgeClientProxy.java b/src/main/java/com/irtimaled/bbor/forge/ForgeClientProxy.java
new file mode 100644 (file)
index 0000000..0ec1a8b
--- /dev/null
@@ -0,0 +1,57 @@
+package com.irtimaled.bbor.forge;
+
+import com.irtimaled.bbor.client.ClientProxy;
+import net.minecraft.client.Minecraft;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraftforge.client.event.RenderWorldLastEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.InputEvent;
+import net.minecraftforge.fml.common.network.FMLNetworkEvent;
+
+public class ForgeClientProxy extends ForgeCommonProxy {
+    private ClientProxy proxy;
+
+    @Override
+    public ClientProxy getProxy() {
+        if (proxy == null) {
+            proxy = new ClientProxy();
+        }
+        return proxy;
+    }
+
+    @SubscribeEvent
+    public void onKeyInputEvent(InputEvent.KeyInputEvent evt) {
+        getProxy().keyPressed();
+    }
+
+    @Override
+    protected void onRegisteredPlayerCountChanged(int registeredPlayerCount) {
+        getProxy().setRemoteUserCount(registeredPlayerCount-1);
+    }
+
+    @Override
+    protected boolean isRemotePlayer(EntityPlayer player) {
+        if (Minecraft.getMinecraft().isSingleplayer()) {
+            EntityPlayer singlePlayer = Minecraft.getMinecraft().player;
+            return singlePlayer != null && player.getGameProfile() != singlePlayer.getGameProfile();
+        }
+        return true;
+    }
+
+    @SubscribeEvent
+    public void renderWorldLastEvent(RenderWorldLastEvent event) {
+        getProxy().render(event.getPartialTicks());
+    }
+
+    @SubscribeEvent
+    public void clientConnectionToServerEvent(FMLNetworkEvent.ClientConnectedToServerEvent evt) {
+        if (!evt.isLocal()) {
+            getProxy().playerConnectedToServer(evt.getManager());
+        }
+    }
+
+    @SubscribeEvent
+    public void clientDisconnectionFromServerEvent(FMLNetworkEvent.ClientDisconnectionFromServerEvent evt) {
+        getProxy().playerDisconnectedFromServer();
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/forge/ForgeCommonProxy.java b/src/main/java/com/irtimaled/bbor/forge/ForgeCommonProxy.java
new file mode 100644 (file)
index 0000000..956275f
--- /dev/null
@@ -0,0 +1,206 @@
+package com.irtimaled.bbor.forge;
+
+import com.irtimaled.bbor.Logger;
+import com.irtimaled.bbor.common.BoundingBoxCache;
+import com.irtimaled.bbor.common.CommonProxy;
+import com.irtimaled.bbor.common.DimensionCache;
+import com.irtimaled.bbor.common.IVillageEventHandler;
+import com.irtimaled.bbor.common.models.BoundingBox;
+import com.irtimaled.bbor.forge.messages.*;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.network.NetHandlerPlayServer;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.world.DimensionType;
+import net.minecraft.world.World;
+import net.minecraftforge.event.world.ChunkEvent;
+import net.minecraftforge.event.world.WorldEvent;
+import net.minecraftforge.fml.common.FMLCommonHandler;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.PlayerEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import net.minecraftforge.fml.common.network.FMLNetworkEvent;
+import net.minecraftforge.fml.common.network.NetworkRegistry;
+import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
+import net.minecraftforge.fml.relauncher.Side;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ForgeCommonProxy implements IVillageEventHandler {
+    private Map<EntityPlayerMP, DimensionType> playerDimensions = new ConcurrentHashMap<>();
+    private Map<EntityPlayerMP, Set<BoundingBox>> playerBoundingBoxesCache = new HashMap<>();
+    private HashSet<EntityPlayerMP> registeredPlayers = new HashSet<>();
+
+    protected CommonProxy getProxy() {
+        if (commonProxy == null)
+            commonProxy = new CommonProxy();
+        return commonProxy;
+    }
+
+    @SubscribeEvent
+    public void packetRegistrationEvent(FMLNetworkEvent.CustomPacketRegistrationEvent event) {
+        if (event.getOperation().equals("REGISTER") &&
+                event.getRegistrations().contains("bbor") &&
+                event.getHandler() instanceof NetHandlerPlayServer) {
+            registeredPlayers.add(((NetHandlerPlayServer) event.getHandler()).player);
+            onRegisteredPlayerCountChanged(registeredPlayers.size());
+        }
+    }
+
+    protected SimpleNetworkWrapper network;
+    private CommonProxy commonProxy;
+
+    void init() {
+        CommonProxy proxy = getProxy();
+        proxy.setEventHandler(this);
+        proxy.init();
+        network = NetworkRegistry.INSTANCE.newSimpleChannel("bbor");
+        network.registerMessage(AddBoundingBoxMessageHandler.class, AddBoundingBoxMessage.class, 0, Side.CLIENT);
+        network.registerMessage(RemoveBoundingBoxMessageHandler.class, RemoveBoundingBoxMessage.class, 1, Side.CLIENT);
+        network.registerMessage(InitializeClientMessageHandler.class, InitializeClientMessage.class, 2, Side.CLIENT);
+    }
+
+    @SubscribeEvent
+    public void worldEvent(WorldEvent.Load event) {
+        World world = event.getWorld();
+        getProxy().worldLoaded(world);
+    }
+
+    @SubscribeEvent
+    public void chunkEvent(ChunkEvent.Load event) {
+        getProxy().chunkLoaded(event.getChunk());
+    }
+
+    @SubscribeEvent
+    public void playerChangedDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent evt) {
+        if (playerDimensions.containsKey(evt.player)) {
+            EntityPlayerMP player = (EntityPlayerMP) evt.player;
+            sendBoundingBoxes(player);
+        }
+    }
+
+    @SubscribeEvent
+    public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent evt) {
+        if (evt.player instanceof EntityPlayerMP &&
+                isRemotePlayer(evt.player)) {
+            EntityPlayerMP player = (EntityPlayerMP) evt.player;
+            initializeClient(player);
+            sendBoundingBoxes(player);
+        }
+    }
+
+    private void sendBoundingBoxes(EntityPlayerMP player) {
+        DimensionType dimensionType = DimensionType.getById(player.dimension);
+        playerDimensions.put(player, dimensionType);
+        sendToPlayer(player, getDimensionCache().getBoundingBoxes(dimensionType));
+    }
+
+    protected boolean isRemotePlayer(EntityPlayer player) {
+        return registeredPlayers.contains(player);
+    }
+
+    private void initializeClient(EntityPlayerMP player) {
+        network.sendTo(InitializeClientMessage.from(getDimensionCache().getWorldData()), player);
+    }
+
+    @SubscribeEvent
+    public void playerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent evt) {
+        if (isRemotePlayer(evt.player)) {
+            playerDimensions.remove(evt.player);
+            playerBoundingBoxesCache.remove(evt.player);
+            registeredPlayers.remove(evt.player);
+            onRegisteredPlayerCountChanged(registeredPlayers.size());
+        }
+    }
+
+    protected void onRegisteredPlayerCountChanged(int registeredPlayerCount) {
+    }
+
+    @SubscribeEvent
+    public void tickEvent(TickEvent event) {
+        for (EntityPlayerMP player : playerDimensions.keySet()) {
+            MinecraftServer mc = FMLCommonHandler.instance().getMinecraftServerInstance();
+            if (!mc.getPlayerList().getPlayers().contains(player)) {
+                playerDimensions.remove(player);
+            } else {
+                DimensionType dimensionType = playerDimensions.get(player);
+                sendToPlayer(player, getDimensionCache().getBoundingBoxes(dimensionType));
+            }
+        }
+        getProxy().tick();
+    }
+
+    private void sendToPlayer(EntityPlayerMP player, BoundingBoxCache boundingBoxCache) {
+        if (boundingBoxCache == null)
+            return;
+        Map<BoundingBox, Set<BoundingBox>> cacheSubset = getBoundingBoxMap(player, boundingBoxCache.getBoundingBoxes());
+
+        DimensionType dimensionType = DimensionType.getById(player.dimension);
+        if (cacheSubset.keySet().size() > 0) {
+            Logger.info("send %d entries to %s (%s)", cacheSubset.keySet().size(), player.getDisplayNameString(), dimensionType);
+        }
+
+        for (BoundingBox key : cacheSubset.keySet()) {
+            Set<BoundingBox> boundingBoxes = cacheSubset.get(key);
+            network.sendTo(AddBoundingBoxMessage.from(dimensionType, key, boundingBoxes), player);
+
+            if (!playerBoundingBoxesCache.containsKey(player)) {
+                playerBoundingBoxesCache.put(player, new HashSet<>());
+            }
+            playerBoundingBoxesCache.get(player).add(key);
+        }
+    }
+
+    private Map<BoundingBox, Set<BoundingBox>> getBoundingBoxMap(EntityPlayerMP player, Map<BoundingBox, Set<BoundingBox>> boundingBoxMap) {
+        Map<BoundingBox, Set<BoundingBox>> 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;
+    }
+
+    public void villageRemoved(DimensionType dimensionType, BoundingBox bb) {
+        RemoveBoundingBoxMessage message = RemoveBoundingBoxMessage.from(dimensionType, bb);
+        for (EntityPlayerMP player : playerDimensions.keySet()) {
+            if (DimensionType.getById(player.dimension) == dimensionType) {
+                Logger.info("remove 1 entry from %s (%s)", player.getDisplayNameString(), dimensionType);
+                network.sendTo(message, player);
+
+                if (playerBoundingBoxesCache.containsKey(player) &&
+                        playerBoundingBoxesCache.get(player).contains(bb)) {
+                    playerBoundingBoxesCache.get(player).remove(bb);
+                }
+            }
+        }
+    }
+
+    public void setWorldData(long seed, int spawnX, int spawnZ) {
+        getDimensionCache().setWorldData(seed, spawnX, spawnZ);
+    }
+
+    public void addBoundingBox(DimensionType dimensionType, BoundingBox key, Set<BoundingBox> boundingBoxes) {
+        DimensionCache dimensionCache = getDimensionCache();
+        BoundingBoxCache cache = dimensionCache.getBoundingBoxes(dimensionType);
+        if (cache == null) {
+            dimensionCache.put(dimensionType, cache = new BoundingBoxCache());
+        }
+        cache.addBoundingBoxes(key, boundingBoxes);
+    }
+
+    public void removeBoundingBox(DimensionType dimensionType, BoundingBox key) {
+        BoundingBoxCache cache = getDimensionCache().getBoundingBoxes(dimensionType);
+        if (cache != null) {
+            cache.removeBoundingBox(key);
+        }
+    }
+
+    private DimensionCache getDimensionCache() {
+        return getProxy().getDimensionCache();
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/forge/ForgeMod.java b/src/main/java/com/irtimaled/bbor/forge/ForgeMod.java
new file mode 100644 (file)
index 0000000..3311a06
--- /dev/null
@@ -0,0 +1,36 @@
+package com.irtimaled.bbor.forge;
+
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.fml.common.Mod;
+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 = ForgeMod.MODID, name = ForgeMod.NAME, version = ForgeMod.VERSION, acceptedMinecraftVersions = ForgeMod.MCVERSION, acceptableRemoteVersions = "*")
+public class ForgeMod {
+    static final String MODID = "bbor";
+    static final String NAME = "BoundingBoxOutlineReloaded";
+    static final String VERSION = "1.0.3";
+    static final String MCVERSION = "1.12.2";
+
+    public SimpleNetworkWrapper network;
+
+    @Mod.Instance()
+    public static ForgeMod instance;
+
+    @SidedProxy(clientSide = "com.irtimaled.bbor.forge.ForgeClientProxy", serverSide = "com.irtimaled.bbor.forge.ForgeCommonProxy")
+    public static ForgeCommonProxy proxy;
+
+    @Mod.EventHandler
+    public void preInit(FMLPreInitializationEvent evt) {
+        ConfigManager.loadConfig(evt.getModConfigurationDirectory());
+    }
+
+    @Mod.EventHandler
+    public void load(FMLInitializationEvent evt) {
+        MinecraftForge.EVENT_BUS.register(proxy);
+        proxy.init();
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessage.java b/src/main/java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessage.java
new file mode 100644 (file)
index 0000000..26f5cb4
--- /dev/null
@@ -0,0 +1,61 @@
+package com.irtimaled.bbor.forge.messages;
+
+import com.irtimaled.bbor.common.models.BoundingBox;
+import io.netty.buffer.ByteBuf;
+import net.minecraft.world.DimensionType;
+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 AddBoundingBoxMessage implements IMessage {
+    private DimensionType dimensionType;
+    private BoundingBox key;
+    private Set<BoundingBox> boundingBoxes;
+
+    public static AddBoundingBoxMessage from(DimensionType dimensionType, BoundingBox key, Set<BoundingBox> boundingBoxes) {
+        AddBoundingBoxMessage message = new AddBoundingBoxMessage();
+        message.dimensionType = dimensionType;
+        message.key = key;
+        message.boundingBoxes = boundingBoxes;
+        return message;
+    }
+
+    @Override
+    public void fromBytes(ByteBuf buf) {
+        dimensionType = DimensionType.getById(ByteBufUtils.readVarInt(buf, 5));
+        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.writeVarInt(buf, dimensionType.getId(), 5);
+        BoundingBoxSerializer.serialize(key, buf);
+        if (boundingBoxes != null &&
+                boundingBoxes.size() > 1) {
+            for (BoundingBox boundingBox : boundingBoxes) {
+                BoundingBoxSerializer.serialize(boundingBox, buf);
+            }
+        }
+    }
+
+    public DimensionType getDimensionType() {
+        return dimensionType;
+    }
+
+    BoundingBox getKey() {
+        return key;
+    }
+
+    Set<BoundingBox> getBoundingBoxes() {
+        return boundingBoxes;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessageHandler.java b/src/main/java/com/irtimaled/bbor/forge/messages/AddBoundingBoxMessageHandler.java
new file mode 100644 (file)
index 0000000..37e6027
--- /dev/null
@@ -0,0 +1,14 @@
+package com.irtimaled.bbor.forge.messages;
+
+import com.irtimaled.bbor.forge.ForgeMod;
+import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
+import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
+import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
+
+public class AddBoundingBoxMessageHandler implements IMessageHandler<AddBoundingBoxMessage, IMessage> {
+    @Override
+    public IMessage onMessage(AddBoundingBoxMessage message, MessageContext ctx) {
+        ForgeMod.proxy.addBoundingBox(message.getDimensionType(), message.getKey(), message.getBoundingBoxes());
+        return null;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/forge/messages/BoundingBoxDeserializer.java b/src/main/java/com/irtimaled/bbor/forge/messages/BoundingBoxDeserializer.java
new file mode 100644 (file)
index 0000000..d044152
--- /dev/null
@@ -0,0 +1,52 @@
+package com.irtimaled.bbor.forge.messages;
+
+import com.irtimaled.bbor.common.models.BoundingBox;
+import com.irtimaled.bbor.common.models.BoundingBoxStructure;
+import com.irtimaled.bbor.common.models.BoundingBoxVillage;
+import io.netty.buffer.ByteBuf;
+import net.minecraft.util.math.BlockPos;
+import net.minecraftforge.fml.common.network.ByteBufUtils;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
+
+class BoundingBoxDeserializer {
+    static BoundingBox deserialize(ByteBuf buf) {
+        char type = (char) ByteBufUtils.readVarShort(buf);
+        switch (type) {
+            case 'V':
+                return deserializeVillage(buf);
+            case 'S':
+                return deserializeStructure(buf);
+        }
+        return null;
+    }
+
+    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));
+        Set<BlockPos> doors = new HashSet<>();
+        while (buf.isReadable()) {
+            BlockPos door = deserializeBlockPos(buf);
+            doors.add(door);
+        }
+        return BoundingBoxVillage.from(center, radius, color, spawnsIronGolems, doors);
+    }
+
+    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);
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/forge/messages/BoundingBoxSerializer.java b/src/main/java/com/irtimaled/bbor/forge/messages/BoundingBoxSerializer.java
new file mode 100644 (file)
index 0000000..f0392f6
--- /dev/null
@@ -0,0 +1,53 @@
+package com.irtimaled.bbor.forge.messages;
+
+import com.irtimaled.bbor.common.models.BoundingBox;
+import com.irtimaled.bbor.common.models.BoundingBoxStructure;
+import com.irtimaled.bbor.common.models.BoundingBoxVillage;
+import io.netty.buffer.ByteBuf;
+import net.minecraft.util.math.BlockPos;
+import net.minecraftforge.fml.common.network.ByteBufUtils;
+
+import java.awt.*;
+
+class BoundingBoxSerializer {
+    static void serialize(BoundingBox boundingBox, ByteBuf buf) {
+        if (boundingBox instanceof BoundingBoxVillage) {
+            serializeVillage((BoundingBoxVillage) boundingBox, buf);
+        }
+        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);
+        for (BlockPos door : boundingBox.getDoors()) {
+            serializeBlockPos(door, buf);
+        }
+    }
+
+    private static void serializeStructure(BoundingBoxStructure boundingBox, ByteBuf buf) {
+        ByteBufUtils.writeVarShort(buf, 'S');
+        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);
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/forge/messages/InitializeClientMessage.java b/src/main/java/com/irtimaled/bbor/forge/messages/InitializeClientMessage.java
new file mode 100644 (file)
index 0000000..684736a
--- /dev/null
@@ -0,0 +1,34 @@
+package com.irtimaled.bbor.forge.messages;
+
+import com.irtimaled.bbor.common.models.WorldData;
+import io.netty.buffer.ByteBuf;
+import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
+
+public class InitializeClientMessage implements IMessage {
+    private WorldData worldData;
+
+    public static InitializeClientMessage from(WorldData worldData) {
+        InitializeClientMessage message = new InitializeClientMessage();
+        message.worldData = new WorldData(worldData.getSeed(), worldData.getSpawnX(), worldData.getSpawnZ());
+        return message;
+    }
+
+    @Override
+    public void fromBytes(ByteBuf buf) {
+        long seed = buf.readLong();
+        int spawnX = buf.readInt();
+        int spawnZ = buf.readInt();
+        worldData = new WorldData(seed, spawnX, spawnZ);
+    }
+
+    @Override
+    public void toBytes(ByteBuf buf) {
+        buf.writeLong(worldData.getSeed());
+        buf.writeInt(worldData.getSpawnX());
+        buf.writeInt(worldData.getSpawnZ());
+    }
+
+    WorldData getWorldData() {
+        return worldData;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/forge/messages/InitializeClientMessageHandler.java b/src/main/java/com/irtimaled/bbor/forge/messages/InitializeClientMessageHandler.java
new file mode 100644 (file)
index 0000000..176231a
--- /dev/null
@@ -0,0 +1,16 @@
+package com.irtimaled.bbor.forge.messages;
+
+import com.irtimaled.bbor.common.models.WorldData;
+import com.irtimaled.bbor.forge.ForgeMod;
+import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
+import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
+import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
+
+public class InitializeClientMessageHandler implements IMessageHandler<InitializeClientMessage, IMessage> {
+    @Override
+    public IMessage onMessage(InitializeClientMessage message, MessageContext ctx) {
+        WorldData worldData = message.getWorldData();
+        ForgeMod.proxy.setWorldData(worldData.getSeed(), worldData.getSpawnX(), worldData.getSpawnZ());
+        return null;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessage.java b/src/main/java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessage.java
new file mode 100644 (file)
index 0000000..283dbe1
--- /dev/null
@@ -0,0 +1,39 @@
+package com.irtimaled.bbor.forge.messages;
+
+import com.irtimaled.bbor.common.models.BoundingBox;
+import io.netty.buffer.ByteBuf;
+import net.minecraft.world.DimensionType;
+import net.minecraftforge.fml.common.network.ByteBufUtils;
+import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
+
+public class RemoveBoundingBoxMessage implements IMessage {
+    private DimensionType dimensionType;
+    private BoundingBox key;
+
+    public static RemoveBoundingBoxMessage from(DimensionType dimensionType, BoundingBox key) {
+        RemoveBoundingBoxMessage message = new RemoveBoundingBoxMessage();
+        message.dimensionType = dimensionType;
+        message.key = key;
+        return message;
+    }
+
+    @Override
+    public void fromBytes(ByteBuf buf) {
+        dimensionType = DimensionType.getById(ByteBufUtils.readVarInt(buf, 5));
+        key = BoundingBoxDeserializer.deserialize(buf);
+    }
+
+    @Override
+    public void toBytes(ByteBuf buf) {
+        ByteBufUtils.writeVarInt(buf, dimensionType.getId(), 5);
+        BoundingBoxSerializer.serialize(key, buf);
+    }
+
+    public DimensionType getDimensionType() {
+        return dimensionType;
+    }
+
+    BoundingBox getKey() {
+        return key;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessageHandler.java b/src/main/java/com/irtimaled/bbor/forge/messages/RemoveBoundingBoxMessageHandler.java
new file mode 100644 (file)
index 0000000..58c972c
--- /dev/null
@@ -0,0 +1,14 @@
+package com.irtimaled.bbor.forge.messages;
+
+import com.irtimaled.bbor.forge.ForgeMod;
+import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
+import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
+import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
+
+public class RemoveBoundingBoxMessageHandler implements IMessageHandler<RemoveBoundingBoxMessage, IMessage> {
+    @Override
+    public IMessage onMessage(RemoveBoundingBoxMessage message, MessageContext ctx) {
+        ForgeMod.proxy.removeBoundingBox(message.getDimensionType(), message.getKey());
+        return null;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/litemod/LiteMod.java b/src/main/java/com/irtimaled/bbor/litemod/LiteMod.java
new file mode 100644 (file)
index 0000000..bdd1f86
--- /dev/null
@@ -0,0 +1,36 @@
+package com.irtimaled.bbor.litemod;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+import com.mumfrey.liteloader.Tickable;
+import net.minecraft.client.Minecraft;
+
+import java.io.File;
+
+public class LiteMod implements Tickable  {
+    public LiteMod() {
+    }
+
+    @Override
+    public String getName() {
+        return "BoundingBoxOutlineReloaded";
+    }
+
+    @Override
+    public String getVersion() {
+        return "1.0.1";
+    }
+
+    @Override
+    public void init(File configPath) {
+        BoundingBoxOutlineReloaded.init();
+    }
+
+    @Override
+    public void upgradeSettings(String version, File configPath, File oldConfigPath) {
+    }
+
+    @Override
+    public void onTick(Minecraft minecraft, float partialTicks, boolean inGame, boolean clock) {
+        BoundingBoxOutlineReloaded.keyPressed();
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinChunk.java b/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinChunk.java
new file mode 100644 (file)
index 0000000..eadba89
--- /dev/null
@@ -0,0 +1,17 @@
+package com.irtimaled.bbor.litemod.mixins;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+import net.minecraft.world.chunk.Chunk;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(Chunk.class)
+public abstract class MixinChunk {
+    @Inject(method = "onLoad",
+            at = @At("RETURN"))
+    private void onLoaded(CallbackInfo ci) {
+        BoundingBoxOutlineReloaded.chunkLoaded((Chunk)(Object)this);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer.java b/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer.java
new file mode 100644 (file)
index 0000000..9833c42
--- /dev/null
@@ -0,0 +1,21 @@
+package com.irtimaled.bbor.litemod.mixins;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+import com.mumfrey.liteloader.client.overlays.IEntityRenderer;
+import net.minecraft.client.renderer.EntityRenderer;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(EntityRenderer.class)
+public abstract class MixinEntityRenderer implements IEntityRenderer {
+    @Inject(method = "renderWorldPass",
+            at = @At(shift = At.Shift.BEFORE,
+                    value = "INVOKE_STRING",
+                    target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V",
+                    args = "ldc=hand"))
+    private void onRenderHand(int pass, float partialTicks, long timeSlice, CallbackInfo ci) {
+        BoundingBoxOutlineReloaded.render(partialTicks);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer.java b/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer.java
new file mode 100644 (file)
index 0000000..e23c038
--- /dev/null
@@ -0,0 +1,27 @@
+package com.irtimaled.bbor.litemod.mixins;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.integrated.IntegratedServer;
+import net.minecraft.world.World;
+import net.minecraft.world.WorldType;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(IntegratedServer.class)
+public abstract class MixinIntegratedServer extends MinecraftServer {
+    public MixinIntegratedServer() {
+        super(null, null, null, null, null, null, null);
+    }
+
+    @Inject(method = "loadAllWorlds",
+            at = @At("RETURN"),
+            remap = false)
+    private void onLoadAllWorlds(String saveName, String worldNameIn, long seed, WorldType type, String generatorOptions, CallbackInfo ci) {
+        for (World world : this.worlds) {
+            BoundingBoxOutlineReloaded.worldLoaded(world);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinKeyBinding.java b/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinKeyBinding.java
new file mode 100644 (file)
index 0000000..b7bd818
--- /dev/null
@@ -0,0 +1,26 @@
+package com.irtimaled.bbor.litemod.mixins;
+
+import net.minecraft.client.resources.I18n;
+import net.minecraft.client.settings.KeyBinding;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Overwrite;
+import org.spongepowered.asm.mixin.Shadow;
+
+import java.util.Map;
+
+@Mixin(KeyBinding.class)
+public abstract class MixinKeyBinding implements Comparable<KeyBinding> {
+    @Shadow
+    private static Map<String, Integer> CATEGORY_ORDER;
+
+    @Shadow
+    private String keyDescription;
+
+    @Shadow
+    private String keyCategory;
+
+    @Overwrite()
+    public int compareTo(KeyBinding p_compareTo_1_) {
+        return this.keyCategory.equals(p_compareTo_1_.getKeyCategory()) ? I18n.format(this.keyDescription).compareTo(I18n.format(p_compareTo_1_.getKeyDescription())) : ((Integer) CATEGORY_ORDER.getOrDefault(this.keyCategory, 0)).compareTo(CATEGORY_ORDER.getOrDefault(p_compareTo_1_.getKeyCategory(), 0));
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinNetworkManager.java b/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinNetworkManager.java
new file mode 100644 (file)
index 0000000..e108bc2
--- /dev/null
@@ -0,0 +1,21 @@
+package com.irtimaled.bbor.litemod.mixins;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.network.Packet;
+import net.minecraft.network.login.client.CPacketLoginStart;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(NetworkManager.class)
+public abstract class MixinNetworkManager {
+    @Inject(method = "sendPacket(Lnet/minecraft/network/Packet;)V",
+            at = @At("RETURN"))
+    private void onLoaded(Packet<?> packetIn, CallbackInfo ci) {
+        if (packetIn instanceof CPacketLoginStart) {
+            BoundingBoxOutlineReloaded.playerConnectedToServer((NetworkManager)(Object)this);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinWorldClient.java b/src/main/java/com/irtimaled/bbor/litemod/mixins/MixinWorldClient.java
new file mode 100644 (file)
index 0000000..e03412c
--- /dev/null
@@ -0,0 +1,22 @@
+package com.irtimaled.bbor.litemod.mixins;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+import net.minecraft.client.multiplayer.WorldClient;
+import net.minecraft.world.World;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(WorldClient.class)
+public abstract class MixinWorldClient extends World {
+    public MixinWorldClient() {
+        super(null, null, null, null, true);
+    }
+
+    @Inject(method = "sendQuittingDisconnectingPacket",
+    at = @At("RETURN"))
+    private void onDisconnecting(CallbackInfo ci) {
+        BoundingBoxOutlineReloaded.playerDisconnectedFromServer();
+    }
+}
diff --git a/src/main/resources/litemod.json b/src/main/resources/litemod.json
new file mode 100644 (file)
index 0000000..ad93565
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "name": "bbor",
+  "displayName": "BoundingBoxOutlineReloaded",
+  "description": "Shows the bounding boxes of structures and features.",
+  "version": "1.0.1",
+  "author": "irtimaled",
+  "mcversion": "1.12.1",
+  "mixinConfigs": [
+    "mixins.bbor.json"
+  ]
+}
diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info
new file mode 100644 (file)
index 0000000..39c6045
--- /dev/null
@@ -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": "http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-mods/2345401",
+  "updateUrl": "",
+  "authorList": ["irtimaled"],
+  "credits": "Thanks to 4poc & KaboPC.",
+  "logoFile": "",
+  "screenshots": [],
+  "dependencies": []
+}
+]
+
diff --git a/src/main/resources/mixins.bbor.json b/src/main/resources/mixins.bbor.json
new file mode 100644 (file)
index 0000000..8c7a41b
--- /dev/null
@@ -0,0 +1,19 @@
+{
+  "required": true,
+  "minVersion": "0.7.3",
+  "compatibilityLevel": "JAVA_8",
+  "target": "@env(DEFAULT)",
+  "package": "com.irtimaled.bbor.litemod.mixins",
+  "refmap": "mixins.bbor.refmap.json",
+  "mixins": [
+    "MixinIntegratedServer",
+    "MixinEntityRenderer",
+    "MixinChunk",
+    "MixinNetworkManager",
+    "MixinWorldClient",
+    "MixinKeyBinding"
+  ],
+  "injectors": {
+    "defaultRequire": 1
+  }
+}
diff --git a/src/main/resources/mixins.bbor.refmap.json b/src/main/resources/mixins.bbor.refmap.json
new file mode 100644 (file)
index 0000000..56feab2
--- /dev/null
@@ -0,0 +1,67 @@
+{
+  "mappings": {
+    "com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer": {
+      "loadAllWorlds": "Lchd;a(Ljava/lang/String;Ljava/lang/String;JLamz;Ljava/lang/String;)V"
+    },
+    "com/irtimaled/bbor/litemod/mixins/MixinNetworkManager": {
+      "sendPacket(Lnet/minecraft/network/Packet;)V": "Lgw;a(Lht;)V"
+    },
+    "com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer": {
+      "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V": "Lrl;c(Ljava/lang/String;)V",
+      "renderWorldPass": "Lbuq;a(IFJ)V"
+    },
+    "com/irtimaled/bbor/litemod/mixins/MixinWorldClient": {
+      "sendQuittingDisconnectingPacket": "Lbsb;O()V"
+    },
+    "com/irtimaled/bbor/litemod/mixins/MixinChunk": {
+      "onLoad": "Laxw;c()V"
+    },
+    "com/irtimaled/bbor/litemod/mixins/MixinKeyBinding": {
+      "compareTo": "Lbhy;a(Lbhy;)I"
+    }
+  },
+  "data": {
+    "notch": {
+      "com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer": {
+        "loadAllWorlds": "Lchd;a(Ljava/lang/String;Ljava/lang/String;JLamz;Ljava/lang/String;)V"
+      },
+      "com/irtimaled/bbor/litemod/mixins/MixinNetworkManager": {
+        "sendPacket(Lnet/minecraft/network/Packet;)V": "Lgw;a(Lht;)V"
+      },
+      "com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer": {
+        "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V": "Lrl;c(Ljava/lang/String;)V",
+        "renderWorldPass": "Lbuq;a(IFJ)V"
+      },
+      "com/irtimaled/bbor/litemod/mixins/MixinWorldClient": {
+        "sendQuittingDisconnectingPacket": "Lbsb;O()V"
+      },
+      "com/irtimaled/bbor/litemod/mixins/MixinChunk": {
+        "onLoad": "Laxw;c()V"
+      },
+      "com/irtimaled/bbor/litemod/mixins/MixinKeyBinding": {
+        "compareTo": "Lbhy;a(Lbhy;)I"
+      }
+    },
+    "searge": {
+      "com/irtimaled/bbor/litemod/mixins/MixinIntegratedServer": {
+        "loadAllWorlds": "Lnet/minecraft/server/integrated/IntegratedServer;func_71247_a(Ljava/lang/String;Ljava/lang/String;JLnet/minecraft/world/WorldType;Ljava/lang/String;)V"
+      },
+      "com/irtimaled/bbor/litemod/mixins/MixinNetworkManager": {
+        "sendPacket(Lnet/minecraft/network/Packet;)V": "Lnet/minecraft/network/NetworkManager;func_179290_a(Lnet/minecraft/network/Packet;)V"
+      },
+      "com/irtimaled/bbor/litemod/mixins/MixinEntityRenderer": {
+        "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V": "Lnet/minecraft/profiler/Profiler;func_76318_c(Ljava/lang/String;)V",
+        "renderWorldPass": "Lnet/minecraft/client/renderer/EntityRenderer;func_175068_a(IFJ)V"
+      },
+      "com/irtimaled/bbor/litemod/mixins/MixinWorldClient": {
+        "sendQuittingDisconnectingPacket": "Lnet/minecraft/client/multiplayer/WorldClient;func_72882_A()V"
+      },
+      "com/irtimaled/bbor/litemod/mixins/MixinChunk": {
+        "onLoad": "Lnet/minecraft/world/chunk/Chunk;func_76631_c()V"
+      },
+      "com/irtimaled/bbor/litemod/mixins/MixinKeyBinding": {
+        "compareTo": "Lnet/minecraft/client/settings/KeyBinding;compareTo(Lnet/minecraft/client/settings/KeyBinding;)I"
+      }
+    }
+  }
+}
diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta
new file mode 100644 (file)
index 0000000..c00c642
--- /dev/null
@@ -0,0 +1,7 @@
+{
+    "pack": {
+        "description": "bbor resources",
+        "pack_format": 3,
+        "_comment": "A pack_format of 3 should be used starting with Minecraft 1.11. All resources, including language files, should be lowercase (eg: en_us.lang). A pack_format of 2 will load your mod resources with LegacyV2Adapter, which requires language files to have uppercase letters (eg: en_US.lang)."
+    }
+}