package appeng.core.sync; import static appeng.core.sync.GuiHostType.ITEM; import static appeng.core.sync.GuiHostType.ITEM_OR_WORLD; import static appeng.core.sync.GuiHostType.WORLD; import java.lang.reflect.Constructor; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import appeng.api.AEApi; import appeng.api.config.SecurityPermissions; import appeng.api.exceptions.AppEngException; import appeng.api.features.IWirelessTermHandler; import appeng.api.implementations.IUpgradeableHost; import appeng.api.implementations.guiobjects.IGuiItem; import appeng.api.implementations.guiobjects.INetworkTool; import appeng.api.implementations.guiobjects.IPortableCell; import appeng.api.networking.IGrid; import appeng.api.networking.IGridNode; import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.security.IActionHost; import appeng.api.networking.security.ISecurityGrid; import appeng.api.parts.IPart; import appeng.api.parts.IPartHost; import appeng.api.storage.ITerminalHost; import appeng.client.gui.GuiNull; import appeng.container.AEBaseContainer; import appeng.container.ContainerNull; import appeng.container.ContainerOpenContext; import appeng.container.implementations.ContainerCellWorkbench; import appeng.container.implementations.ContainerChest; import appeng.container.implementations.ContainerCondenser; import appeng.container.implementations.ContainerCraftAmount; import appeng.container.implementations.ContainerCraftingTerm; import appeng.container.implementations.ContainerDrive; import appeng.container.implementations.ContainerFormationPlane; import appeng.container.implementations.ContainerGrinder; import appeng.container.implementations.ContainerIOPort; import appeng.container.implementations.ContainerInscriber; import appeng.container.implementations.ContainerInterface; import appeng.container.implementations.ContainerLevelEmitter; import appeng.container.implementations.ContainerMAC; import appeng.container.implementations.ContainerMEMonitorable; import appeng.container.implementations.ContainerMEPortableCell; import appeng.container.implementations.ContainerNetworkStatus; import appeng.container.implementations.ContainerNetworkTool; import appeng.container.implementations.ContainerPatternTerm; import appeng.container.implementations.ContainerPriority; import appeng.container.implementations.ContainerQNB; import appeng.container.implementations.ContainerQuartzKnife; import appeng.container.implementations.ContainerSecurity; import appeng.container.implementations.ContainerSkyChest; import appeng.container.implementations.ContainerSpatialIOPort; import appeng.container.implementations.ContainerStorageBus; import appeng.container.implementations.ContainerUpgradeable; import appeng.container.implementations.ContainerVibrationChamber; import appeng.container.implementations.ContainerWireless; import appeng.container.implementations.ContainerWirelessTerm; import appeng.helpers.IInterfaceHost; import appeng.helpers.IPriorityHost; import appeng.helpers.WirelessTerminalGuiObject; import appeng.items.contents.QuartzKnifeObj; import appeng.parts.automation.PartFormationPlane; import appeng.parts.automation.PartLevelEmitter; import appeng.parts.misc.PartStorageBus; import appeng.parts.reporting.PartCraftingTerminal; import appeng.parts.reporting.PartPatternTerminal; import appeng.server.AccessType; import appeng.tile.crafting.TileMolecularAssembler; import appeng.tile.grindstone.TileGrinder; import appeng.tile.misc.TileCellWorkbench; import appeng.tile.misc.TileCondenser; import appeng.tile.misc.TileInscriber; import appeng.tile.misc.TileSecurity; import appeng.tile.misc.TileVibrationChamber; import appeng.tile.networking.TileWireless; import appeng.tile.qnb.TileQuantumBridge; import appeng.tile.spatial.TileSpatialIOPort; import appeng.tile.storage.TileChest; import appeng.tile.storage.TileDrive; import appeng.tile.storage.TileIOPort; import appeng.tile.storage.TileSkyChest; import appeng.util.Platform; import cpw.mods.fml.common.network.IGuiHandler; import cpw.mods.fml.relauncher.ReflectionHelper; public enum GuiBridge implements IGuiHandler { GUI_Handler(), GUI_GRINDER(ContainerGrinder.class, TileGrinder.class, WORLD, null), GUI_QNB(ContainerQNB.class, TileQuantumBridge.class, WORLD, SecurityPermissions.BUILD), GUI_SKYCHEST(ContainerSkyChest.class, TileSkyChest.class, WORLD, null), GUI_CHEST(ContainerChest.class, TileChest.class, WORLD, SecurityPermissions.BUILD), GUI_WIRELESS(ContainerWireless.class, TileWireless.class, WORLD, SecurityPermissions.BUILD), GUI_ME(ContainerMEMonitorable.class, ITerminalHost.class, WORLD, null), GUI_PORTABLE_CELL(ContainerMEPortableCell.class, IPortableCell.class, ITEM, null), GUI_WIRELESS_TERM(ContainerWirelessTerm.class, WirelessTerminalGuiObject.class, ITEM, null), GUI_NETWORK_STATUS(ContainerNetworkStatus.class, INetworkTool.class, ITEM, null), GUI_NETWORK_TOOL(ContainerNetworkTool.class, INetworkTool.class, ITEM, null), GUI_QUARTZ_KNIFE(ContainerQuartzKnife.class, QuartzKnifeObj.class, ITEM, null), GUI_DRIVE(ContainerDrive.class, TileDrive.class, WORLD, SecurityPermissions.BUILD), GUI_VIBRATIONCHAMBER(ContainerVibrationChamber.class, TileVibrationChamber.class, WORLD, null), GUI_CONDENSER(ContainerCondenser.class, TileCondenser.class, WORLD, null), GUI_INTERFACE(ContainerInterface.class, IInterfaceHost.class, WORLD, SecurityPermissions.BUILD), GUI_BUS(ContainerUpgradeable.class, IUpgradeableHost.class, WORLD, SecurityPermissions.BUILD), GUI_IOPORT(ContainerIOPort.class, TileIOPort.class, WORLD, SecurityPermissions.BUILD), GUI_STORAGEBUS(ContainerStorageBus.class, PartStorageBus.class, WORLD, SecurityPermissions.BUILD), GUI_FPLANE(ContainerFormationPlane.class, PartFormationPlane.class, WORLD, SecurityPermissions.BUILD), GUI_PRIORITY(ContainerPriority.class, IPriorityHost.class, WORLD, SecurityPermissions.BUILD), GUI_SECURITY(ContainerSecurity.class, TileSecurity.class, WORLD, SecurityPermissions.SECURITY), GUI_CRAFTING_TERMINAL(ContainerCraftingTerm.class, PartCraftingTerminal.class, WORLD, SecurityPermissions.CRAFT), GUI_PATTERN_TERMINAL(ContainerPatternTerm.class, PartPatternTerminal.class, WORLD, SecurityPermissions.CRAFT), // extends (Container/Gui) + Bus GUI_LEVELEMITTER(ContainerLevelEmitter.class, PartLevelEmitter.class, WORLD, SecurityPermissions.BUILD), GUI_SPATIALIOPORT(ContainerSpatialIOPort.class, TileSpatialIOPort.class, WORLD, SecurityPermissions.BUILD), GUI_INSCRIBER(ContainerInscriber.class, TileInscriber.class, WORLD, null), GUI_CELLWORKBENCH(ContainerCellWorkbench.class, TileCellWorkbench.class, WORLD, null), GUI_MAC(ContainerMAC.class, TileMolecularAssembler.class, WORLD, null), GUI_CRAFTING_AMOUNT(ContainerCraftAmount.class, ITerminalHost.class, ITEM_OR_WORLD, SecurityPermissions.CRAFT); private Class Tile; private Class Gui; private Class Container; private GuiHostType type; private SecurityPermissions requiredPermission; private GuiBridge() { Tile = null; Gui = null; Container = null; } /** * I honestly wish I could just use the GuiClass Names myself, but I can't access them without MC's Server * Exploding. */ private void getGui() { if ( Platform.isClient() ) { String start = Container.getName(); String GuiClass = start.replaceFirst( "container.", "client.gui." ).replace( ".Container", ".Gui" ); if ( start.equals( GuiClass ) ) throw new RuntimeException( "Unable to find gui class" ); Gui = ReflectionHelper.getClass( this.getClass().getClassLoader(), GuiClass ); if ( Gui == null ) throw new RuntimeException( "Cannot Load class: " + GuiClass ); } } private GuiBridge(Class _Container, SecurityPermissions requiredPermission) { this.requiredPermission = requiredPermission; Container = _Container; Tile = null; getGui(); } private GuiBridge(Class _Container, Class _Tile, GuiHostType type, SecurityPermissions requiredPermission) { this.requiredPermission = requiredPermission; Container = _Container; this.type = type; Tile = _Tile; getGui(); } public boolean CorrectTileOrPart(Object tE) { if ( Tile == null ) throw new RuntimeException( "This Gui Cannot use the standard Handler." ); return Tile.isInstance( tE ); } public Object ConstructContainer(InventoryPlayer inventory, ForgeDirection side, Object tE) { try { Constructor[] c = Container.getConstructors(); if ( c.length == 0 ) throw new AppEngException( "Invalid Gui Class" ); Constructor target = findConstructor( c, inventory, tE ); if ( target == null ) { throw new RuntimeException( "Cannot find " + Container.getName() + "( " + typeName( inventory ) + ", " + typeName( tE ) + " )" ); } return target.newInstance( inventory, tE ); } catch (Throwable t) { throw new RuntimeException( t ); } } public Object ConstructGui(InventoryPlayer inventory, ForgeDirection side, Object tE) { try { Constructor[] c = Gui.getConstructors(); if ( c.length == 0 ) throw new AppEngException( "Invalid Gui Class" ); Constructor target = findConstructor( c, inventory, tE ); if ( target == null ) { throw new RuntimeException( "Cannot find " + Container.getName() + "( " + typeName( inventory ) + ", " + typeName( tE ) + " )" ); } return target.newInstance( inventory, tE ); } catch (Throwable t) { throw new RuntimeException( t ); } } private String typeName(Object inventory) { if ( inventory == null ) return "NULL"; return inventory.getClass().getName(); } private Constructor findConstructor(Constructor[] c, InventoryPlayer inventory, Object tE) { for (Constructor con : c) { Class[] types = con.getParameterTypes(); if ( types.length == 2 ) { if ( types[0].isAssignableFrom( inventory.getClass() ) && types[1].isAssignableFrom( tE.getClass() ) ) return con; } } return null; } private Object updateGui(Object newContainer, World w, int x, int y, int z, ForgeDirection side) { if ( newContainer instanceof AEBaseContainer ) { AEBaseContainer bc = (AEBaseContainer) newContainer; bc.openContext = new ContainerOpenContext(); bc.openContext.w = w; bc.openContext.x = x; bc.openContext.y = y; bc.openContext.z = z; bc.openContext.side = side; } return newContainer; } @Override public Object getServerGuiElement(int ID_ORDINAL, EntityPlayer player, World w, int x, int y, int z) { ForgeDirection side = ForgeDirection.getOrientation( ID_ORDINAL & 0x07 ); GuiBridge ID = values()[ID_ORDINAL >> 3]; if ( ID.type.isItem() ) { ItemStack it = player.inventory.getCurrentItem(); Object myItem = getGuiObject( it, player, w, x, y, z ); if ( myItem != null && ID.CorrectTileOrPart( myItem ) ) return updateGui( ID.ConstructContainer( player.inventory, side, myItem ), w, x, y, z, side ); } if ( ID.type.isTile() ) { TileEntity TE = w.getTileEntity( x, y, z ); if ( TE instanceof IPartHost ) { ((IPartHost) TE).getPart( side ); IPart part = ((IPartHost) TE).getPart( side ); if ( ID.CorrectTileOrPart( part ) ) return updateGui( ID.ConstructContainer( player.inventory, side, part ), w, x, y, z, side ); } else { if ( ID.CorrectTileOrPart( TE ) ) return updateGui( ID.ConstructContainer( player.inventory, side, TE ), w, x, y, z, side ); } } return new ContainerNull(); } private Object getGuiObject(ItemStack it, EntityPlayer player, World w, int x, int y, int z) { if ( it != null ) { if ( it.getItem() instanceof IGuiItem ) { return ((IGuiItem) it.getItem()).getGuiObject( it, w, x, y, z ); } IWirelessTermHandler wh = AEApi.instance().registries().wireless().getWirelessTerminalHandler( it ); if ( wh != null ) return new WirelessTerminalGuiObject( wh, it, player, w, x, y, z ); } return null; } @Override public Object getClientGuiElement(int ID_ORDINAL, EntityPlayer player, World w, int x, int y, int z) { ForgeDirection side = ForgeDirection.getOrientation( ID_ORDINAL & 0x07 ); GuiBridge ID = values()[ID_ORDINAL >> 3]; if ( ID.type.isItem() ) { ItemStack it = player.inventory.getCurrentItem(); Object myItem = getGuiObject( it, player, w, x, y, z ); if ( ID.CorrectTileOrPart( myItem ) ) return ID.ConstructGui( player.inventory, side, myItem ); } if ( ID.type.isTile() ) { TileEntity TE = w.getTileEntity( x, y, z ); if ( TE instanceof IPartHost ) { ((IPartHost) TE).getPart( side ); IPart part = ((IPartHost) TE).getPart( side ); if ( ID.CorrectTileOrPart( part ) ) return ID.ConstructGui( player.inventory, side, part ); } else { if ( ID.CorrectTileOrPart( TE ) ) return ID.ConstructGui( player.inventory, side, TE ); } } return new GuiNull( new ContainerNull() ); } public boolean hasPermissions(TileEntity te, int x, int y, int z, ForgeDirection side, EntityPlayer player) { World w = player.getEntityWorld(); if ( Platform.hasPermissions( x, y, z, player, AccessType.BLOCK_ACCESS ) ) { if ( type.isItem() ) { ItemStack it = player.inventory.getCurrentItem(); if ( it != null && it.getItem() instanceof IGuiItem ) { Object myItem = ((IGuiItem) it.getItem()).getGuiObject( it, w, x, y, z ); if ( CorrectTileOrPart( myItem ) ) { return true; } } } if ( type.isTile() ) { TileEntity TE = w.getTileEntity( x, y, z ); if ( TE instanceof IPartHost ) { ((IPartHost) TE).getPart( side ); IPart part = ((IPartHost) TE).getPart( side ); if ( CorrectTileOrPart( part ) ) return securityCheck( part, player ); } else { if ( CorrectTileOrPart( TE ) ) return securityCheck( TE, player ); } } } return false; } private boolean securityCheck(Object te, EntityPlayer player) { if ( te instanceof IActionHost && requiredPermission != null ) { boolean requirePower = false; IGridNode gn = ((IActionHost) te).getActionableNode(); if ( gn != null ) { IGrid g = gn.getGrid(); if ( g != null ) { if ( requirePower ) { IEnergyGrid eg = g.getCache( IEnergyGrid.class ); if ( !eg.isNetworkPowered() ) { return false; } } ISecurityGrid sg = g.getCache( ISecurityGrid.class ); if ( sg.hasPermission( player, requiredPermission ) ) return true; } } return false; } return true; } public GuiHostType getType() { return type; } }