diff --git a/src/main/java/appeng/client/gui/implementations/GuiController.java b/src/main/java/appeng/client/gui/implementations/GuiController.java new file mode 100644 index 00000000..c2f9d038 --- /dev/null +++ b/src/main/java/appeng/client/gui/implementations/GuiController.java @@ -0,0 +1,292 @@ +package appeng.client.gui.implementations; + +import java.util.List; + +import appeng.api.config.Settings; +import appeng.api.config.SortDir; +import appeng.api.config.SortOrder; +import appeng.api.config.ViewItems; +import appeng.api.networking.IGridHost; +import appeng.api.storage.data.IAEItemStack; +import appeng.client.gui.AEBaseGui; +import appeng.client.gui.widgets.GuiImgButton; +import appeng.client.gui.widgets.GuiScrollbar; +import appeng.client.gui.widgets.ISortSource; +import appeng.client.me.ItemRepo; +import appeng.client.me.SlotME; +import appeng.container.implementations.ContainerController; +import appeng.core.AEConfig; +import appeng.core.localization.GuiText; +import appeng.util.Platform; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +public class GuiController extends AEBaseGui implements ISortSource { + private final ItemRepo repo; + private final int rows = 4; + private GuiImgButton units; + private int tooltip = -1; + + public GuiController(final InventoryPlayer inventoryPlayer, final IGridHost te) { + super(new ContainerController(inventoryPlayer, te)); + final GuiScrollbar scrollbar = new GuiScrollbar(); + + this.setScrollBar(scrollbar); + this.repo = new ItemRepo(scrollbar, this); + this.ySize = 215; + this.xSize = 242; + this.repo.setRowSize(5); + } + + @Override + protected void actionPerformed(final GuiButton btn) { + super.actionPerformed(btn); + + final boolean backwards = Mouse.isButtonDown(1); + + if (btn == this.units) { + AEConfig.instance.nextPowerUnit(backwards); + this.units.set(AEConfig.instance.selectedPowerUnit()); + } + } + + @Override + public void initGui() { + super.initGui(); + + this.units = new GuiImgButton( + this.guiLeft - 18, + this.guiTop + 8, + Settings.POWER_UNITS, + AEConfig.instance.selectedPowerUnit() + ); + this.buttonList.add(this.units); + } + + @Override + public void drawScreen(final int mouseX, final int mouseY, final float btn) { + final int gx = (this.width - this.xSize) / 2; + final int gy = (this.height - this.ySize) / 2; + + this.tooltip = -1; + + int y = 0; + int x = 0; + for (int z = 0; z <= 4 * 5; z++) { + final int minX = gx + 14 + x * 31; + final int minY = gy + 41 + y * 18; + + if (minX < mouseX && minX + 28 > mouseX) { + if (minY < mouseY && minY + 20 > mouseY) { + this.tooltip = z; + break; + } + } + + x++; + + if (x > 4) { + y++; + x = 0; + } + } + + super.drawScreen(mouseX, mouseY, btn); + } + + @Override + public void + drawFG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + final ContainerController ns = (ContainerController) this.inventorySlots; + + this.fontRendererObj.drawString(GuiText.NetworkDetails.getLocal(), 8, 6, 4210752); + + this.fontRendererObj.drawString( + GuiText.StoredPower.getLocal() + ": " + + Platform.formatPowerLong(ns.getCurrentPower(), false), + 13, + 16, + 4210752 + ); + this.fontRendererObj.drawString( + GuiText.PowerUsageRate.getLocal() + ": " + + Platform.formatPowerLong(ns.getPowerUsage(), true), + 13, + 26, + 4210752 + ); + + final int sectionLength = 30; + + int x = 0; + int y = 0; + final int xo = 12; + final int yo = 42; + final int viewStart = 0; // myScrollBar.getCurrentScroll() * 5; + final int viewEnd = viewStart + 5 * 4; + + String toolTip = ""; + int toolPosX = 0; + int toolPosY = 0; + + for (int z = viewStart; z < Math.min(viewEnd, this.repo.size()); z++) { + final IAEItemStack refStack = this.repo.getReferenceItem(z); + if (refStack != null) { + GL11.glPushMatrix(); + GL11.glScaled(0.5, 0.5, 0.5); + + String str = Long.toString(refStack.getStackSize()); + if (refStack.getStackSize() >= 10000) { + str = Long.toString(refStack.getStackSize() / 1000) + 'k'; + } + + final int w = this.fontRendererObj.getStringWidth(str); + this.fontRendererObj.drawString( + str, + (int) ((x * sectionLength + xo + sectionLength - 19 - (w * 0.5)) * 2), + (y * 18 + yo + 6) * 2, + 4210752 + ); + + GL11.glPopMatrix(); + final int posX = x * sectionLength + xo + sectionLength - 18; + final int posY = y * 18 + yo; + + if (this.tooltip == z - viewStart) { + toolTip = Platform.getItemDisplayName(this.repo.getItem(z)); + + toolTip + += ('\n' + GuiText.Installed.getLocal() + ": " + + (refStack.getStackSize())); + if (refStack.getCountRequestable() > 0) { + toolTip + += ('\n' + GuiText.EnergyDrain.getLocal() + ": " + + Platform.formatPowerLong( + refStack.getCountRequestable(), true + )); + } + + toolPosX = x * sectionLength + xo + sectionLength - 8; + toolPosY = y * 18 + yo; + } + + this.drawItem(posX, posY, this.repo.getItem(z)); + + x++; + + if (x > 4) { + y++; + x = 0; + } + } + } + + if (this.tooltip >= 0 && toolTip.length() > 0) { + this.drawTooltip(toolPosX, toolPosY + 10, 0, toolTip); + } + } + + @Override + public void + drawBG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { + this.bindTexture("guis/controller.png"); + this.drawTexturedModalRect(offsetX, offsetY, 0, 0, this.xSize, this.ySize); + } + + public void postUpdate(final List list) { + this.repo.clear(); + + for (final IAEItemStack is : list) { + this.repo.postUpdate(is); + } + + this.repo.updateView(); + this.setScrollBar(); + } + + private void setScrollBar() { + final int size = this.repo.size(); + this.getScrollBar().setTop(39).setLeft(175).setHeight(78); + this.getScrollBar().setRange(0, (size + 4) / 5 - this.rows, 1); + } + + // @Override - NEI + public List handleItemTooltip( + final ItemStack stack, + final int mouseX, + final int mouseY, + final List currentToolTip + ) { + if (stack != null) { + final Slot s = this.getSlot(mouseX, mouseY); + if (s instanceof SlotME) { + IAEItemStack myStack = null; + + try { + final SlotME theSlotField = (SlotME) s; + myStack = theSlotField.getAEStack(); + } catch (final Throwable ignore) {} + + if (myStack != null) { + while (currentToolTip.size() > 1) { + currentToolTip.remove(1); + } + } + } + } + return currentToolTip; + } + + // Vanilla version... + protected void drawItemStackTooltip(final ItemStack stack, final int x, final int y) { + final Slot s = this.getSlot(x, y); + if (s instanceof SlotME && stack != null) { + IAEItemStack myStack = null; + + try { + final SlotME theSlotField = (SlotME) s; + myStack = theSlotField.getAEStack(); + } catch (final Throwable ignore) {} + + if (myStack != null) { + final List currentToolTip = stack.getTooltip( + this.mc.thePlayer, this.mc.gameSettings.advancedItemTooltips + ); + + while (currentToolTip.size() > 1) { + currentToolTip.remove(1); + } + + currentToolTip.add( + GuiText.Installed.getLocal() + ": " + (myStack.getStackSize()) + ); + currentToolTip.add( + GuiText.EnergyDrain.getLocal() + ": " + + Platform.formatPowerLong(myStack.getCountRequestable(), true) + ); + + this.drawTooltip(x, y, 0, join(currentToolTip, "\n")); + } + } + // super.drawItemStackTooltip( stack, x, y ); + } + + @Override + public Enum getSortBy() { + return SortOrder.NAME; + } + + @Override + public Enum getSortDir() { + return SortDir.ASCENDING; + } + + @Override + public Enum getSortDisplay() { + return ViewItems.ALL; + } +} diff --git a/src/main/java/appeng/container/implementations/ContainerController.java b/src/main/java/appeng/container/implementations/ContainerController.java new file mode 100644 index 00000000..90cb9025 --- /dev/null +++ b/src/main/java/appeng/container/implementations/ContainerController.java @@ -0,0 +1,243 @@ +package appeng.container.implementations; + +import java.io.IOException; + +import appeng.api.AEApi; +import appeng.api.features.ILocatable; +import appeng.api.features.INetworkEncodable; +import appeng.api.features.IWirelessTermHandler; +import appeng.api.networking.IGrid; +import appeng.api.networking.IGridBlock; +import appeng.api.networking.IGridHost; +import appeng.api.networking.IGridNode; +import appeng.api.networking.energy.IEnergyGrid; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.storage.data.IItemList; +import appeng.container.AEBaseContainer; +import appeng.container.guisync.GuiSync; +import appeng.container.slot.SlotOutput; +import appeng.container.slot.SlotPlayerHotBar; +import appeng.container.slot.SlotPlayerInv; +import appeng.container.slot.SlotRestrictedInput; +import appeng.core.sync.network.NetworkHandler; +import appeng.core.sync.packets.PacketMEInventoryUpdate; +import appeng.tile.inventory.AppEngInternalInventory; +import appeng.tile.inventory.IAEAppEngInventory; +import appeng.tile.inventory.InvOperation; +import appeng.util.Platform; +import appeng.util.item.AEItemStack; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.ICrafting; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.util.ForgeDirection; + +public class ContainerController extends AEBaseContainer implements IAEAppEngInventory { + @GuiSync(0) + public long avgAddition; + @GuiSync(1) + public long powerUsage; + @GuiSync(2) + public long currentPower; + @GuiSync(3) + public long maxPower; + private IGrid network; + private IGridHost host; + private int delay = 40; + private final AppEngInternalInventory wirelessEncoder = new AppEngInternalInventory(this, 2); + private final SlotRestrictedInput wirelessIn; + private final SlotOutput wirelessOut; + + public ContainerController(final InventoryPlayer ip, final IGridHost te) { + super(ip, null, null); + host = te; + + if (host != null) { + this.findNode(host, ForgeDirection.UNKNOWN); + for (final ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { + this.findNode(host, d); + } + } + + if (this.network == null && Platform.isServer()) { + this.setValidContainer(false); + } + + this.wirelessIn = new SlotRestrictedInput(SlotRestrictedInput.PlacableItemType.ENCODABLE_ITEM, this.wirelessEncoder, 0, 212, 10, ip); + this.wirelessOut = new SlotOutput(this.wirelessEncoder, 1, 212, 68, -1); + this.addSlotToContainer(wirelessIn); + this.addSlotToContainer(wirelessOut); + + this.bindPlayerInventory(ip); + } + + private void findNode(final IGridHost host, final ForgeDirection d) { + if (this.network == null) { + final IGridNode node = host.getGridNode(d); + if (node != null) { + this.network = node.getGrid(); + } + } + } + + @Override + public void detectAndSendChanges() { + this.delay++; + if (Platform.isServer() && this.delay > 15 && this.network != null) { + this.delay = 0; + + final IEnergyGrid eg = this.network.getCache(IEnergyGrid.class); + if (eg != null) { + this.setAverageAddition((long) (100.0 * eg.getAvgPowerInjection())); + this.setPowerUsage((long) (100.0 * eg.getAvgPowerUsage())); + this.setCurrentPower((long) (100.0 * eg.getStoredPower())); + this.setMaxPower((long) (100.0 * eg.getMaxStoredPower())); + } + + try { + final PacketMEInventoryUpdate piu = new PacketMEInventoryUpdate(); + + for (final Class machineClass : + this.network.getMachinesClasses()) { + final IItemList list + = AEApi.instance().storage().createItemList(); + for (final IGridNode machine : + this.network.getMachines(machineClass)) { + final IGridBlock blk = machine.getGridBlock(); + final ItemStack is = blk.getMachineRepresentation(); + if (is != null && is.getItem() != null) { + final IAEItemStack ais = AEItemStack.create(is); + ais.setStackSize(1); + ais.setCountRequestable((long + ) (blk.getIdlePowerUsage() * 100.0)); + list.add(ais); + } + } + + for (final IAEItemStack ais : list) { + piu.appendItem(ais); + } + } + + for (final Object c : this.crafters) { + if (c instanceof EntityPlayer) { + NetworkHandler.instance.sendTo(piu, (EntityPlayerMP) c); + } + } + } catch (final IOException e) { + // :P + } + } + super.detectAndSendChanges(); + } + + public long getCurrentPower() { + return this.currentPower; + } + + private void setCurrentPower(final long currentPower) { + this.currentPower = currentPower; + } + + public long getMaxPower() { + return this.maxPower; + } + + private void setMaxPower(final long maxPower) { + this.maxPower = maxPower; + } + + public long getAverageAddition() { + return this.avgAddition; + } + + private void setAverageAddition(final long avgAddition) { + this.avgAddition = avgAddition; + } + + public long getPowerUsage() { + return this.powerUsage; + } + + private void setPowerUsage(final long powerUsage) { + this.powerUsage = powerUsage; + } + + protected void bindPlayerInventory(final InventoryPlayer inventoryPlayer) { + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 9; ++j) { + this.addSlotToContainer(new SlotPlayerInv(inventoryPlayer, j + i * 9 + 9, 8 + j * 18, 113 + i * 18 + 20)); + } + } + for (int i = 0; i < 9; ++i) { + this.addSlotToContainer(new SlotPlayerHotBar(inventoryPlayer, i, 8 + i * 18, 191)); + } + } + + @Override + public void onContainerClosed(final EntityPlayer player) { + super.onContainerClosed(player); + + if (this.wirelessIn.getHasStack()) { + player.dropPlayerItemWithRandomChoice(this.wirelessIn.getStack(), false); + } + + if (this.wirelessOut.getHasStack()) { + player.dropPlayerItemWithRandomChoice(this.wirelessOut.getStack(), false); + } + } + + @Override + public void saveChanges() { + + } + + @Override + public void onChangeInventory( + final IInventory inv, + final int slot, + final InvOperation mc, + final ItemStack removedStack, + final ItemStack newStack + ) { + if (!this.wirelessOut.getHasStack() && this.wirelessIn.getHasStack() && this.host instanceof ILocatable) { + final ItemStack term = this.wirelessIn.getStack().copy(); + INetworkEncodable networkEncodable = null; + + if (term.getItem() instanceof INetworkEncodable) { + networkEncodable = (INetworkEncodable) term.getItem(); + } + + final IWirelessTermHandler wTermHandler + = AEApi.instance().registries().wireless().getWirelessTerminalHandler( + term + ); + if (wTermHandler != null) { + networkEncodable = wTermHandler; + } + + if (networkEncodable != null) { + networkEncodable.setEncryptionKey( + term, String.valueOf(((ILocatable)host).getLocatableSerial()), "" + ); + + this.wirelessIn.putStack(null); + this.wirelessOut.putStack(term); + + // update the two slots in question... + for (final Object crafter : this.crafters) { + final ICrafting icrafting = (ICrafting) crafter; + icrafting.sendSlotContents( + this, this.wirelessIn.slotNumber, this.wirelessIn.getStack() + ); + icrafting.sendSlotContents( + this, this.wirelessOut.slotNumber, this.wirelessOut.getStack() + ); + } + } + } + } + +} diff --git a/src/main/java/appeng/core/sync/GuiBridge.java b/src/main/java/appeng/core/sync/GuiBridge.java index b1cdd088..e2ef768e 100644 --- a/src/main/java/appeng/core/sync/GuiBridge.java +++ b/src/main/java/appeng/core/sync/GuiBridge.java @@ -126,7 +126,7 @@ public enum GuiBridge implements IGuiHandler { ), GUI_NETWORK_STATUS_BLOCK( - ContainerNetworkStatus.class, TileLegacyController.class, GuiHostType.WORLD, null + ContainerController.class, TileLegacyController.class, GuiHostType.WORLD, null ), GUI_CRAFTING_CPU( diff --git a/src/main/java/appeng/core/sync/packets/PacketMEInventoryUpdate.java b/src/main/java/appeng/core/sync/packets/PacketMEInventoryUpdate.java index 69f3e044..fc0ca6f9 100644 --- a/src/main/java/appeng/core/sync/packets/PacketMEInventoryUpdate.java +++ b/src/main/java/appeng/core/sync/packets/PacketMEInventoryUpdate.java @@ -29,6 +29,7 @@ import java.util.zip.GZIPOutputStream; import javax.annotation.Nullable; import appeng.api.storage.data.IAEItemStack; +import appeng.client.gui.implementations.GuiController; import appeng.client.gui.implementations.GuiCraftConfirm; import appeng.client.gui.implementations.GuiCraftingCPU; import appeng.client.gui.implementations.GuiMEMonitorable; @@ -150,6 +151,10 @@ public class PacketMEInventoryUpdate extends AppEngPacket { if (gs instanceof GuiNetworkStatus) { ((GuiNetworkStatus) gs).postUpdate(this.list); } + + if (gs instanceof GuiController) { + ((GuiController) gs).postUpdate(this.list); + } } @Nullable diff --git a/src/main/java/appeng/tile/legacy/TileLegacyController.java b/src/main/java/appeng/tile/legacy/TileLegacyController.java index 21bad806..eb0429f7 100644 --- a/src/main/java/appeng/tile/legacy/TileLegacyController.java +++ b/src/main/java/appeng/tile/legacy/TileLegacyController.java @@ -1,22 +1,49 @@ package appeng.tile.legacy; import appeng.api.config.Actionable; +import appeng.api.events.LocatableEventAnnounce; +import appeng.api.events.LocatableEventAnnounce.LocatableEvent; +import appeng.api.features.ILocatable; import appeng.me.GridAccessException; +import appeng.tile.TileEvent; +import appeng.tile.events.TileEventType; import appeng.tile.grid.AENetworkPowerTile; import appeng.tile.inventory.AppEngInternalInventory; import appeng.tile.inventory.InvOperation; +import appeng.util.Platform; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.ForgeDirection; -public class TileLegacyController extends AENetworkPowerTile { +public class TileLegacyController extends AENetworkPowerTile implements ILocatable { private static final IInventory NULL_INVENTORY = new AppEngInternalInventory(null, 0); private static final int[] ACCESSIBLE_SLOTS_BY_SIDE = {}; - + private static int difference = 0; + private int ticksSinceRefresh = 0; + private long controllerKey; + public TileLegacyController() { //TODO Fix power storage this.setInternalMaxPower(10000); this.setInternalPublicPowerStorage(true); this.getProxy().setIdlePowerUsage(6.0); + difference++; + this.controllerKey = System.currentTimeMillis() * 10 + difference; + if (difference > 10) { + difference = 0; + } + } + + @TileEvent(TileEventType.TICK) + public void onTick() { + if (!this.worldObj.isRemote) { + ticksSinceRefresh++; + if (ticksSinceRefresh % 20 == 0) { + ticksSinceRefresh = 0; + updateMeta(); + } + } } @Override @@ -35,22 +62,27 @@ public class TileLegacyController extends AENetworkPowerTile { } @Override - protected double getFunnelPowerDemand(final double maxReceived) { - updateMeta(); - try { - return this.getProxy().getEnergy().getEnergyDemand(10000); - } catch (final GridAccessException e) { + protected double getFunnelPowerDemand( final double maxReceived ) + { + try + { + return this.getProxy().getEnergy().getEnergyDemand( 10000 ); + } + catch( final GridAccessException e ) + { // no grid? use local... return super.getFunnelPowerDemand(maxReceived); } } @Override - protected double funnelPowerIntoStorage(final double power, final Actionable mode) { - updateMeta(); - try { - final double ret = this.getProxy().getEnergy().injectPower(power, mode); - if (mode == Actionable.SIMULATE) { + protected double funnelPowerIntoStorage( final double power, final Actionable mode ) + { + try + { + final double ret = this.getProxy().getEnergy().injectPower( power, mode ); + if( mode == Actionable.SIMULATE ) + { return ret; } return 0; @@ -68,11 +100,57 @@ public class TileLegacyController extends AENetworkPowerTile { } else if (meta > 5) { meta = 5; } - if (getProxy().isActive() && getInternalCurrentPower() == 0.0) { + if (getProxy().isActive() && meta == 0) { meta = 6; + } else if (!getProxy().isActive()) { + meta = 0; } this.worldObj.setBlockMetadataWithNotify( this.xCoord, this.yCoord, this.zCoord, meta, 2 ); } + + @Override + public long getLocatableSerial() { + return controllerKey; + } + + @TileEvent(TileEventType.WORLD_NBT_WRITE) + public void writeNBT(final NBTTagCompound data) { + data.setLong("controllerKey", this.controllerKey); + } + + @TileEvent(TileEventType.WORLD_NBT_READ) + public void readNBT(final NBTTagCompound data) { + if (data.hasKey("controllerKey")) { + this.controllerKey = data.getLong("controllerKey"); + } + } + + @Override + public void onReady() { + super.onReady(); + if (Platform.isServer()) { + MinecraftForge.EVENT_BUS.post( + new LocatableEventAnnounce(this, LocatableEvent.Register) + ); + } + } + + @Override + public void invalidate() { + super.invalidate(); + MinecraftForge.EVENT_BUS.post( + new LocatableEventAnnounce(this, LocatableEvent.Unregister) + ); + } + + @Override + public void onChunkUnload() { + super.onChunkUnload(); + MinecraftForge.EVENT_BUS.post( + new LocatableEventAnnounce(this, LocatableEvent.Unregister) + ); + } + } diff --git a/src/main/resources/assets/appliedenergistics2/textures/guis/controller.png b/src/main/resources/assets/appliedenergistics2/textures/guis/controller.png new file mode 100644 index 00000000..4f032b34 Binary files /dev/null and b/src/main/resources/assets/appliedenergistics2/textures/guis/controller.png differ