package hunternif.mc.atlas.ext; import hunternif.mc.atlas.AntiqueAtlasMod; import hunternif.mc.atlas.api.AtlasAPI; import hunternif.mc.atlas.util.Log; import hunternif.mc.atlas.util.MathUtil; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.world.World; import net.minecraft.world.gen.structure.MapGenStructureData; import net.minecraft.world.gen.structure.StructureBoundingBox; import net.minecraftforge.event.terraingen.PopulateChunkEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import java.util.HashSet; import java.util.Set; @SuppressWarnings("unused") public class NetherFortressWatcher { /** Set of tag names for every fortress, in the format "[x, y]" */ private final Set<String> visited = new HashSet<>(); // Corridors: private static final String ROOFED = "NeSCLT"; // Roofed corridor, solid wall down to the ground private static final String ROOFED2 = "NeSCR"; // Another roofed corridor? i guess private static final String ROOFED_STAIRS = "NeCCS"; // Roofed stairs, solid wall down to the ground private static final String ROOFED3 = "NeCTB"; // Really small roofed corridor private static final String ROOFED4 = "NeSC"; // ? Roofed? Covers most of the area of the Fortress. Solid wall down to the ground? // Crossings: private static final String BRIDGE_GATE = "NeRC"; // That room with no roof with gates facing each direction. One thick solid column going down to the ground. -done! private static final String ROOFED_CROSS = "NeSCSC"; // Roofed corridor? private static final String BRIDGE_CROSS = "NeBCr"; // A crossing of open bridges. No roof, no column. Takes up 19x19 area because of the beginnings of bridges starting off in different directions. - done! private static final String START = "NeStart"; // The same as "NeBCr" - done! // Bridges: private static final String BRIDGE = "NeBS"; // "19-block-long section of the bridge with columns, no roof. -done! private static final String BRIDGE_END = "NeBEF"; // The ruined end of a bridge - done! private static final String ENTRANCE = "NeCE"; // "Entrance", a very large room with an iron-barred gate. Contains a well of lava in the center. private static final String WART_STAIRS = "NeCSR"; // Room with the Nether Wart and a wide staircase leading to an open roof with a fence railing. private static final String THRONE = "NeMT"; // Blaze spawner. No roof. A decorative wall of fence ("the throne"?) private static final String TOWER = "NeSR"; // That room with tiny stairs going up to the roof along the wall -done! @SubscribeEvent(priority=EventPriority.LOWEST) public void onWorldLoad(WorldEvent.Load event) { if (!event.getWorld().isRemote && event.getWorld().provider.getDimension() == -1) { visitAllUnvisitedFortresses(event.getWorld()); } } @SubscribeEvent public void onPopulateChunk(PopulateChunkEvent.Post event) { if (!event.getWorld().isRemote && event.getWorld().provider.getDimension() == -1) { visitAllUnvisitedFortresses(event.getWorld()); } } public void visitAllUnvisitedFortresses(World world) { MapGenStructureData data = (MapGenStructureData)world.getPerWorldStorage().getOrLoadData(MapGenStructureData.class, "Fortress"); if (data == null) return; NBTTagCompound fortressNBTData = data.getTagCompound(); Set<String> tagSet = fortressNBTData.getKeySet(); for (String coords : tagSet) { if (!visited.contains(coords)) { NBTBase tag = fortressNBTData.getTag(coords); if (tag.getId() == 10) { // is NBTTagCompound visitFortress(world, (NBTTagCompound) tag); visited.add(coords); } } } } /** Put all child parts of the fortress on the map as global custom tiles. */ private void visitFortress(World world, NBTTagCompound tag) { int startChunkX = tag.getInteger("ChunkX"); int startChunkZ = tag.getInteger("ChunkZ"); Log.info("Visiting Nether Fortress in dimension #%d \"%s\" at chunk (%d, %d) ~ blocks (%d, %d)", world.provider.getDimension(), world.provider.getDimensionType().getName(), startChunkX, startChunkZ, startChunkX << 4, startChunkZ << 4); NBTTagList children = tag.getTagList("Children", 10); for (int i = 0; i < children.tagCount(); i++) { NBTTagCompound child = children.getCompoundTagAt(i); String childID = child.getString("id"); StructureBoundingBox boundingBox = new StructureBoundingBox(child.getIntArray("BB")); if (BRIDGE.equals(childID)) { // Straight open bridge segment. Is allowed to span several chunks. if (boundingBox.getXSize() > 16) { String tileName = ExtTileIdMap.TILE_NETHER_BRIDGE_X; int chunkZ = MathUtil.getCenter(boundingBox).getZ() >> 4; for (int x = boundingBox.minX; x < boundingBox.maxX; x += 16) { int chunkX = x >> 4; if (noTileAt(world, chunkX, chunkZ)) { AtlasAPI.tiles.putCustomGlobalTile(world, tileName, chunkX, chunkZ); } } } else {//if (boundingBox.getZSize() > 16) { String tileName = ExtTileIdMap.TILE_NETHER_BRIDGE_Z; int chunkX = MathUtil.getCenter(boundingBox).getX() >> 4; for (int z = boundingBox.minZ; z < boundingBox.maxZ; z += 16) { int chunkZ = z >> 4; if (noTileAt(world, chunkX, chunkZ)) { AtlasAPI.tiles.putCustomGlobalTile(world, tileName, chunkX, chunkZ); } } } } else if (BRIDGE_END.equals(childID)) { // End of a straight open bridge segment String tileName; int chunkX, chunkZ; if (boundingBox.getXSize() > boundingBox.getZSize()) { tileName = ExtTileIdMap.TILE_NETHER_BRIDGE_END_X; chunkX = boundingBox.minX >> 4; chunkZ = MathUtil.getCenter(boundingBox).getZ() >> 4; } else { tileName = ExtTileIdMap.TILE_NETHER_BRIDGE_END_Z; chunkX = MathUtil.getCenter(boundingBox).getX() >> 4; chunkZ = boundingBox.minZ >> 4; } if (noTileAt(world, chunkX, chunkZ)) { AtlasAPI.tiles.putCustomGlobalTile(world, tileName, chunkX, chunkZ); } } else { int chunkX = MathUtil.getCenter(boundingBox).getX() >> 4; int chunkZ = MathUtil.getCenter(boundingBox).getZ() >> 4; String tileName; if (BRIDGE_GATE.equals(childID)) { tileName = ExtTileIdMap.TILE_NETHER_BRIDGE_GATE; AtlasAPI.tiles.putCustomGlobalTile(world, tileName, chunkX, chunkZ); } else if (BRIDGE_CROSS.equals(childID) || START.equals(childID)) { tileName = ExtTileIdMap.TILE_NETHER_BRIDGE; AtlasAPI.tiles.putCustomGlobalTile(world, tileName, chunkX, chunkZ); } else if (TOWER.equals(childID)) { tileName = ExtTileIdMap.TILE_NETHER_TOWER; AtlasAPI.tiles.putCustomGlobalTile(world, tileName, chunkX, chunkZ); } else if (ENTRANCE.equals(childID)) { tileName = ExtTileIdMap.TILE_NETHER_HALL; AtlasAPI.tiles.putCustomGlobalTile(world, tileName, chunkX, chunkZ); } else if (WART_STAIRS.equals(childID)) { tileName = ExtTileIdMap.TILE_NETHER_FORT_STAIRS; AtlasAPI.tiles.putCustomGlobalTile(world, tileName, chunkX, chunkZ); } else if (THRONE.equals(childID)) { tileName = ExtTileIdMap.TILE_NETHER_THRONE; AtlasAPI.tiles.putCustomGlobalTile(world, tileName, chunkX, chunkZ); } else { tileName = ExtTileIdMap.TILE_NETHER_WALL; if (noTileAt(world, chunkX, chunkZ)) { AtlasAPI.tiles.putCustomGlobalTile(world, tileName, chunkX, chunkZ); } } } } } private static boolean noTileAt(World world, int chunkX, int chunkZ) { return AntiqueAtlasMod.extBiomeData.getData().getBiomeIdAt(world.provider.getDimension(), chunkX, chunkZ) == -1; } }