package shedar.mods.ic2.nuclearcontrol.panel; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Facing; import net.minecraft.world.World; import shedar.mods.ic2.nuclearcontrol.IC2NuclearControl; import shedar.mods.ic2.nuclearcontrol.IScreenPart; import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityAdvancedInfoPanel; import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityAdvancedInfoPanelExtender; import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityInfoPanel; import shedar.mods.ic2.nuclearcontrol.tileentities.TileEntityInfoPanelExtender; import cpw.mods.fml.common.FMLCommonHandler; public class ScreenManager { private final Map<Integer, List<Screen>> screens; private final Map<Integer, List<TileEntityInfoPanel>> unusedPanels; public ScreenManager() { screens = new HashMap<Integer, List<Screen>>(); unusedPanels = new HashMap<Integer, List<TileEntityInfoPanel>>(); } private int getWorldKey(World world) { if (world == null) return -10; if (world.getWorldInfo() == null) return -10; if (world.getWorldInfo().getVanillaDimension() == 0 && world.provider != null) { return world.provider.dimensionId; } else { return world.getWorldInfo().getVanillaDimension(); } } private boolean isValidExtender(World world, int x, int y, int z, int facing, boolean advanced) { if (world.getBlock(x, y, z) != IC2NuclearControl.blockNuclearControlMain) return false; TileEntity tileEntity = world.getTileEntity(x, y, z); if (!(tileEntity instanceof TileEntityInfoPanelExtender)) return false; if (advanced ^ (tileEntity instanceof TileEntityAdvancedInfoPanelExtender)) return false; if (((TileEntityInfoPanelExtender) tileEntity).facing != facing) return false; if (((IScreenPart) tileEntity).getScreen() != null) return false; return true; } private void updateScreenBound(Screen screen, int dx, int dy, int dz, World world, boolean advanced) { if (dx == 0 && dy == 0 && dz == 0) return; boolean isMin = dx + dy + dz < 0; int dir = isMin ? 1 : -1; int steps = 0; while (steps < 20) { int x, rx; int y, ry; int z, rz; if (isMin) { x = screen.minX + dx; y = screen.minY + dy; z = screen.minZ + dz; } else { x = screen.maxX + dx; y = screen.maxY + dy; z = screen.maxZ + dz; } rx = dx != 0 ? 0 : (screen.maxX - screen.minX); ry = dy != 0 ? 0 : (screen.maxY - screen.minY); rz = dz != 0 ? 0 : (screen.maxZ - screen.minZ); boolean allOk = true; for (int interX = 0; interX <= rx && allOk; interX++) { for (int interY = 0; interY <= ry && allOk; interY++) { for (int interZ = 0; interZ <= rz && allOk; interZ++) { TileEntityInfoPanel core = screen.getCore(world); allOk = core != null && isValidExtender(world, x + dir * interX, y + dir * interY, z + dir * interZ, core.facing, advanced); } } } if (!allOk) break; if (isMin) { screen.minX += dx; screen.minY += dy; screen.minZ += dz; } else { screen.maxX += dx; screen.maxY += dy; screen.maxZ += dz; } steps++; } } public Screen loadScreen(TileEntityInfoPanel panel) { if (panel.screenData != null) { NBTTagCompound tag = panel.screenData; Screen screen = new Screen(); screen.minX = tag.getInteger("minX"); screen.minY = tag.getInteger("minY"); screen.minZ = tag.getInteger("minZ"); screen.maxX = tag.getInteger("maxX"); screen.maxY = tag.getInteger("maxY"); screen.maxZ = tag.getInteger("maxZ"); screen.setCore(panel); if (FMLCommonHandler.instance().getEffectiveSide().isServer()) { Integer key = getWorldKey(panel.getWorldObj()); if (!screens.containsKey(key)) screens.put(key, new ArrayList<Screen>()); if (!unusedPanels.containsKey(key)) unusedPanels.put(key, new ArrayList<TileEntityInfoPanel>()); if (!screens.get(key).contains(screen)) { screens.get(key).add(screen); } } return screen; } return null; } public Screen loadScreen(World world, int coreX, int coreY, int coreZ) { TileEntity core = world.getTileEntity(coreX, coreY, coreZ); if (core != null && core instanceof TileEntityInfoPanel) return loadScreen((TileEntityInfoPanel) core); return null; } private Screen tryBuildFromPanel(TileEntityInfoPanel panel) { boolean advanced = panel instanceof TileEntityAdvancedInfoPanel; Screen screen = new Screen(); screen.maxX = screen.minX = panel.xCoord; screen.maxY = screen.minY = panel.yCoord; screen.maxZ = screen.minZ = panel.zCoord; screen.setCore(panel); int dx = Facing.offsetsXForSide[panel.facing] != 0 ? 0 : -1; int dy = Facing.offsetsYForSide[panel.facing] != 0 ? 0 : -1; int dz = Facing.offsetsZForSide[panel.facing] != 0 ? 0 : -1; updateScreenBound(screen, dx, 0, 0, panel.getWorldObj(), advanced); updateScreenBound(screen, -dx, 0, 0, panel.getWorldObj(), advanced); updateScreenBound(screen, 0, dy, 0, panel.getWorldObj(), advanced); updateScreenBound(screen, 0, -dy, 0, panel.getWorldObj(), advanced); updateScreenBound(screen, 0, 0, dz, panel.getWorldObj(), advanced); updateScreenBound(screen, 0, 0, -dz, panel.getWorldObj(), advanced); screen.init(false, panel.getWorldObj()); panel.updateData(); return screen; } private void destroyScreen(Screen screen, World world) { screens.get(getWorldKey(world)).remove(screen); screen.destroy(false, world); } public void unregisterScreenPart(TileEntity part) { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) return; if (!screens.containsKey(getWorldKey(part.getWorldObj()))) return; if (!unusedPanels.containsKey(getWorldKey(part.getWorldObj()))) return; if (!(part instanceof IScreenPart)) return; IScreenPart screenPart = (IScreenPart) part; Screen screen = screenPart.getScreen(); if (screen == null) { if (part instanceof TileEntityInfoPanel && unusedPanels.get(getWorldKey(part.getWorldObj())) .contains(part)) unusedPanels.get(getWorldKey(part.getWorldObj())).remove(part); return; } TileEntityInfoPanel core = screen.getCore(part.getWorldObj()); destroyScreen(screen, part.getWorldObj()); boolean isCoreDestroyed = part instanceof TileEntityInfoPanel; if (!isCoreDestroyed && core != null) { Screen newScreen = tryBuildFromPanel(core); if (newScreen == null) unusedPanels.get(getWorldKey(core.getWorldObj())).add(core); else screens.get(getWorldKey(core.getWorldObj())).add(newScreen); } } public void registerInfoPanel(TileEntityInfoPanel panel) { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) return; if (!screens.containsKey(getWorldKey(panel.getWorldObj()))) screens.put(getWorldKey(panel.getWorldObj()), new ArrayList<Screen>()); if (!unusedPanels.containsKey(getWorldKey(panel.getWorldObj()))) unusedPanels.put(getWorldKey(panel.getWorldObj()), new ArrayList<TileEntityInfoPanel>()); for (Screen screen : screens.get(getWorldKey(panel.getWorldObj()))) { if (screen.isBlockPartOf(panel)) { // occurs on chunk unloading/loading destroyScreen(screen, panel.getWorldObj()); break; } } Screen screen = tryBuildFromPanel(panel); if (screen != null) screens.get(getWorldKey(panel.getWorldObj())).add(screen); else unusedPanels.get(getWorldKey(panel.getWorldObj())).add(panel); } public void registerInfoPanelExtender(TileEntityInfoPanelExtender extender) { if (FMLCommonHandler.instance().getEffectiveSide().isClient()) return; if (!screens.containsKey(getWorldKey(extender.getWorldObj()))) screens.put(getWorldKey(extender.getWorldObj()), new ArrayList<Screen>()); if (!unusedPanels.containsKey(getWorldKey(extender.getWorldObj()))) unusedPanels.put(getWorldKey(extender.getWorldObj()), new ArrayList<TileEntityInfoPanel>()); List<TileEntityInfoPanel> rebuildPanels = new ArrayList<TileEntityInfoPanel>(); List<Screen> screensToDestroy = new ArrayList<Screen>(); for (Screen screen : screens.get(getWorldKey(extender.getWorldObj()))) { TileEntityInfoPanel core = screen.getCore(extender.getWorldObj()); if (screen.isBlockNearby(extender) && core != null && extender.facing == core.facing) { rebuildPanels.add(core); screensToDestroy.add(screen); } else if (screen.isBlockPartOf(extender)) { // block is already part of the screen // shouldn't be registered twice return; } } for (Screen screen : screensToDestroy) { destroyScreen(screen, extender.getWorldObj()); } for (TileEntityInfoPanel panel : unusedPanels.get(getWorldKey(extender.getWorldObj()))) { if (((panel.xCoord == extender.xCoord && panel.yCoord == extender.yCoord && (panel.zCoord == extender.zCoord + 1 || panel.zCoord == extender.zCoord - 1)) || (panel.xCoord == extender.xCoord && (panel.yCoord == extender.yCoord + 1 || panel.yCoord == extender.yCoord - 1) && panel.zCoord == extender.zCoord) || ((panel.xCoord == extender.xCoord + 1 || panel.xCoord == extender.xCoord - 1) && panel.yCoord == extender.yCoord && panel.zCoord == extender.zCoord)) && extender.facing == panel.facing) { rebuildPanels.add(panel); } } for (TileEntityInfoPanel panel : rebuildPanels) { Screen screen = tryBuildFromPanel(panel); if (screen != null) { screens.get(getWorldKey(extender.getWorldObj())).add(screen); if (unusedPanels.get(getWorldKey(extender.getWorldObj())) .contains(panel)) unusedPanels.get(getWorldKey(extender.getWorldObj())) .remove(panel); } else { if (!unusedPanels.get(getWorldKey(extender.getWorldObj())) .contains(panel)) unusedPanels.get(getWorldKey(extender.getWorldObj())).add( panel); } } } public void clearWorld(World world) { if (screens.containsKey(getWorldKey(world))) { screens.get(getWorldKey(world)).clear(); } } }