]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/commitdiff
Refactor for new version consistency
authorirtimaled <irtimaled@gmail.com>
Fri, 1 Feb 2019 00:26:48 +0000 (16:26 -0800)
committerirtimaled <irtimaled@gmail.com>
Fri, 1 Feb 2019 00:59:32 +0000 (16:59 -0800)
89 files changed:
.gitignore
build.gradle
src/java/com/irtimaled/bbor/Logger.java [deleted file]
src/java/com/irtimaled/bbor/client/BoundingBoxOutlineReloaded.java [deleted file]
src/java/com/irtimaled/bbor/client/ClientBoundingBoxProvider.java [deleted file]
src/java/com/irtimaled/bbor/client/ClientDimensionCache.java [deleted file]
src/java/com/irtimaled/bbor/client/ClientProxy.java [deleted file]
src/java/com/irtimaled/bbor/client/ClientRenderer.java [deleted file]
src/java/com/irtimaled/bbor/client/NBTFileParser.java [deleted file]
src/java/com/irtimaled/bbor/client/PlayerData.java [deleted file]
src/java/com/irtimaled/bbor/client/renderers/Renderer.java [deleted file]
src/java/com/irtimaled/bbor/client/renderers/SlimeChunkRenderer.java [deleted file]
src/java/com/irtimaled/bbor/client/renderers/StructureRenderer.java [deleted file]
src/java/com/irtimaled/bbor/client/renderers/VillageRenderer.java [deleted file]
src/java/com/irtimaled/bbor/client/renderers/WorldSpawnRenderer.java [deleted file]
src/java/com/irtimaled/bbor/common/BoundingBoxCache.java [deleted file]
src/java/com/irtimaled/bbor/common/CommonProxy.java [deleted file]
src/java/com/irtimaled/bbor/common/DimensionCache.java [deleted file]
src/java/com/irtimaled/bbor/common/DimensionProcessor.java [deleted file]
src/java/com/irtimaled/bbor/common/IVillageEventHandler.java [deleted file]
src/java/com/irtimaled/bbor/common/StructureType.java [deleted file]
src/java/com/irtimaled/bbor/common/VillageColorCache.java [deleted file]
src/java/com/irtimaled/bbor/common/VillageProcessor.java [deleted file]
src/java/com/irtimaled/bbor/common/models/BoundingBox.java [deleted file]
src/java/com/irtimaled/bbor/common/models/BoundingBoxSlimeChunk.java [deleted file]
src/java/com/irtimaled/bbor/common/models/BoundingBoxStructure.java [deleted file]
src/java/com/irtimaled/bbor/common/models/BoundingBoxVillage.java [deleted file]
src/java/com/irtimaled/bbor/common/models/BoundingBoxWorldSpawn.java [deleted file]
src/java/com/irtimaled/bbor/common/models/WorldData.java [deleted file]
src/java/com/irtimaled/bbor/config/ConfigManager.java [deleted file]
src/java/com/irtimaled/bbor/config/Configuration.java [deleted file]
src/java/com/irtimaled/bbor/config/Setting.java [deleted file]
src/java/com/irtimaled/bbor/install/Main.java [deleted file]
src/java/com/irtimaled/bbor/launch/ClientTweaker.java [deleted file]
src/java/com/irtimaled/bbor/launch/ServerTweaker.java [deleted file]
src/java/com/irtimaled/bbor/launch/Tweaker.java [deleted file]
src/java/com/irtimaled/bbor/mixin/client/MixinMinecraft.java [deleted file]
src/java/com/irtimaled/bbor/mixin/client/multiplayer/MixinWorldClient.java [deleted file]
src/java/com/irtimaled/bbor/mixin/client/renderer/MixinEntityRenderer.java [deleted file]
src/java/com/irtimaled/bbor/mixin/client/settings/MixinKeyBinding.java [deleted file]
src/java/com/irtimaled/bbor/mixin/network/MixinNetworkManager.java [deleted file]
src/java/com/irtimaled/bbor/mixin/server/MixinMinecraftServer.java [deleted file]
src/java/com/irtimaled/bbor/mixin/world/chunk/MixinChunk.java [deleted file]
src/main/java/com/irtimaled/bbor/Logger.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/install/Main.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/launch/ClientTweaker.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/launch/ServerTweaker.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/launch/Tweaker.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/mixin/client/MixinMinecraft.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/mixin/client/multiplayer/MixinWorldClient.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/mixin/client/renderer/MixinEntityRenderer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/mixin/client/settings/MixinGameSettings.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/mixin/client/settings/MixinKeyBinding.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/mixin/network/MixinNetworkManager.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/mixin/server/MixinMinecraftServer.java [new file with mode: 0644]
src/main/java/com/irtimaled/bbor/mixin/world/chunk/MixinChunk.java [new file with mode: 0644]
src/main/resources/mixins.bbor.json [new file with mode: 0644]
src/main/resources/profile.json [new file with mode: 0644]
src/resources/mixins.bbor.json [deleted file]
src/resources/profile.json [deleted file]

index eae3eac42ee3b14932b87fbd01952d25d41ab95b..96d71af634454fbf659ba67683dfa0d96dcdad57 100644 (file)
@@ -2,3 +2,5 @@
 .gradle
 build
 run
+.idea
+classes
index 6e1f8eed3996f35b907e7b77da237a9cd02cb832..f45490c62d9c5f05ea17c7793342919e014eca01 100644 (file)
@@ -18,8 +18,9 @@ apply plugin: 'com.github.johnrengelman.shadow'
 apply plugin: 'org.spongepowered.mixin'
 apply plugin: 'maven-publish'
 
+def mcVersion = '1.13'
 group 'com.irtimaled'
-version '1.0.4-beta2'
+version "1.0.4-beta3-$mcVersion"
 archivesBaseName = 'BBOutlineReloaded'
 
 sourceCompatibility = 1.8
