/* * This file is part of Applied Energistics 2. * Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved. * * Applied Energistics 2 is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Applied Energistics 2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Applied Energistics 2. If not, see . */ package appeng.parts.p2p; import appeng.api.AEApi; import appeng.api.config.*; import appeng.api.implementations.items.IMemoryCard; import appeng.api.implementations.items.MemoryCardMessages; import appeng.api.networking.events.MENetworkBootingStatusChange; import appeng.api.networking.events.MENetworkChannelsChanged; import appeng.api.networking.events.MENetworkEventSubscribe; import appeng.api.networking.events.MENetworkPowerStatusChange; import appeng.api.parts.IPart; import appeng.api.parts.IPartCollisionHelper; import appeng.api.parts.IPartItem; import appeng.api.parts.PartItemStack; import appeng.api.util.AECableType; import appeng.api.util.AEColor; import appeng.api.util.AEPartLocation; import appeng.core.AEConfig; import appeng.me.GridAccessException; import appeng.me.cache.P2PCache; import appeng.me.cache.helpers.TunnelCollection; import appeng.parts.PartBasicState; import appeng.util.Platform; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumHand; import net.minecraft.util.math.Vec3d; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; public abstract class PartP2PTunnel extends PartBasicState { private final TunnelCollection type = new TunnelCollection(null, this.getClass()); private boolean output; private short freq; public PartP2PTunnel(final ItemStack is) { super(is); } public TunnelCollection getCollection(final Collection collection, final Class c) { if (this.type.matches(c)) { this.type.setSource(collection); return this.type; } return null; } public TunnelCollection getInputs() throws GridAccessException { if (this.getProxy().isActive() && this.getFrequency() != 0) { return (TunnelCollection) this.getProxy().getP2P().getInputs(this.getFrequency(), this.getClass()); } return new TunnelCollection(new ArrayList(), this.getClass()); } public TunnelCollection getOutputs() throws GridAccessException { if (this.getProxy().isActive()) { return (TunnelCollection) this.getProxy().getP2P().getOutputs(this.getFrequency(), this.getClass()); } return new TunnelCollection(new ArrayList(), this.getClass()); } @Override public void getBoxes(final IPartCollisionHelper bch) { bch.addBox(5, 5, 12, 11, 11, 13); bch.addBox(3, 3, 13, 13, 13, 14); bch.addBox(2, 2, 14, 14, 14, 16); } @Override public void readFromNBT(final NBTTagCompound data) { super.readFromNBT(data); this.setOutput(data.getBoolean("output")); this.freq = data.getShort("freq"); } @Override public void writeToNBT(final NBTTagCompound data) { super.writeToNBT(data); data.setBoolean("output", this.isOutput()); data.setShort("freq", this.getFrequency()); } @Override public boolean readFromStream(ByteBuf data) throws IOException { final boolean c = super.readFromStream(data); final short oldf = this.freq; this.freq = data.readShort(); return c || oldf != this.freq; } @Override public void writeToStream(ByteBuf data) throws IOException { super.writeToStream(data); data.writeShort(this.getFrequency()); } @Override @MENetworkEventSubscribe public void chanRender(final MENetworkChannelsChanged c) { this.onTunnelNetworkChange(); super.chanRender(c); } @Override @MENetworkEventSubscribe public void powerRender(final MENetworkPowerStatusChange c) { this.onTunnelNetworkChange(); super.powerRender(c); } @Override @MENetworkEventSubscribe public void bootingRender(final MENetworkBootingStatusChange bs) { this.onTunnelNetworkChange(); super.bootingRender(bs); } @Override public float getCableConnectionLength(AECableType cable) { return 1; } @Override public boolean useStandardMemoryCard() { return false; } @Override public boolean onPartActivate(final EntityPlayer player, final EnumHand hand, final Vec3d pos) { if (Platform.isClient()) { return true; } if (hand == EnumHand.OFF_HAND) { return false; } boolean pasteAsOutput = true; ItemStack is = player.getHeldItem(hand); if (is.isEmpty()) { pasteAsOutput = false; is = player.getHeldItemOffhand(); } // UniqueIdentifier id = GameRegistry.findUniqueIdentifierFor( is.getItem() ); // AELog.info( "ID:" + id.toString() + " : " + is.getItemDamage() ); try { boolean hasPerms = this.getProxy().getSecurity().hasPermission(player, SecurityPermissions.BUILD); if (!hasPerms) { return false; } } catch (GridAccessException e) { return false; } final TunnelType tt = AEApi.instance().registries().p2pTunnel().getTunnelTypeByItem(is); if (!is.isEmpty() && is.getItem() instanceof IMemoryCard mc) { final NBTTagCompound data = mc.getData(is); final ItemStack newType = new ItemStack(data); final short freq = data.getShort("freq"); if (!newType.isEmpty()) { if (newType.getItem() instanceof IPartItem) { final IPart testPart = ((IPartItem) newType.getItem()).createPartFromItemStack(newType); if (testPart instanceof PartP2PTunnel) { try { this.getProxy().getP2P().removeTunnel(this, this.getFrequency()); } catch (GridAccessException e) { e.printStackTrace(); } this.getHost().removePart(this.getSide(), true); final AEPartLocation dir = this.getHost().addPart(newType, this.getSide(), player, hand); final IPart newBus = this.getHost().getPart(dir); if (newBus instanceof PartP2PTunnel newTunnel) { if (pasteAsOutput) { newTunnel.setOutput(true); } try { final P2PCache p2p = newTunnel.getProxy().getP2P(); p2p.updateFreq(newTunnel, freq); } catch (final GridAccessException e) { // :P } newTunnel.onTunnelNetworkChange(); } mc.notifyUser(player, MemoryCardMessages.SETTINGS_LOADED); return true; } } } mc.notifyUser(player, MemoryCardMessages.INVALID_MACHINE); } else if (tt != null) // attunement { final ItemStack newType = tt.getPartItemStack(); if (!newType.isEmpty() && !ItemStack.areItemsEqual(newType, this.getItemStack())) { final boolean oldOutput = this.isOutput(); final short myFreq = this.getFrequency(); try { this.getProxy().getP2P().removeTunnel(this, this.getFrequency()); } catch (GridAccessException e) { e.printStackTrace(); } this.getHost().removePart(this.getSide(), false); final AEPartLocation dir = this.getHost().addPart(newType, this.getSide(), player, hand); final IPart newBus = this.getHost().getPart(dir); if (newBus instanceof PartP2PTunnel newTunnel) { newTunnel.setOutput(oldOutput); try { final P2PCache p2p = newTunnel.getProxy().getP2P(); p2p.updateFreq(newTunnel, myFreq); } catch (final GridAccessException e) { // :P } newTunnel.onTunnelNetworkChange(); } return true; } } return false; } @Override public boolean onPartShiftActivate(final EntityPlayer player, final EnumHand hand, final Vec3d pos) { try { boolean hasPerms = this.getProxy().getSecurity().hasPermission(player, SecurityPermissions.BUILD); if (!hasPerms) { return false; } } catch (GridAccessException e) { return false; } final ItemStack is = player.inventory.getCurrentItem(); if (!is.isEmpty() && is.getItem() instanceof IMemoryCard mc) { if (Platform.isClient()) { return true; } final NBTTagCompound data = mc.getData(is); final short storedFrequency = data.getShort("freq"); short newFreq = this.getFrequency(); final boolean wasOutput = this.isOutput(); this.setOutput(false); final boolean needsNewFrequency = wasOutput || this.getFrequency() == 0 || storedFrequency == newFreq; try { if (needsNewFrequency) { newFreq = this.getProxy().getP2P().newFrequency(); final ItemStack newType = this.getHost().getPart(this.getSide()).getItemStack(PartItemStack.WRENCH); try { this.getProxy().getP2P().removeTunnel(this, this.getFrequency()); } catch (GridAccessException e) { e.printStackTrace(); } this.getHost().removePart(this.getSide(), false); final AEPartLocation dir = this.getHost().addPart(newType, this.getSide(), player, hand); final IPart newBus = this.getHost().getPart(dir); if (newBus instanceof PartP2PTunnel newTunnel) { newTunnel.setOutput(false); newTunnel.getProxy().getP2P().updateFreq(newTunnel, newFreq); newTunnel.onTunnelNetworkChange(); } } else { this.getProxy().getP2P().updateFreq(this, newFreq); this.onTunnelNetworkChange(); } Platform.notifyBlocksOfNeighbors(this.getTile().getWorld(), this.getTile().getPos()); } catch (final GridAccessException e) { // :P } this.onTunnelConfigChange(); final ItemStack p2pItem = this.getItemStack(PartItemStack.WRENCH); final String type = p2pItem.getTranslationKey(); p2pItem.writeToNBT(data); if (needsNewFrequency) { data.setShort("freq", newFreq); } else { data.setShort("freq", this.getFrequency()); } final AEColor[] colors = Platform.p2p().toColors(this.getFrequency()); final int[] colorCode = new int[]{ colors[0].ordinal(), colors[0].ordinal(), colors[1].ordinal(), colors[1].ordinal(), colors[2].ordinal(), colors[2].ordinal(), colors[3].ordinal(), colors[3].ordinal(), }; data.setIntArray("colorCode", colorCode); mc.setMemoryCardContents(is, type + ".name", data); if (needsNewFrequency) { mc.notifyUser(player, MemoryCardMessages.SETTINGS_RESET); } else { mc.notifyUser(player, MemoryCardMessages.SETTINGS_SAVED); } return true; } return false; } public void onTunnelConfigChange() { } public void onTunnelNetworkChange() { } protected void queueTunnelDrain(final PowerUnits unit, final double f) { final double ae_to_tax = unit.convertTo(PowerUnits.AE, f * AEConfig.TUNNEL_POWER_LOSS); try { this.getProxy().getEnergy().extractAEPower(ae_to_tax, Actionable.MODULATE, PowerMultiplier.ONE); } catch (final GridAccessException e) { // :P } } public short getFrequency() { return this.freq; } public void setFrequency(final short freq) { final short oldf = this.freq; this.freq = freq; if (oldf != this.freq) { this.getHost().markForUpdate(); } } public boolean isOutput() { return this.output; } void setOutput(final boolean output) { this.output = output; } @Override public Long getRenderFlag() { long ret = Short.toUnsignedLong(this.getFrequency()); if (this.isActive() && this.isPowered()) { ret |= 0x10000L; } return ret; } }