@@ -33,14 +34,14 @@ repositories {
 }
 
 dependencies {
-    compile('org.spongepowered:mixin:0.7.11-SNAPSHOT')
+    compile('org.spongepowered:mixin:0.7.11-SNAPSHOT') { transitive = false }
     implementation('net.minecraft:launchwrapper:1.12') { transitive = false }
     implementation 'org.ow2.asm:asm:6.2'
     implementation 'org.ow2.asm:asm-commons:6.2'
 }
 
 minecraft {
-    version = '1.13'
+    version = mcVersion
     mappings = 'snapshot_20180908'
     runDir = 'run'
     tweakClass = 'com.irtimaled.bbor.launch.ClientTweaker'
@@ -77,7 +78,7 @@ processResources {
 
     // Re-run this task when these change
     inputs.property "version", project.version
-    inputs.property "mcversion", project.minecraft.version
+    inputs.property "mcVersion", project.minecraft.version
 }
 
 jar {
@@ -92,11 +93,6 @@ task devJar(type: Jar, dependsOn: classes) {
     from sourceSets.main.output
 }
 
-task sourcesJar(type: Jar, dependsOn: classes) {
-    classifier 'sources'
-    from sourceSets.main.allSource
-}
-
 shadowJar {
     dependsOn 'reobfJar'
     from sourceSets.main.output
@@ -110,7 +106,7 @@ shadowJar {
         include(dependency('org.spongepowered:mixin'))
     }
     
-    classifier = 'vanilla' + project.minecraft.version
+    classifier = 'vanilla'
 }
 
 reobf {
@@ -131,6 +127,4 @@ build.dependsOn {[
 
 artifacts {
     archives shadowJar
-    archives sourceJar
-    archives devJar
 }
\ No newline at end of file
diff --git a/src/java/com/irtimaled/bbor/Logger.java b/src/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/src/java/com/irtimaled/bbor/client/BoundingBoxOutlineReloaded.java b/src/java/com/irtimaled/bbor/client/BoundingBoxOutlineReloaded.java
deleted file mode 100644 (file)
index 134710b..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.getInstance().gameDir, "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/java/com/irtimaled/bbor/client/ClientBoundingBoxProvider.java b/src/java/com/irtimaled/bbor/client/ClientBoundingBoxProvider.java
deleted file mode 100644 (file)
index b535a10..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.dimension.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.getInstance();
-        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/java/com/irtimaled/bbor/client/ClientDimensionCache.java b/src/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/src/java/com/irtimaled/bbor/client/ClientProxy.java b/src/java/com/irtimaled/bbor/client/ClientProxy.java
deleted file mode 100644 (file)
index f905eeb..0000000
+++ /dev/null
@@ -1,87 +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.dimension.DimensionType;
-import org.apache.commons.lang3.ArrayUtils;
-
-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", 0x42, category);
-        outerBoxOnlyHotKey = new KeyBinding("Toggle Display Outer Box Only", 0x4f, category);
-        Minecraft.getInstance().gameSettings.keyBindings = ArrayUtils.addAll(Minecraft.getInstance().gameSettings.keyBindings, activeHotKey, outerBoxOnlyHotKey);
-        ClientDimensionCache clientDimensionCache = new ClientDimensionCache();
-        renderer = new ClientRenderer(clientDimensionCache);
-        dimensionCache = clientDimensionCache;
-    }
-
-    public void render(float partialTicks) {
-        EntityPlayer entityPlayer = Minecraft.getInstance().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/java/com/irtimaled/bbor/client/ClientRenderer.java b/src/java/com/irtimaled/bbor/client/ClientRenderer.java
deleted file mode 100644 (file)
index 61ba392..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.dimension.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.getInstance().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/java/com/irtimaled/bbor/client/NBTFileParser.java b/src/java/com/irtimaled/bbor/client/NBTFileParser.java
deleted file mode 100644 (file)
index 719fb18..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.dimension.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.size()];
-        for (int index = 0; index < tagList.size(); index++) {
-            result[index] = tagList.getCompoundTagAt(index);
-        }
-        return result;
-    }
-}
diff --git a/src/java/com/irtimaled/bbor/client/PlayerData.java b/src/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/src/java/com/irtimaled/bbor/client/renderers/Renderer.java b/src/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/src/java/com/irtimaled/bbor/client/renderers/SlimeChunkRenderer.java b/src/java/com/irtimaled/bbor/client/renderers/SlimeChunkRenderer.java
deleted file mode 100644 (file)
index 173007a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.irtimaled.bbor.client.renderers;
-
-import com.irtimaled.bbor.client.PlayerData;
-import com.irtimaled.bbor.common.models.BoundingBoxSlimeChunk;
-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/java/com/irtimaled/bbor/client/renderers/StructureRenderer.java b/src/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/src/java/com/irtimaled/bbor/client/renderers/VillageRenderer.java b/src/java/com/irtimaled/bbor/client/renderers/VillageRenderer.java
deleted file mode 100644 (file)
index 88392e0..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-package com.irtimaled.bbor.client.renderers;
-
-import com.irtimaled.bbor.client.PlayerData;
-import com.irtimaled.bbor.common.models.BoundingBoxVillage;
-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/java/com/irtimaled/bbor/client/renderers/WorldSpawnRenderer.java b/src/java/com/irtimaled/bbor/client/renderers/WorldSpawnRenderer.java
deleted file mode 100644 (file)
index 96e07ac..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.irtimaled.bbor.client.renderers;
-
-import com.irtimaled.bbor.client.PlayerData;
-import com.irtimaled.bbor.common.models.BoundingBoxWorldSpawn;
-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/java/com/irtimaled/bbor/common/BoundingBoxCache.java b/src/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/src/java/com/irtimaled/bbor/common/CommonProxy.java b/src/java/com/irtimaled/bbor/common/CommonProxy.java
deleted file mode 100644 (file)
index 115cf2b..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.irtimaled.bbor.common;
-
-
-import com.irtimaled.bbor.Logger;
-import com.irtimaled.bbor.config.ConfigManager;
-import net.minecraft.world.World;
-import net.minecraft.world.chunk.Chunk;
-import net.minecraft.world.chunk.IChunkProvider;
-import net.minecraft.world.dimension.DimensionType;
-import net.minecraft.world.gen.ChunkProviderServer;
-
-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) {
-            dimensionCache.setWorldData(world.getSeed(), world.getWorldInfo().getSpawnX(), world.getWorldInfo().getSpawnZ());
-            DimensionType dimensionType = world.dimension.getType();
-            Logger.info("create world dimension: %s, %s (seed: %d)", dimensionType, world.getClass().toString(), world.getSeed());
-            DimensionProcessor boundingBoxCache = new DimensionProcessor(dimensionType, (ChunkProviderServer)chunkProvider);
-            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().dimension.getType();
-        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/java/com/irtimaled/bbor/common/DimensionCache.java b/src/java/com/irtimaled/bbor/common/DimensionCache.java
deleted file mode 100644 (file)
index 86004d5..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.irtimaled.bbor.common;
-
-import com.irtimaled.bbor.common.models.WorldData;
-import net.minecraft.world.dimension.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/java/com/irtimaled/bbor/common/DimensionProcessor.java b/src/java/com/irtimaled/bbor/common/DimensionProcessor.java
deleted file mode 100644 (file)
index c9ed1c4..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.irtimaled.bbor.common;
-
-import com.irtimaled.bbor.Logger;
-import com.irtimaled.bbor.common.models.BoundingBox;
-import com.irtimaled.bbor.common.models.BoundingBoxStructure;
-import com.irtimaled.bbor.config.ConfigManager;
-import com.irtimaled.bbor.config.Setting;
-import net.minecraft.util.math.MutableBoundingBox;
-import net.minecraft.world.chunk.Chunk;
-import net.minecraft.world.dimension.DimensionType;
-import net.minecraft.world.gen.ChunkProviderServer;
-import net.minecraft.world.gen.feature.structure.StructurePiece;
-import net.minecraft.world.gen.feature.structure.StructureStart;
-
-import java.awt.*;
-import java.util.*;
-
-public class DimensionProcessor extends BoundingBoxCache {
-    DimensionProcessor(DimensionType dimensionType, ChunkProviderServer chunkProvider) {
-        this.dimensionType = dimensionType;
-        this.chunkProvider = chunkProvider;
-    }
-
-    private DimensionType dimensionType;
-    private ChunkProviderServer chunkProvider;
-
-    private boolean closed = false;
-
-    @Override
-    public void close() {
-        closed = true;
-        super.close();
-    }
-
-    private void addStructures(Setting drawStructure, StructureType structureType, Map<String, Collection<StructureStart>> structureMap) {
-        if (!drawStructure.getBoolean()) return;
-
-        Collection<StructureStart> structureStarts = structureMap.get(structureType.getName());
-        if (structureStarts == null || structureStarts.size() == 0) return;
-        Color color = structureType.getColor();
-        for (StructureStart structureStart : structureStarts) {
-
-            MutableBoundingBox bb = structureStart.getBoundingBox();
-            if(bb == null)
-                continue;
-
-            BoundingBox boundingBox = BoundingBoxStructure.from(bb, color);
-            if (isCached(boundingBox)) continue;
-
-            Set<BoundingBox> structureBoundingBoxes = new HashSet<>();
-            for (StructurePiece structureComponent : structureStart.getComponents()) {
-                structureBoundingBoxes.add(BoundingBoxStructure.from(structureComponent.getBoundingBox(), color));
-            }
-            addBoundingBoxes(boundingBox, structureBoundingBoxes);
-            Logger.info("[%s] new dimensionCache entries: %d", dimensionType, structureBoundingBoxes.size());
-        }
-    }
-
-    private Map<String, Collection<StructureStart>> getStructureMap(ChunkProviderServer chunkProvider) {
-        Map<String, Collection<StructureStart>> map = new HashMap<>();
-        for (Chunk chunk : chunkProvider.getLoadedChunks()) {
-            Map<String, StructureStart> structureStarts = chunk.getStructureStarts();
-            for (String key : structureStarts.keySet())            {
-                map.computeIfAbsent(key, s -> new HashSet<>())
-                   .add(structureStarts.get(key));
-            }
-        }
-        return map;
-    }
-
-    @Override
-    public synchronized void refresh() {
-        if (closed) return;
-
-        Map<String, Collection<StructureStart>> structureMap = getStructureMap(chunkProvider);
-        if (structureMap.size() > 0) {
-            addStructures(ConfigManager.drawDesertTemples, StructureType.DesertTemple, structureMap);
-            addStructures(ConfigManager.drawJungleTemples, StructureType.JungleTemple, structureMap);
-            addStructures(ConfigManager.drawWitchHuts, StructureType.WitchHut, structureMap);
-            addStructures(ConfigManager.drawOceanMonuments, StructureType.OceanMonument, structureMap);
-            addStructures(ConfigManager.drawStrongholds, StructureType.Stronghold, structureMap);
-            addStructures(ConfigManager.drawMansions, StructureType.Mansion, structureMap);
-            addStructures(ConfigManager.drawMineShafts, StructureType.MineShaft, structureMap);
-            addStructures(ConfigManager.drawShipwrecks, StructureType.Shipwreck, structureMap);
-            addStructures(ConfigManager.drawOceanRuins, StructureType.OceanRuin, structureMap);
-            addStructures(ConfigManager.drawBuriedTreasure, StructureType.BuriedTreasure, structureMap);
-            addStructures(ConfigManager.drawIgloos, StructureType.Igloo, structureMap);
-            addStructures(ConfigManager.drawNetherFortresses, StructureType.NetherFortress, structureMap);
-            addStructures(ConfigManager.drawEndCities, StructureType.EndCity, structureMap);
-        }
-    }
-}
diff --git a/src/java/com/irtimaled/bbor/common/IVillageEventHandler.java b/src/java/com/irtimaled/bbor/common/IVillageEventHandler.java
deleted file mode 100644 (file)
index d28efff..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.irtimaled.bbor.common;
-
-import com.irtimaled.bbor.common.models.BoundingBox;
-import net.minecraft.world.dimension.DimensionType;
-
-public interface IVillageEventHandler {
-    void villageRemoved(DimensionType dimensionType, BoundingBox bb);
-}
diff --git a/src/java/com/irtimaled/bbor/common/StructureType.java b/src/java/com/irtimaled/bbor/common/StructureType.java
deleted file mode 100644 (file)
index a1493ad..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.irtimaled.bbor.common;
-import java.awt.*;
-
-public class StructureType {
-    public final static StructureType JungleTemple = new StructureType(Color.GREEN, "Jungle_Pyramid");
-    public final static StructureType DesertTemple = new StructureType(Color.ORANGE, "Desert_Pyramid");
-    public final static StructureType WitchHut = new StructureType(Color.BLUE, "Swamp_Hut");
-    public final static StructureType OceanMonument = new StructureType(Color.CYAN, "Monument");
-    public final static StructureType Shipwreck = new StructureType(Color.CYAN, "Shipwreck");
-    public final static StructureType OceanRuin = new StructureType(Color.CYAN, "Ocean_Ruin");
-    public final static StructureType BuriedTreasure = new StructureType(Color.CYAN, "Buried_Treasure");
-    public final static StructureType Stronghold = new StructureType(Color.YELLOW, "Stronghold");
-    public final static StructureType MineShaft = new StructureType(Color.LIGHT_GRAY, "Mineshaft");
-    public final static StructureType NetherFortress = new StructureType(Color.RED, "Fortress");
-    public final static StructureType EndCity = new StructureType(Color.MAGENTA, "EndCity");
-    public final static StructureType Mansion = new StructureType(new Color(139, 69, 19), "Mansion");
-    public final static StructureType Igloo = new StructureType(Color.WHITE, "Igloo");
-
-    private final Color color;
-    private String name;
-
-    private StructureType(Color color, String name) {
-        this.color = color;
-        this.name = name;
-    }
-
-    public Color getColor() {
-        return color;
-    }
-
-    public String getName() {
-        return name;
-    }
-}
diff --git a/src/java/com/irtimaled/bbor/common/VillageColorCache.java b/src/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/src/java/com/irtimaled/bbor/common/VillageProcessor.java b/src/java/com/irtimaled/bbor/common/VillageProcessor.java
deleted file mode 100644 (file)
index 2bdbe6e..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.World;
-import net.minecraft.world.dimension.DimensionType;
-
-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/java/com/irtimaled/bbor/common/models/BoundingBox.java b/src/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/src/java/com/irtimaled/bbor/common/models/BoundingBoxSlimeChunk.java b/src/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/src/java/com/irtimaled/bbor/common/models/BoundingBoxStructure.java b/src/java/com/irtimaled/bbor/common/models/BoundingBoxStructure.java
deleted file mode 100644 (file)
index 50c53a0..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.irtimaled.bbor.common.models;
-
-import net.minecraft.util.math.BlockPos;
-import net.minecraft.util.math.MutableBoundingBox;
-
-import java.awt.*;
-
-public class BoundingBoxStructure extends BoundingBox {
-    private BoundingBoxStructure(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
-        super(minBlockPos, maxBlockPos, color);
-    }
-
-    public static BoundingBoxStructure from(MutableBoundingBox 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/java/com/irtimaled/bbor/common/models/BoundingBoxVillage.java b/src/java/com/irtimaled/bbor/common/models/BoundingBoxVillage.java
deleted file mode 100644 (file)
index 44bfcfb..0000000
+++ /dev/null
@@ -1,146 +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.HashSet;
-import java.util.List;
-import java.util.Set;
-
-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/java/com/irtimaled/bbor/common/models/BoundingBoxWorldSpawn.java b/src/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/src/java/com/irtimaled/bbor/common/models/WorldData.java b/src/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/src/java/com/irtimaled/bbor/config/ConfigManager.java b/src/java/com/irtimaled/bbor/config/ConfigManager.java
deleted file mode 100644 (file)
index a280d1d..0000000
+++ /dev/null
@@ -1,81 +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 Setting drawShipwrecks;
-    public static Setting drawOceanRuins;
-    public static Setting drawBuriedTreasure;
-    public static Setting drawIgloos;
-
-    public static void loadConfig(File mcConfigDir) {
-        configDir = mcConfigDir;
-        configDir.mkdirs();
-        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)");
-        drawShipwrecks = SetupBooleanProperty(config, "features", "drawShipwrecks", false, "If set to true shipwrecks will be drawn. (default: false)");
-        drawOceanRuins = SetupBooleanProperty(config, "features", "drawOceanRuins", false, "If set to true ocean ruins will be drawn. (default: false)");
-        drawBuriedTreasure = SetupBooleanProperty(config, "features", "drawBuriedTreasures", false, "If set to true buried treasure will be drawn. (default: false)");
-        drawIgloos = SetupBooleanProperty(config, "features", "drawIgloos", false, "If set to true igloos will be drawn. (default: false)");
-        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/java/com/irtimaled/bbor/config/Configuration.java b/src/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/src/java/com/irtimaled/bbor/config/Setting.java b/src/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/src/java/com/irtimaled/bbor/install/Main.java b/src/java/com/irtimaled/bbor/install/Main.java
deleted file mode 100644 (file)
index 32cb8f9..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.irtimaled.bbor.install;
-
-import javax.swing.*;
-import java.io.*;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.text.SimpleDateFormat;
-import java.util.*;
-
-public class Main {
-    public static void main(String... args) throws Throwable {
-        try {
-            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
-        } catch (Throwable t) {
-            t.printStackTrace();
-        }
-
-        try {
-            String osName = getOsName();
-            File minecraftFolder = getMinecraftFolder(osName);
-            File versionFolder = new File(minecraftFolder, "versions/@MC_VERSION@-BBOR-@VERSION@/");
-            versionFolder.mkdirs();
-
-            File versionJson = new File(versionFolder, "@MC_VERSION@-BBOR-@VERSION@.json");
-            Files.copy(Main.class.getResourceAsStream("/profile.json"), versionJson.toPath(), StandardCopyOption.REPLACE_EXISTING);
-
-            try {
-                File profilesJson = new File(minecraftFolder, "launcher_profiles.json");
-                if (profilesJson.exists()) { // TODO: use gson instead
-                    String identifier = "\"bbor-@MC_VERSION@\"";
-                    String contents = new String(Files.readAllBytes(profilesJson.toPath()));
-                    if (contents.contains(identifier)) {
-                        contents = contents.replaceAll(",\n *"+identifier+": \\{[^}]*},", ",");
-                        contents = contents.replaceAll(",?\n *"+identifier+": \\{[^}]*},?", "");
-                    }
-
-                    String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
-
-                    contents = contents.replace("\n  \"profiles\": {", "\n  \"profiles\": {\n" +
-                            "    "+identifier+": {\n" +
-                            "      \"name\": \"Bounding Box Outline Reloaded\",\n" +
-                            "      \"type\": \"custom\",\n" +
-                            "      \"created\": \""+date+"T00:00:00.000Z\",\n" +
-                            "      \"lastUsed\": \"2100-01-01T00:00:00.000Z\",\n" +
-                            "      \"lastVersionId\": \"@MC_VERSION@-BBOR-@VERSION@\"\n" +
-                            "    },");
-
-                    Files.write(profilesJson.toPath(), contents.getBytes());
-                }
-            } catch (Throwable t) {
-                t.printStackTrace();
-            }
-
-            // Copy rift jar to libraries
-            try {
-                String source = Main.class.getProtectionDomain().getCodeSource().getLocation().getPath();
-                if (source.startsWith("/") && osName.contains("win")) {
-                    source = source.substring(1);
-                }
-                File riftJar = new File(minecraftFolder, "libraries/com/irtimaled/bbor/@VERSION@/bbor-@VERSION@.jar");
-                riftJar.getParentFile().mkdirs();
-                Files.copy(Paths.get(source), riftJar.toPath(), StandardCopyOption.REPLACE_EXISTING);
-            } catch (Throwable t) {
-                t.printStackTrace();
-            }
-
-            JOptionPane.showMessageDialog(null,
-                    "Bounding Box Outline Reloaded @VERSION@ for\n Minecraft @MC_VERSION@ has been successfully installed!\n" +
-                            "\n" +
-                            "Re-open the Minecraft Launcher to see it in the dropdown.",
-                    "Bounding Box Outline Reloaded Installer", JOptionPane.INFORMATION_MESSAGE);
-        } catch (Throwable t) {
-            StringWriter w = new StringWriter();
-            t.printStackTrace(new PrintWriter(w));
-            JOptionPane.showMessageDialog(null,
-                    "An error occured while installing Bounding Box Outline Reloaded, please report this to the issue\n" +
-                            "tracker (https://github.com/irtimaled/BoundingBoxOutlineReloaded/issues):\n" +
-                            "\n" +
-                            w.toString().replace("\t", "    "), "Bounding Box Outline Reloaded Installer", JOptionPane.ERROR_MESSAGE);
-        }
-    }
-
-    private static File getMinecraftFolder(String osName) {
-        File minecraftFolder;
-        if (osName.contains("win")) {
-            minecraftFolder = new File(System.getenv("APPDATA") + "/.minecraft");
-        } else if (osName.contains("mac")) {
-            minecraftFolder = new File(System.getProperty("user.home") + "/Library/Application Support/minecraft");
-        } else {
-            minecraftFolder = new File(System.getProperty("user.home") + "/.minecraft");
-        }
-        return minecraftFolder;
-    }
-
-    private static String getOsName() {
-        return System.getProperty("os.name").toLowerCase(Locale.ROOT);
-    }
-
-}
diff --git a/src/java/com/irtimaled/bbor/launch/ClientTweaker.java b/src/java/com/irtimaled/bbor/launch/ClientTweaker.java
deleted file mode 100644 (file)
index 77eb7e0..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.irtimaled.bbor.launch;
-
-import java.io.File;
-import java.util.List;
-
-public class ClientTweaker extends Tweaker {
-    @Override
-    protected void addOptions(List<String> args, File gameDir, File assetsDir, String profile){
-        addArg("--assetsDir", assetsDir.getPath());
-    }
-
-    @Override
-    public String getLaunchTarget() {
-        return "net.minecraft.client.main.Main";
-    }
-
-    @Override
-    protected boolean isClient() {
-        return true;
-    }
-}
diff --git a/src/java/com/irtimaled/bbor/launch/ServerTweaker.java b/src/java/com/irtimaled/bbor/launch/ServerTweaker.java
deleted file mode 100644 (file)
index f214d0d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.irtimaled.bbor.launch;
-
-public class ServerTweaker extends Tweaker {
-    @Override
-    protected boolean isClient() {
-        return false;
-    }
-
-    @Override
-    public String getLaunchTarget() {
-        return "net.minecraft.server.MinecraftServer";
-    }
-}
diff --git a/src/java/com/irtimaled/bbor/launch/Tweaker.java b/src/java/com/irtimaled/bbor/launch/Tweaker.java
deleted file mode 100644 (file)
index 2b8e67a..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.irtimaled.bbor.launch;
-
-import net.minecraft.launchwrapper.ITweaker;
-import net.minecraft.launchwrapper.LaunchClassLoader;
-import org.spongepowered.asm.launch.MixinBootstrap;
-import org.spongepowered.asm.mixin.MixinEnvironment;
-import org.spongepowered.asm.mixin.Mixins;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class Tweaker implements ITweaker {
-    public List<String> args;
-
-    @Override
-    public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
-        this.args = new ArrayList<>(args);
-        addArg("--version", profile);
-        addOptions(args, gameDir, assetsDir, profile);
-    }
-
-    protected void addArg(String name, String value) {
-        args.add(name);
-        if (value != null) {
-            args.add(value);
-        }
-    }
-
-    protected void addOptions(List<String> args, File gameDir, File assetsDir, String profile) {
-    }
-
-    @Override
-    public void injectIntoClassLoader(LaunchClassLoader classLoader) {
-        // Use the Launch classLoader to load the RiftLoader class. Otherwise identical
-        // classes may not be equal, and 'instanceof' may return false when it should be true.
-        /*try {
-            Class<?> clazz = Launch.classLoader.findClass("org.dimdev.riftloader.RiftLoader");
-            clazz.getMethod("load", boolean.class).invoke(clazz.getField("instance").get(null), isClient());
-        } catch (ReflectiveOperationException e) {
-            throw new RuntimeException(e);
-        }
-*/
-        MixinBootstrap.init();
-        Mixins.addConfiguration("mixins.bbor.json");
-        MixinEnvironment.getDefaultEnvironment().setSide(isClient() ? MixinEnvironment.Side.CLIENT : MixinEnvironment.Side.SERVER);
-
-    }
-
-    protected abstract boolean isClient();
-
-    @Override
-    public String[] getLaunchArguments() {
-        return args.toArray(new String[0]);
-    }
-}
diff --git a/src/java/com/irtimaled/bbor/mixin/client/MixinMinecraft.java b/src/java/com/irtimaled/bbor/mixin/client/MixinMinecraft.java
deleted file mode 100644 (file)
index 38152b8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.irtimaled.bbor.mixin.client;
-
-import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
-import net.minecraft.client.Minecraft;
-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(Minecraft.class)
-public class MixinMinecraft {
-    @Inject(method = "init", at = @At("RETURN"))
-    private void init(CallbackInfo ci) {
-        BoundingBoxOutlineReloaded.init();
-    }
-
-    @Inject(method = "processKeyBinds", at = @At("HEAD"))
-    public void processKeyBinds(CallbackInfo ci) {
-        BoundingBoxOutlineReloaded.keyPressed();
-    }
-}
\ No newline at end of file
diff --git a/src/java/com/irtimaled/bbor/mixin/client/multiplayer/MixinWorldClient.java b/src/java/com/irtimaled/bbor/mixin/client/multiplayer/MixinWorldClient.java
deleted file mode 100644 (file)
index f52ad19..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.irtimaled.bbor.mixin.client.multiplayer;
-
-import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
-import net.minecraft.client.multiplayer.WorldClient;
-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 class MixinWorldClient {
-    @Inject(method="sendQuittingDisconnectingPacket", at=@At("RETURN"))
-    private void sendQuittingDisconnectingPacket(CallbackInfo ci)
-    {
-        BoundingBoxOutlineReloaded.playerDisconnectedFromServer();
-    }
-}
diff --git a/src/java/com/irtimaled/bbor/mixin/client/renderer/MixinEntityRenderer.java b/src/java/com/irtimaled/bbor/mixin/client/renderer/MixinEntityRenderer.java
deleted file mode 100644 (file)
index 44e5222..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.irtimaled.bbor.mixin.client.renderer;
-
-import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
-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 class MixinEntityRenderer {
-    @Inject(method = "updateCameraAndRender(FJ)V", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V", args = "ldc=hand", shift = At.Shift.BEFORE))
-    private void render(float partialTicks, long ignored, CallbackInfo ci) {
-        BoundingBoxOutlineReloaded.render(partialTicks);
-    }
-}
diff --git a/src/java/com/irtimaled/bbor/mixin/client/settings/MixinKeyBinding.java b/src/java/com/irtimaled/bbor/mixin/client/settings/MixinKeyBinding.java
deleted file mode 100644 (file)
index f9a4724..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.irtimaled.bbor.mixin.client.settings;
-
-import net.minecraft.client.settings.KeyBinding;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.Shadow;
-
-import java.util.Map;
-
-
-@Mixin(KeyBinding.class)
-public class MixinKeyBinding {
-    @Shadow
-    private static Map<String, Integer> CATEGORY_ORDER;
-
-    static {
-        CATEGORY_ORDER.put("Bounding Box Outline Reloaded", 0);
-    }
-}
\ No newline at end of file
diff --git a/src/java/com/irtimaled/bbor/mixin/network/MixinNetworkManager.java b/src/java/com/irtimaled/bbor/mixin/network/MixinNetworkManager.java
deleted file mode 100644 (file)
index 1dae203..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.irtimaled.bbor.mixin.network;
-
-import io.netty.util.concurrent.GenericFutureListener;
-import net.minecraft.network.NetworkManager;
-import net.minecraft.network.Packet;
-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 class MixinNetworkManager {
-    @Inject(method = "sendPacket(Lnet/minecraft/network/Packet;Lio/netty/util/concurrent/GenericFutureListener;)V", at= @At("RETURN"))
-    public void sendPacket(Packet<?> packetIn, GenericFutureListener<?> listener, CallbackInfo ci) {
-        if (packetIn instanceof net.minecraft.network.login.client.CPacketLoginStart) {
-            com.irtimaled.bbor.client.BoundingBoxOutlineReloaded.playerConnectedToServer((NetworkManager) (Object) this);
-        }
-    }
-
-}
diff --git a/src/java/com/irtimaled/bbor/mixin/server/MixinMinecraftServer.java b/src/java/com/irtimaled/bbor/mixin/server/MixinMinecraftServer.java
deleted file mode 100644 (file)
index 045396f..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.irtimaled.bbor.mixin.server;
-
-import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
-import net.minecraft.server.MinecraftServer;
-import net.minecraft.world.World;
-import net.minecraft.world.WorldServer;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.Shadow;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-
-@Mixin(MinecraftServer.class)
-public class MixinMinecraftServer {
-
-    @Shadow public WorldServer[] worlds;
-
-    @Inject(method = "initialWorldChunkLoad", at = @At("HEAD"))
-    private void initialWorldChunkLoad(CallbackInfo ci)
-    {
-        for(World world : worlds) {
-            BoundingBoxOutlineReloaded.worldLoaded(world);
-        }
-    }
-}
diff --git a/src/java/com/irtimaled/bbor/mixin/world/chunk/MixinChunk.java b/src/java/com/irtimaled/bbor/mixin/world/chunk/MixinChunk.java
deleted file mode 100644 (file)
index 82c0770..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.irtimaled.bbor.mixin.world.chunk;
-
-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 class MixinChunk {
-    @Inject(method = "onLoad", at = @At("RETURN"))
-    private void onLoad(CallbackInfo ci) {
-        BoundingBoxOutlineReloaded.chunkLoaded((Chunk) (Object) this);
-    }
-}
\ No newline at end of file
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/client/BoundingBoxOutlineReloaded.java b/src/main/java/com/irtimaled/bbor/client/BoundingBoxOutlineReloaded.java
new file mode 100644 (file)
index 0000000..48e51f0
--- /dev/null
@@ -0,0 +1,53 @@
+package com.irtimaled.bbor.client;
+
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.settings.KeyBinding;
+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.getInstance().gameDir, "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() {
+        if (ActiveHotKey.isPressed()) {
+            proxy.toggleActive();
+        } else if (OuterBoxOnlyHotKey.isPressed()) {
+            proxy.toggleOuterBoxOnly();
+        }
+    }
+
+    public static final String KeyCategory = "Bounding Box Outline Reloaded";
+    public static KeyBinding ActiveHotKey =  new KeyBinding("Toggle On/Off", 0x42, KeyCategory);
+    public static KeyBinding OuterBoxOnlyHotKey= new KeyBinding("Toggle Display Outer Box Only", 0x4f, KeyCategory);
+
+    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..b535a10
--- /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.dimension.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.getInstance();
+        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..6b26bc6
--- /dev/null
@@ -0,0 +1,79 @@
+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.entity.player.EntityPlayer;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.world.dimension.DimensionType;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+public class ClientProxy extends CommonProxy {
+    private boolean active;
+    private boolean outerBoxOnly;
+    private ClientRenderer renderer;
+    private int remoteUserCount = 0;
+
+    public void toggleActive() {
+        active = !active;
+        if (active)
+            PlayerData.setActiveY();
+    }
+
+    public void toggleOuterBoxOnly() {
+        outerBoxOnly = !outerBoxOnly;
+    }
+
+    @Override
+    public void init() {
+        ClientDimensionCache clientDimensionCache = new ClientDimensionCache();
+        renderer = new ClientRenderer(clientDimensionCache);
+        dimensionCache = clientDimensionCache;
+    }
+
+    public void render(float partialTicks) {
+        EntityPlayer entityPlayer = Minecraft.getInstance().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..61ba392
--- /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.dimension.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.getInstance().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..719fb18
--- /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.dimension.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.size()];
+        for (int index = 0; index < tagList.size(); 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..173007a
--- /dev/null
@@ -0,0 +1,22 @@
+package com.irtimaled.bbor.client.renderers;
+
+import com.irtimaled.bbor.client.PlayerData;
+import com.irtimaled.bbor.common.models.BoundingBoxSlimeChunk;
+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..88392e0
--- /dev/null
@@ -0,0 +1,143 @@
+package com.irtimaled.bbor.client.renderers;
+
+import com.irtimaled.bbor.client.PlayerData;
+import com.irtimaled.bbor.common.models.BoundingBoxVillage;
+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..96e07ac
--- /dev/null
@@ -0,0 +1,18 @@
+package com.irtimaled.bbor.client.renderers;
+
+import com.irtimaled.bbor.client.PlayerData;
+import com.irtimaled.bbor.common.models.BoundingBoxWorldSpawn;
+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..fc13839
--- /dev/null
@@ -0,0 +1,40 @@
+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 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..0021d43
--- /dev/null
@@ -0,0 +1,57 @@
+package com.irtimaled.bbor.common;
+
+import com.irtimaled.bbor.Logger;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraft.world.chunk.IChunkProvider;
+import net.minecraft.world.dimension.DimensionType;
+import net.minecraft.world.gen.ChunkProviderServer;
+
+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) {
+            dimensionCache.setWorldData(world.getSeed(), world.getWorldInfo().getSpawnX(), world.getWorldInfo().getSpawnZ());
+            DimensionType dimensionType = world.dimension.getType();
+            Logger.info("create world dimension: %s, %s (seed: %d)", dimensionType, world.getClass().toString(), world.getSeed());
+            DimensionProcessor boundingBoxCache = new DimensionProcessor(dimensionType);
+            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().dimension.getType();
+        BoundingBoxCache cache = dimensionCache.get(dimensionType);
+        if(cache instanceof DimensionProcessor) {
+            ((DimensionProcessor)cache).processChunk(chunk);
+        }
+    }
+
+    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..5ba7597
--- /dev/null
@@ -0,0 +1,40 @@
+package com.irtimaled.bbor.common;
+
+import com.irtimaled.bbor.common.models.WorldData;
+import net.minecraft.world.dimension.DimensionType;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class DimensionCache {
+    private final Map<DimensionType, BoundingBoxCache> map = new ConcurrentHashMap<>();
+    private WorldData worldData;
+
+    public BoundingBoxCache get(DimensionType dimensionType) {
+        return map.get(dimensionType);
+    }
+
+    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..91501e6
--- /dev/null
@@ -0,0 +1,75 @@
+package com.irtimaled.bbor.common;
+
+import com.irtimaled.bbor.Logger;
+import com.irtimaled.bbor.common.models.BoundingBox;
+import com.irtimaled.bbor.common.models.BoundingBoxStructure;
+import com.irtimaled.bbor.config.ConfigManager;
+import com.irtimaled.bbor.config.Setting;
+import net.minecraft.util.math.MutableBoundingBox;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraft.world.dimension.DimensionType;
+import net.minecraft.world.gen.feature.structure.StructurePiece;
+import net.minecraft.world.gen.feature.structure.StructureStart;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class DimensionProcessor extends BoundingBoxCache {
+    DimensionProcessor(DimensionType dimensionType) {
+        this.dimensionType = dimensionType;
+    }
+
+    private DimensionType dimensionType;
+
+    private boolean closed = false;
+
+    @Override
+    public void close() {
+        closed = true;
+        super.close();
+    }
+
+    private void addStructures(Setting drawStructure, StructureType structureType, Map<String, StructureStart> structureMap) {
+        if (!drawStructure.getBoolean()) return;
+
+        StructureStart structureStart = structureMap.get(structureType.getName());
+        if (structureStart == null) return;
+        Color color = structureType.getColor();
+        MutableBoundingBox bb = structureStart.getBoundingBox();
+        if (bb == null)
+            return;
+
+        BoundingBox boundingBox = BoundingBoxStructure.from(bb, color);
+        if (isCached(boundingBox)) return;
+
+        Set<BoundingBox> structureBoundingBoxes = new HashSet<>();
+        for (StructurePiece structureComponent : structureStart.getComponents()) {
+            structureBoundingBoxes.add(BoundingBoxStructure.from(structureComponent.getBoundingBox(), color));
+        }
+        addBoundingBoxes(boundingBox, structureBoundingBoxes);
+        Logger.info("[%s] new dimensionCache entries: %d", dimensionType, structureBoundingBoxes.size());
+    }
+
+    public synchronized void processChunk(Chunk chunk) {
+        if (closed) return;
+
+        Map<String, StructureStart> structureMap = chunk.getStructureStarts();
+        if (structureMap.size() > 0) {
+            addStructures(ConfigManager.drawDesertTemples, StructureType.DesertTemple, structureMap);
+            addStructures(ConfigManager.drawJungleTemples, StructureType.JungleTemple, structureMap);
+            addStructures(ConfigManager.drawWitchHuts, StructureType.WitchHut, structureMap);
+            addStructures(ConfigManager.drawOceanMonuments, StructureType.OceanMonument, structureMap);
+            addStructures(ConfigManager.drawStrongholds, StructureType.Stronghold, structureMap);
+            addStructures(ConfigManager.drawMansions, StructureType.Mansion, structureMap);
+            addStructures(ConfigManager.drawMineShafts, StructureType.MineShaft, structureMap);
+            addStructures(ConfigManager.drawShipwrecks, StructureType.Shipwreck, structureMap);
+            addStructures(ConfigManager.drawOceanRuins, StructureType.OceanRuin, structureMap);
+            addStructures(ConfigManager.drawBuriedTreasure, StructureType.BuriedTreasure, structureMap);
+            addStructures(ConfigManager.drawIgloos, StructureType.Igloo, structureMap);
+            addStructures(ConfigManager.drawNetherFortresses, StructureType.NetherFortress, structureMap);
+            addStructures(ConfigManager.drawEndCities, StructureType.EndCity, structureMap);
+        }
+    }
+}
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..d28efff
--- /dev/null
@@ -0,0 +1,8 @@
+package com.irtimaled.bbor.common;
+
+import com.irtimaled.bbor.common.models.BoundingBox;
+import net.minecraft.world.dimension.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..54672ce
--- /dev/null
@@ -0,0 +1,35 @@
+package com.irtimaled.bbor.common;
+
+import java.awt.*;
+
+public class StructureType {
+    public final static StructureType JungleTemple = new StructureType(Color.GREEN, "Jungle_Pyramid");
+    public final static StructureType DesertTemple = new StructureType(Color.ORANGE, "Desert_Pyramid");
+    public final static StructureType WitchHut = new StructureType(Color.BLUE, "Swamp_Hut");
+    public final static StructureType OceanMonument = new StructureType(Color.CYAN, "Monument");
+    public final static StructureType Shipwreck = new StructureType(Color.CYAN, "Shipwreck");
+    public final static StructureType OceanRuin = new StructureType(Color.CYAN, "Ocean_Ruin");
+    public final static StructureType BuriedTreasure = new StructureType(Color.CYAN, "Buried_Treasure");
+    public final static StructureType Stronghold = new StructureType(Color.YELLOW, "Stronghold");
+    public final static StructureType MineShaft = new StructureType(Color.LIGHT_GRAY, "Mineshaft");
+    public final static StructureType NetherFortress = new StructureType(Color.RED, "Fortress");
+    public final static StructureType EndCity = new StructureType(Color.MAGENTA, "EndCity");
+    public final static StructureType Mansion = new StructureType(new Color(139, 69, 19), "Mansion");
+    public final static StructureType Igloo = new StructureType(Color.WHITE, "Igloo");
+
+    private final Color color;
+    private String name;
+
+    private StructureType(Color color, String name) {
+        this.color = color;
+        this.name = name;
+    }
+
+    public Color getColor() {
+        return color;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
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..2bdbe6e
--- /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.World;
+import net.minecraft.world.dimension.DimensionType;
+
+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..50c53a0
--- /dev/null
@@ -0,0 +1,28 @@
+package com.irtimaled.bbor.common.models;
+
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.MutableBoundingBox;
+
+import java.awt.*;
+
+public class BoundingBoxStructure extends BoundingBox {
+    private BoundingBoxStructure(BlockPos minBlockPos, BlockPos maxBlockPos, Color color) {
+        super(minBlockPos, maxBlockPos, color);
+    }
+
+    public static BoundingBoxStructure from(MutableBoundingBox 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..44bfcfb
--- /dev/null
@@ -0,0 +1,146 @@
+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.HashSet;
+import java.util.List;
+import java.util.Set;
+
+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..a280d1d
--- /dev/null
@@ -0,0 +1,81 @@
+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 Setting drawShipwrecks;
+    public static Setting drawOceanRuins;
+    public static Setting drawBuriedTreasure;
+    public static Setting drawIgloos;
+
+    public static void loadConfig(File mcConfigDir) {
+        configDir = mcConfigDir;
+        configDir.mkdirs();
+        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)");
+        drawShipwrecks = SetupBooleanProperty(config, "features", "drawShipwrecks", false, "If set to true shipwrecks will be drawn. (default: false)");
+        drawOceanRuins = SetupBooleanProperty(config, "features", "drawOceanRuins", false, "If set to true ocean ruins will be drawn. (default: false)");
+        drawBuriedTreasure = SetupBooleanProperty(config, "features", "drawBuriedTreasures", false, "If set to true buried treasure will be drawn. (default: false)");
+        drawIgloos = SetupBooleanProperty(config, "features", "drawIgloos", false, "If set to true igloos will be drawn. (default: false)");
+        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/install/Main.java b/src/main/java/com/irtimaled/bbor/install/Main.java
new file mode 100644 (file)
index 0000000..3f49b1b
--- /dev/null
@@ -0,0 +1,100 @@
+package com.irtimaled.bbor.install;
+
+import javax.swing.*;
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+public class Main {
+    public static void main(String... args) throws Throwable {
+        try {
+            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+
+        try {
+            String osName = getOsName();
+            File minecraftFolder = getMinecraftFolder(osName);
+            File versionFolder = new File(minecraftFolder, "versions/@MC_VERSION@-BBOR-@VERSION@/");
+            versionFolder.mkdirs();
+
+            File versionJson = new File(versionFolder, "@MC_VERSION@-BBOR-@VERSION@.json");
+            Files.copy(Main.class.getResourceAsStream("/profile.json"), versionJson.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+            try {
+                File profilesJson = new File(minecraftFolder, "launcher_profiles.json");
+                if (profilesJson.exists()) { // TODO: use gson instead
+                    String identifier = "\"bbor-@MC_VERSION@\"";
+                    String contents = new String(Files.readAllBytes(profilesJson.toPath()));
+                    if (contents.contains(identifier)) {
+                        contents = contents.replaceAll(",\n *"+identifier+": \\{[^}]*},", ",");
+                        contents = contents.replaceAll(",?\n *"+identifier+": \\{[^}]*},?", "");
+                    }
+
+                    String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
+
+                    contents = contents.replace("\n  \"profiles\": {", "\n  \"profiles\": {\n" +
+                            "    "+identifier+": {\n" +
+                            "      \"name\": \"Bounding Box Outline Reloaded\",\n" +
+                            "      \"type\": \"custom\",\n" +
+                            "      \"created\": \""+date+"T00:00:00.000Z\",\n" +
+                            "      \"lastUsed\": \"2100-01-01T00:00:00.000Z\",\n" +
+                            "      \"lastVersionId\": \"@MC_VERSION@-BBOR-@VERSION@\"\n" +
+                            "    },");
+
+                    Files.write(profilesJson.toPath(), contents.getBytes());
+                }
+            } catch (Throwable t) {
+                t.printStackTrace();
+            }
+
+            // Copy rift jar to libraries
+            try {
+                String source = Main.class.getProtectionDomain().getCodeSource().getLocation().getPath();
+                if (source.startsWith("/") && osName.contains("win")) {
+                    source = source.substring(1);
+                }
+                File riftJar = new File(minecraftFolder, "libraries/com/irtimaled/bbor/@VERSION@/bbor-@VERSION@.jar");
+                riftJar.getParentFile().mkdirs();
+                Files.copy(Paths.get(source), riftJar.toPath(), StandardCopyOption.REPLACE_EXISTING);
+            } catch (Throwable t) {
+                t.printStackTrace();
+            }
+
+            JOptionPane.showMessageDialog(null,
+                    "Bounding Box Outline Reloaded @VERSION@ for\nMinecraft @MC_VERSION@ has been successfully installed!\n" +
+                            "\n" +
+                            "Re-open the Minecraft Launcher to see it in the dropdown.",
+                    "Bounding Box Outline Reloaded Installer", JOptionPane.INFORMATION_MESSAGE);
+        } catch (Throwable t) {
+            StringWriter w = new StringWriter();
+            t.printStackTrace(new PrintWriter(w));
+            JOptionPane.showMessageDialog(null,
+                    "An error occured while installing Bounding Box Outline Reloaded, please report this to the issue\n" +
+                            "tracker (https://github.com/irtimaled/BoundingBoxOutlineReloaded/issues):\n" +
+                            "\n" +
+                            w.toString().replace("\t", "    "), "Bounding Box Outline Reloaded Installer", JOptionPane.ERROR_MESSAGE);
+        }
+    }
+
+    private static File getMinecraftFolder(String osName) {
+        File minecraftFolder;
+        if (osName.contains("win")) {
+            minecraftFolder = new File(System.getenv("APPDATA") + "/.minecraft");
+        } else if (osName.contains("mac")) {
+            minecraftFolder = new File(System.getProperty("user.home") + "/Library/Application Support/minecraft");
+        } else {
+            minecraftFolder = new File(System.getProperty("user.home") + "/.minecraft");
+        }
+        return minecraftFolder;
+    }
+
+    private static String getOsName() {
+        return System.getProperty("os.name").toLowerCase(Locale.ROOT);
+    }
+
+}
diff --git a/src/main/java/com/irtimaled/bbor/launch/ClientTweaker.java b/src/main/java/com/irtimaled/bbor/launch/ClientTweaker.java
new file mode 100644 (file)
index 0000000..77eb7e0
--- /dev/null
@@ -0,0 +1,21 @@
+package com.irtimaled.bbor.launch;
+
+import java.io.File;
+import java.util.List;
+
+public class ClientTweaker extends Tweaker {
+    @Override
+    protected void addOptions(List<String> args, File gameDir, File assetsDir, String profile){
+        addArg("--assetsDir", assetsDir.getPath());
+    }
+
+    @Override
+    public String getLaunchTarget() {
+        return "net.minecraft.client.main.Main";
+    }
+
+    @Override
+    protected boolean isClient() {
+        return true;
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/launch/ServerTweaker.java b/src/main/java/com/irtimaled/bbor/launch/ServerTweaker.java
new file mode 100644 (file)
index 0000000..f214d0d
--- /dev/null
@@ -0,0 +1,13 @@
+package com.irtimaled.bbor.launch;
+
+public class ServerTweaker extends Tweaker {
+    @Override
+    protected boolean isClient() {
+        return false;
+    }
+
+    @Override
+    public String getLaunchTarget() {
+        return "net.minecraft.server.MinecraftServer";
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/launch/Tweaker.java b/src/main/java/com/irtimaled/bbor/launch/Tweaker.java
new file mode 100644 (file)
index 0000000..2b8e67a
--- /dev/null
@@ -0,0 +1,56 @@
+package com.irtimaled.bbor.launch;
+
+import net.minecraft.launchwrapper.ITweaker;
+import net.minecraft.launchwrapper.LaunchClassLoader;
+import org.spongepowered.asm.launch.MixinBootstrap;
+import org.spongepowered.asm.mixin.MixinEnvironment;
+import org.spongepowered.asm.mixin.Mixins;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class Tweaker implements ITweaker {
+    public List<String> args;
+
+    @Override
+    public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
+        this.args = new ArrayList<>(args);
+        addArg("--version", profile);
+        addOptions(args, gameDir, assetsDir, profile);
+    }
+
+    protected void addArg(String name, String value) {
+        args.add(name);
+        if (value != null) {
+            args.add(value);
+        }
+    }
+
+    protected void addOptions(List<String> args, File gameDir, File assetsDir, String profile) {
+    }
+
+    @Override
+    public void injectIntoClassLoader(LaunchClassLoader classLoader) {
+        // Use the Launch classLoader to load the RiftLoader class. Otherwise identical
+        // classes may not be equal, and 'instanceof' may return false when it should be true.
+        /*try {
+            Class<?> clazz = Launch.classLoader.findClass("org.dimdev.riftloader.RiftLoader");
+            clazz.getMethod("load", boolean.class).invoke(clazz.getField("instance").get(null), isClient());
+        } catch (ReflectiveOperationException e) {
+            throw new RuntimeException(e);
+        }
+*/
+        MixinBootstrap.init();
+        Mixins.addConfiguration("mixins.bbor.json");
+        MixinEnvironment.getDefaultEnvironment().setSide(isClient() ? MixinEnvironment.Side.CLIENT : MixinEnvironment.Side.SERVER);
+
+    }
+
+    protected abstract boolean isClient();
+
+    @Override
+    public String[] getLaunchArguments() {
+        return args.toArray(new String[0]);
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/mixin/client/MixinMinecraft.java b/src/main/java/com/irtimaled/bbor/mixin/client/MixinMinecraft.java
new file mode 100644 (file)
index 0000000..38152b8
--- /dev/null
@@ -0,0 +1,21 @@
+package com.irtimaled.bbor.mixin.client;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+import net.minecraft.client.Minecraft;
+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(Minecraft.class)
+public class MixinMinecraft {
+    @Inject(method = "init", at = @At("RETURN"))
+    private void init(CallbackInfo ci) {
+        BoundingBoxOutlineReloaded.init();
+    }
+
+    @Inject(method = "processKeyBinds", at = @At("HEAD"))
+    public void processKeyBinds(CallbackInfo ci) {
+        BoundingBoxOutlineReloaded.keyPressed();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/irtimaled/bbor/mixin/client/multiplayer/MixinWorldClient.java b/src/main/java/com/irtimaled/bbor/mixin/client/multiplayer/MixinWorldClient.java
new file mode 100644 (file)
index 0000000..f52ad19
--- /dev/null
@@ -0,0 +1,17 @@
+package com.irtimaled.bbor.mixin.client.multiplayer;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+import net.minecraft.client.multiplayer.WorldClient;
+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 class MixinWorldClient {
+    @Inject(method="sendQuittingDisconnectingPacket", at=@At("RETURN"))
+    private void sendQuittingDisconnectingPacket(CallbackInfo ci)
+    {
+        BoundingBoxOutlineReloaded.playerDisconnectedFromServer();
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/mixin/client/renderer/MixinEntityRenderer.java b/src/main/java/com/irtimaled/bbor/mixin/client/renderer/MixinEntityRenderer.java
new file mode 100644 (file)
index 0000000..44e5222
--- /dev/null
@@ -0,0 +1,16 @@
+package com.irtimaled.bbor.mixin.client.renderer;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+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 class MixinEntityRenderer {
+    @Inject(method = "updateCameraAndRender(FJ)V", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V", args = "ldc=hand", shift = At.Shift.BEFORE))
+    private void render(float partialTicks, long ignored, CallbackInfo ci) {
+        BoundingBoxOutlineReloaded.render(partialTicks);
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/mixin/client/settings/MixinGameSettings.java b/src/main/java/com/irtimaled/bbor/mixin/client/settings/MixinGameSettings.java
new file mode 100644 (file)
index 0000000..976b18e
--- /dev/null
@@ -0,0 +1,33 @@
+package com.irtimaled.bbor.mixin.client.settings;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+import net.minecraft.client.GameSettings;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.settings.KeyBinding;
+import org.apache.commons.lang3.ArrayUtils;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import java.io.File;
+
+@Mixin(GameSettings.class)
+public class MixinGameSettings {
+    @Shadow private KeyBinding[] keyBindings;
+
+    @Inject(method = "<init>()V", at = @At("RETURN"))
+    private void init(CallbackInfo ci) {
+        keyBindings = getKeysAll();
+    }
+
+    private KeyBinding[] getKeysAll() {
+        return ArrayUtils.addAll(keyBindings, BoundingBoxOutlineReloaded.ActiveHotKey, BoundingBoxOutlineReloaded.OuterBoxOnlyHotKey);
+    }
+
+    @Inject(method = "<init>(Lnet/minecraft/client/Minecraft;Ljava/io/File;)V", at = @At("RETURN"))
+    private void init(Minecraft minecraft, File file, CallbackInfo ci) {
+        keyBindings = getKeysAll();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/irtimaled/bbor/mixin/client/settings/MixinKeyBinding.java b/src/main/java/com/irtimaled/bbor/mixin/client/settings/MixinKeyBinding.java
new file mode 100644 (file)
index 0000000..eee20b2
--- /dev/null
@@ -0,0 +1,17 @@
+package com.irtimaled.bbor.mixin.client.settings;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+import net.minecraft.client.settings.KeyBinding;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+
+import java.util.Map;
+
+@Mixin(KeyBinding.class)
+public class MixinKeyBinding {
+    @Shadow private static Map<String, Integer> CATEGORY_ORDER;
+
+    static {
+        CATEGORY_ORDER.put(BoundingBoxOutlineReloaded.KeyCategory, 0);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/irtimaled/bbor/mixin/network/MixinNetworkManager.java b/src/main/java/com/irtimaled/bbor/mixin/network/MixinNetworkManager.java
new file mode 100644 (file)
index 0000000..1dae203
--- /dev/null
@@ -0,0 +1,20 @@
+package com.irtimaled.bbor.mixin.network;
+
+import io.netty.util.concurrent.GenericFutureListener;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.network.Packet;
+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 class MixinNetworkManager {
+    @Inject(method = "sendPacket(Lnet/minecraft/network/Packet;Lio/netty/util/concurrent/GenericFutureListener;)V", at= @At("RETURN"))
+    public void sendPacket(Packet<?> packetIn, GenericFutureListener<?> listener, CallbackInfo ci) {
+        if (packetIn instanceof net.minecraft.network.login.client.CPacketLoginStart) {
+            com.irtimaled.bbor.client.BoundingBoxOutlineReloaded.playerConnectedToServer((NetworkManager) (Object) this);
+        }
+    }
+
+}
diff --git a/src/main/java/com/irtimaled/bbor/mixin/server/MixinMinecraftServer.java b/src/main/java/com/irtimaled/bbor/mixin/server/MixinMinecraftServer.java
new file mode 100644 (file)
index 0000000..936a5fc
--- /dev/null
@@ -0,0 +1,24 @@
+package com.irtimaled.bbor.mixin.server;
+
+import com.irtimaled.bbor.client.BoundingBoxOutlineReloaded;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.world.World;
+import net.minecraft.world.WorldServer;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(MinecraftServer.class)
+public class MixinMinecraftServer {
+    @Shadow public WorldServer[] worlds;
+
+    @Inject(method = "initialWorldChunkLoad", at = @At("HEAD"))
+    private void initialWorldChunkLoad(CallbackInfo ci)
+    {
+        for(World world : worlds) {
+            BoundingBoxOutlineReloaded.worldLoaded(world);
+        }
+    }
+}
diff --git a/src/main/java/com/irtimaled/bbor/mixin/world/chunk/MixinChunk.java b/src/main/java/com/irtimaled/bbor/mixin/world/chunk/MixinChunk.java
new file mode 100644 (file)
index 0000000..82c0770
--- /dev/null
@@ -0,0 +1,16 @@
+package com.irtimaled.bbor.mixin.world.chunk;
+
+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 class MixinChunk {
+    @Inject(method = "onLoad", at = @At("RETURN"))
+    private void onLoad(CallbackInfo ci) {
+        BoundingBoxOutlineReloaded.chunkLoaded((Chunk) (Object) this);
+    }
+}
\ No newline at end of file
diff --git a/src/main/resources/mixins.bbor.json b/src/main/resources/mixins.bbor.json
new file mode 100644 (file)
index 0000000..65c188b
--- /dev/null
@@ -0,0 +1,20 @@
+{
+  "required": true,
+  "minVersion": "0.7.11",
+  "compatibilityLevel": "JAVA_8",
+  "target": "@env(DEFAULT)",
+  "package": "com.irtimaled.bbor.mixin",
+  "refmap": "mixins.bbor.refmap.json",
+  "mixins": [
+    "world.chunk.MixinChunk",
+    "network.MixinNetworkManager",
+    "server.MixinMinecraftServer"
+  ],
+  "client": [
+    "client.MixinMinecraft",
+    "client.renderer.MixinEntityRenderer",
+    "client.multiplayer.MixinWorldClient",
+    "client.settings.MixinKeyBinding",
+    "client.settings.MixinGameSettings"
+  ]
+}
diff --git a/src/main/resources/profile.json b/src/main/resources/profile.json
new file mode 100644 (file)
index 0000000..22460e4
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    "inheritsFrom": "${mcVersion}",
+    "id": "${mcVersion}-BBOR-${version}",
+    "jar": "${mcVersion}",
+    "time": "${formattedTime}",
+    "type": "release",
+    "arguments": {
+        "game": [
+            "--tweakClass",
+            "${tweakClass}"
+        ]
+    },
+    "mainClass": "net.minecraft.launchwrapper.Launch",
+    "libraries": [
+        {
+            "name": "com.irtimaled:bbor:${version}"
+        },
+        {
+            "name": "org.ow2.asm:asm:6.2",
+            "url": "http://repo1.maven.org/maven2/"
+        },
+        {
+            "name": "org.ow2.asm:asm-commons:6.2",
+            "url": "http://repo1.maven.org/maven2/"
+        },
+        {
+            "name": "net.minecraft:launchwrapper:1.12"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/resources/mixins.bbor.json b/src/resources/mixins.bbor.json
deleted file mode 100644 (file)
index 198e740..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "required": true,
-  "minVersion": "0.7.11",
-  "compatibilityLevel": "JAVA_8",
-  "target": "@env(DEFAULT)",
-  "package": "com.irtimaled.bbor.mixin",
-  "refmap": "mixins.bbor.refmap.json",
-  "mixins": [
-    "world.chunk.MixinChunk",
-    "network.MixinNetworkManager",
-    "server.MixinMinecraftServer"
-  ],
-  "client": [
-    "client.MixinMinecraft",
-    "client.renderer.MixinEntityRenderer",
-    "client.multiplayer.MixinWorldClient",
-    "client.settings.MixinKeyBinding"
-  ]
-}
diff --git a/src/resources/profile.json b/src/resources/profile.json
deleted file mode 100644 (file)
index 22460e4..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-    "inheritsFrom": "${mcVersion}",
-    "id": "${mcVersion}-BBOR-${version}",
-    "jar": "${mcVersion}",
-    "time": "${formattedTime}",
-    "type": "release",
-    "arguments": {
-        "game": [
-            "--tweakClass",
-            "${tweakClass}"
-        ]
-    },
-    "mainClass": "net.minecraft.launchwrapper.Launch",
-    "libraries": [
-        {
-            "name": "com.irtimaled:bbor:${version}"
-        },
-        {
-            "name": "org.ow2.asm:asm:6.2",
-            "url": "http://repo1.maven.org/maven2/"
-        },
-        {
-            "name": "org.ow2.asm:asm-commons:6.2",
-            "url": "http://repo1.maven.org/maven2/"
-        },
-        {
-            "name": "net.minecraft:launchwrapper:1.12"
-        }
-    ]
-}
\ No newline at end of file