From 655cc902d3df19a1ac2bfaa38cc928ed629d0171 Mon Sep 17 00:00:00 2001 From: BlueWeabo Date: Sat, 1 Apr 2023 17:06:06 +0300 Subject: Implement Power Logic, Pollution Logic and Processing Logic for MuTEs and many other things (#1823) * update bs 2 * fuel consumption and energy implementation. clean up * don't register XD * some clean up * coke oven work * semi-working coke oven somehow i broke the activating of the multiblock * power logic * PowerLogic * clean up, saving loading nbt * small cleanup and pollution * pollution working :P * Energy mostly working, wallsharing * processing logic * fix npe and deregister * review requests * missed one * remove extra 0 --- src/main/java/gregtech/api/enums/GT_Values.java | 19 +- src/main/java/gregtech/api/enums/TickTime.java | 10 + .../interfaces/tileentity/IEnergyConnected.java | 74 +- .../java/gregtech/api/logic/PollutionLogic.java | 17 + src/main/java/gregtech/api/logic/PowerLogic.java | 130 ++ .../java/gregtech/api/logic/ProcessingLogic.java | 97 ++ .../api/logic/interfaces/PollutionLogicHost.java | 8 + .../api/logic/interfaces/PowerLogicHost.java | 16 + .../api/logic/interfaces/ProcessingLogicHost.java | 8 + .../MultiTileEntityClassContainer.java | 38 +- .../multitileentity/MultiTileEntityRegistry.java | 5 +- .../multitileentity/base/BaseMultiTileEntity.java | 1414 -------------------- .../base/BaseNontickableMultiTileEntity.java | 58 - .../base/BaseTickableMultiTileEntity.java | 121 -- .../api/multitileentity/base/MultiTileEntity.java | 1392 +++++++++++++++++++ .../base/NonTickableMultiTileEntity.java | 58 + .../base/TickableMultiTileEntity.java | 113 ++ .../multitileentity/enums/GT_MultiTileCasing.java | 19 + .../multitileentity/enums/GT_MultiTileMachine.java | 19 + .../interfaces/IMultiBlockController.java | 7 +- .../interfaces/IMultiTileMachine.java | 10 + .../machine/MultiTileBasicMachine.java | 751 +++++++++-- .../multiblock/base/MultiBlockController.java | 1008 ++++++++------ .../multiblock/base/MultiBlockPart.java | 202 +-- .../multiblock/base/MultiBlockPowerController.java | 44 + .../multiblock/base/MultiBlock_Stackable.java | 7 +- .../multiblock/base/WallShareablePart.java | 107 ++ .../multiblock/casing/AdvancedCasing.java | 36 - .../multiblock/casing/FunctionalCasing.java | 27 + .../multiblock/casing/InventoryUpgrade.java | 94 -- .../multiblock/casing/UpgradeCasing.java | 31 + .../api/net/GT_Packet_MultiTileEntity.java | 54 +- 32 files changed, 3530 insertions(+), 2464 deletions(-) create mode 100644 src/main/java/gregtech/api/enums/TickTime.java create mode 100644 src/main/java/gregtech/api/logic/PollutionLogic.java create mode 100644 src/main/java/gregtech/api/logic/PowerLogic.java create mode 100644 src/main/java/gregtech/api/logic/ProcessingLogic.java create mode 100644 src/main/java/gregtech/api/logic/interfaces/PollutionLogicHost.java create mode 100644 src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java create mode 100644 src/main/java/gregtech/api/logic/interfaces/ProcessingLogicHost.java delete mode 100644 src/main/java/gregtech/api/multitileentity/base/BaseMultiTileEntity.java delete mode 100644 src/main/java/gregtech/api/multitileentity/base/BaseNontickableMultiTileEntity.java delete mode 100644 src/main/java/gregtech/api/multitileentity/base/BaseTickableMultiTileEntity.java create mode 100644 src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java create mode 100644 src/main/java/gregtech/api/multitileentity/base/NonTickableMultiTileEntity.java create mode 100644 src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java create mode 100644 src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java create mode 100644 src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileMachine.java create mode 100644 src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileMachine.java create mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPowerController.java create mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/base/WallShareablePart.java delete mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/casing/AdvancedCasing.java create mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/casing/FunctionalCasing.java delete mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/casing/InventoryUpgrade.java create mode 100644 src/main/java/gregtech/api/multitileentity/multiblock/casing/UpgradeCasing.java (limited to 'src/main/java/gregtech/api') diff --git a/src/main/java/gregtech/api/enums/GT_Values.java b/src/main/java/gregtech/api/enums/GT_Values.java index 14cca69f05..d06e70b0b5 100644 --- a/src/main/java/gregtech/api/enums/GT_Values.java +++ b/src/main/java/gregtech/api/enums/GT_Values.java @@ -232,7 +232,7 @@ public class GT_Values { // Machines ACTIVE = "gt.active", // Boolean FLUID_OUT = "gt.fluidout", // Output Fluid - ITEM_OUT = "gt,itemout", // Output Item + ITEM_OUT = "gt.itemout", // Output Item PARALLEL = "gt.parallel", // Number TANK_CAPACITY = "gt.tankcap", // Number TANK_IN = "gt.tank.in.", // FluidStack @@ -242,6 +242,14 @@ public class GT_Values { INV_OUTPUT_SIZE = "gt.invsize.out", // Number INV_INPUT_LIST = "gt.invlist.in", // NBT List INV_OUTPUT_LIST = "gt.invlist.out", // NBT List + VOLTAGE = "gt.voltage", // Number + AMPERAGE = "gt.amperage", // Number + STORED_ENERGY = "gt.stored.energy", // Number + MAXIMUM_ENERGY = "gt.maximum.energy", // Number + EUT_CONSUMPTION = "gt.eut.consumption", // Number + BURN_TIME_LEFT = "gt.burn.time.left", // Number + TOTAL_BURN_TIME = "gt.total.burn.time", // Number + ALLOWED_WORK = "gt.allowed.work", // Boolean // MultiBlock STRUCTURE_OK = "gt.structure.ok", ROTATION = "gt.eRotation", FLIP = "gt.eFlip", TARGET = "gt.target", // Boolean @@ -255,6 +263,15 @@ public class GT_Values { UPGRADE_INVENTORY_NAME = "gt.invname.upg", // String UPGRADE_INVENTORIES_INPUT = "gt.invlist.upg.in", // NBT List UPGRADE_INVENTORIES_OUTPUT = "gt.invlist.upg.out", // NBT List + SEPARATE_INPUTS = "gt.separate.inputs", // Boolean + + // Logic + POWER_LOGIC = "gt.power.logic", // NBT Tag + POWER_LOGIC_STORED_ENERGY = "gt.power.logic.stored.energy", // Number + POWER_LOGIC_ENERGY_CAPACITY = "gt.power.logic.energy.capacity", // Number + POWER_LOGIC_VOLTAGE = "gt.power.logic.voltage", // Number + POWER_LOGIC_AMPERAGE = "gt.power.logic.voltage", // Number + POWER_LOGIC_TYPE = "gt.power.logic.type", // Number empty_ = ""; } diff --git a/src/main/java/gregtech/api/enums/TickTime.java b/src/main/java/gregtech/api/enums/TickTime.java new file mode 100644 index 0000000000..28c68e172f --- /dev/null +++ b/src/main/java/gregtech/api/enums/TickTime.java @@ -0,0 +1,10 @@ +package gregtech.api.enums; + +public class TickTime { + + public static final int TICK = 1; + public static final int SECOND = TICK * 20; + public static final int MINUTE = SECOND * 60; + public static final int HOUR = MINUTE * 60; + public static final int DAY = HOUR * 24; +} diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java b/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java index 4fcfc861bb..92d2482014 100644 --- a/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java +++ b/src/main/java/gregtech/api/interfaces/tileentity/IEnergyConnected.java @@ -5,6 +5,8 @@ import net.minecraftforge.common.util.ForgeDirection; import cofh.api.energy.IEnergyReceiver; import gregtech.api.GregTech_API; +import gregtech.api.logic.PowerLogic; +import gregtech.api.logic.interfaces.PowerLogicHost; import gregtech.api.util.GT_Utility; import ic2.api.energy.tile.IEnergySink; @@ -58,37 +60,49 @@ public interface IEnergyConnected extends IColoredTileEntity { */ public static long emitEnergyToNetwork(long aVoltage, long aAmperage, IEnergyConnected aEmitter) { long rUsedAmperes = 0; - if (aEmitter instanceof IHasWorldObjectAndCoords) { - IHasWorldObjectAndCoords emitterTile = (IHasWorldObjectAndCoords) aEmitter; - for (byte i = 0, j = 0; i < 6 && aAmperage > rUsedAmperes; i++) { - if (aEmitter.outputsEnergyTo(i)) { - j = GT_Utility.getOppositeSide(i); - final TileEntity tTileEntity = emitterTile.getTileEntityAtSide(i); - if (tTileEntity instanceof IEnergyConnected) { - if (aEmitter.getColorization() >= 0) { - final byte tColor = ((IEnergyConnected) tTileEntity).getColorization(); - if (tColor >= 0 && tColor != aEmitter.getColorization()) continue; - } - rUsedAmperes += ((IEnergyConnected) tTileEntity) - .injectEnergyUnits(j, aVoltage, aAmperage - rUsedAmperes); + if (!(aEmitter instanceof IHasWorldObjectAndCoords)) { + return 0; + } + + IHasWorldObjectAndCoords emitterTile = (IHasWorldObjectAndCoords) aEmitter; + for (byte i = 0, j = 0; i < 6 && aAmperage > rUsedAmperes; i++) { + if (!aEmitter.outputsEnergyTo(i)) { + continue; + } - } else if (tTileEntity instanceof IEnergySink) { - if (((IEnergySink) tTileEntity) - .acceptsEnergyFrom((TileEntity) aEmitter, ForgeDirection.getOrientation(j))) { - while (aAmperage > rUsedAmperes && ((IEnergySink) tTileEntity).getDemandedEnergy() > 0 - && ((IEnergySink) tTileEntity) - .injectEnergy(ForgeDirection.getOrientation(j), aVoltage, aVoltage) - < aVoltage) - rUsedAmperes++; - } - } else if (GregTech_API.mOutputRF && tTileEntity instanceof IEnergyReceiver) { - final ForgeDirection tDirection = ForgeDirection.getOrientation(i).getOpposite(); - final int rfOut = GT_Utility.safeInt(aVoltage * GregTech_API.mEUtoRF / 100); - if (((IEnergyReceiver) tTileEntity).receiveEnergy(tDirection, rfOut, true) == rfOut) { - ((IEnergyReceiver) tTileEntity).receiveEnergy(tDirection, rfOut, false); - rUsedAmperes++; - } - } + j = GT_Utility.getOppositeSide(i); + final TileEntity tTileEntity = emitterTile.getTileEntityAtSide(i); + if (tTileEntity instanceof PowerLogicHost) { + PowerLogicHost host = (PowerLogicHost) tTileEntity; + + PowerLogic logic = host.getPowerLogic(j); + if (logic == null || logic.isEnergyReceiver()) { + continue; + } + + rUsedAmperes += logic.injectEnergy(aVoltage, aAmperage - rUsedAmperes); + } else if (tTileEntity instanceof IEnergyConnected) { + if (aEmitter.getColorization() >= 0) { + final byte tColor = ((IEnergyConnected) tTileEntity).getColorization(); + if (tColor >= 0 && tColor != aEmitter.getColorization()) continue; + } + rUsedAmperes += ((IEnergyConnected) tTileEntity) + .injectEnergyUnits(j, aVoltage, aAmperage - rUsedAmperes); + + } else if (tTileEntity instanceof IEnergySink) { + if (((IEnergySink) tTileEntity) + .acceptsEnergyFrom((TileEntity) aEmitter, ForgeDirection.getOrientation(j))) { + while (aAmperage > rUsedAmperes && ((IEnergySink) tTileEntity).getDemandedEnergy() > 0 + && ((IEnergySink) tTileEntity) + .injectEnergy(ForgeDirection.getOrientation(j), aVoltage, aVoltage) < aVoltage) + rUsedAmperes++; + } + } else if (GregTech_API.mOutputRF && tTileEntity instanceof IEnergyReceiver) { + final ForgeDirection tDirection = ForgeDirection.getOrientation(i).getOpposite(); + final int rfOut = GT_Utility.safeInt(aVoltage * GregTech_API.mEUtoRF / 100); + if (((IEnergyReceiver) tTileEntity).receiveEnergy(tDirection, rfOut, true) == rfOut) { + ((IEnergyReceiver) tTileEntity).receiveEnergy(tDirection, rfOut, false); + rUsedAmperes++; } } } diff --git a/src/main/java/gregtech/api/logic/PollutionLogic.java b/src/main/java/gregtech/api/logic/PollutionLogic.java new file mode 100644 index 0000000000..8e1172e105 --- /dev/null +++ b/src/main/java/gregtech/api/logic/PollutionLogic.java @@ -0,0 +1,17 @@ +package gregtech.api.logic; + +public class PollutionLogic { + + private int pollutionAmount; + + public PollutionLogic() {} + + public PollutionLogic setPollutionAmount(int pollutionAmount) { + this.pollutionAmount = pollutionAmount; + return this; + } + + public int getPollutionAmount() { + return pollutionAmount; + } +} diff --git a/src/main/java/gregtech/api/logic/PowerLogic.java b/src/main/java/gregtech/api/logic/PowerLogic.java new file mode 100644 index 0000000000..8044a2f979 --- /dev/null +++ b/src/main/java/gregtech/api/logic/PowerLogic.java @@ -0,0 +1,130 @@ +package gregtech.api.logic; + +import net.minecraft.nbt.NBTTagCompound; + +import gregtech.api.enums.GT_Values.NBT; + +public class PowerLogic { + + public static int NONE = 0; + public static int RECEIVER = 1; + public static int EMITTER = 2; + public static int BOTH = RECEIVER | EMITTER; + private long storedEnergy = 0; + private long energyCapacity = 0; + private long voltage = 0; + private long amperage = 0; + private int type = 0; + + public PowerLogic() {} + + public PowerLogic setMaxVoltage(long voltage) { + this.voltage = voltage; + return this; + } + + public PowerLogic setEnergyCapacity(long energyCapacity) { + this.energyCapacity = energyCapacity; + return this; + } + + public PowerLogic setAmperage(long amperage) { + this.amperage = amperage; + return this; + } + + public PowerLogic setType(int type) { + this.type = type; + return this; + } + + public boolean addEnergyUnsafe(long totalEUAdded) { + if (storedEnergy + totalEUAdded >= energyCapacity) { + return false; + } + + storedEnergy += totalEUAdded; + return true; + } + + public boolean addEnergy(long voltage, long amperage) { + if (voltage > this.voltage) { + return false; + } + + return addEnergyUnsafe(voltage * amperage); + } + + public boolean addEnergy(long voltage) { + return addEnergy(voltage, 1); + } + + public long injectEnergy(long voltage, long availableAmperage) { + long usedAmperes = 0; + while (addEnergy(voltage, 1) && usedAmperes < amperage) { + usedAmperes++; + } + + return usedAmperes; + } + + public boolean removeEnergyUnsafe(long totalEURemoved) { + if (storedEnergy - totalEURemoved < 0) { + return false; + } + + storedEnergy -= totalEURemoved; + return true; + } + + public boolean removeEnergy(long voltage, long amperage) { + if (voltage > this.voltage) { + return false; + } + + return removeEnergyUnsafe(voltage * amperage); + } + + public boolean removeEnergy(long voltage) { + return removeEnergy(voltage, 1); + } + + public long getCapacity() { + return energyCapacity; + } + + public long getVoltage() { + return voltage; + } + + public long getStoredEnergy() { + return storedEnergy; + } + + public boolean isEnergyReceiver() { + return (type & RECEIVER) > 0; + } + + public boolean isEnergyEmitter() { + return (type & EMITTER) > 0; + } + + public void writeToNBT(NBTTagCompound nbt) { + NBTTagCompound powerLogic = new NBTTagCompound(); + powerLogic.setLong(NBT.POWER_LOGIC_ENERGY_CAPACITY, energyCapacity); + powerLogic.setLong(NBT.POWER_LOGIC_STORED_ENERGY, storedEnergy); + powerLogic.setLong(NBT.POWER_LOGIC_AMPERAGE, amperage); + powerLogic.setLong(NBT.POWER_LOGIC_VOLTAGE, voltage); + powerLogic.setInteger(NBT.POWER_LOGIC_TYPE, type); + nbt.setTag(NBT.POWER_LOGIC, powerLogic); + } + + public void loadFromNBT(NBTTagCompound nbt) { + NBTTagCompound powerLogic = nbt.getCompoundTag(NBT.POWER_LOGIC); + energyCapacity = powerLogic.getLong(NBT.POWER_LOGIC_ENERGY_CAPACITY); + storedEnergy = powerLogic.getLong(NBT.POWER_LOGIC_STORED_ENERGY); + amperage = powerLogic.getLong(NBT.POWER_LOGIC_AMPERAGE); + voltage = powerLogic.getLong(NBT.POWER_LOGIC_VOLTAGE); + type = powerLogic.getInteger(NBT.POWER_LOGIC_TYPE); + } +} diff --git a/src/main/java/gregtech/api/logic/ProcessingLogic.java b/src/main/java/gregtech/api/logic/ProcessingLogic.java new file mode 100644 index 0000000000..fa0d285401 --- /dev/null +++ b/src/main/java/gregtech/api/logic/ProcessingLogic.java @@ -0,0 +1,97 @@ +package gregtech.api.logic; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import gregtech.api.util.GT_Recipe.GT_Recipe_Map; + +public abstract class ProcessingLogic { + + protected GT_Recipe_Map recipeMap; + protected ItemStack[] inputItems; + protected ItemStack[] outputItems; + protected ItemStack[] currentOutputItems; + protected FluidStack[] inputFluids; + protected FluidStack[] outputFluids; + protected FluidStack[] currentOutputFluids; + protected long eut; + protected long duration; + + public ProcessingLogic() {} + + public ProcessingLogic setInputItems(ItemStack... itemInputs) { + this.inputItems = itemInputs; + return this; + } + + public ProcessingLogic setInputFluids(FluidStack... fluidInputs) { + this.inputFluids = fluidInputs; + return this; + } + + public ProcessingLogic setOutputItems(ItemStack... itemOutputs) { + this.outputItems = itemOutputs; + return this; + } + + public ProcessingLogic setOutputFluids(FluidStack... fluidOutputs) { + this.outputFluids = fluidOutputs; + return this; + } + + public ProcessingLogic setCurrentOutputItems(ItemStack... currentOutputItems) { + this.currentOutputItems = currentOutputItems; + return this; + } + + public ProcessingLogic setCurrentOutputFluids(FluidStack... currentOutputFluids) { + this.currentOutputFluids = currentOutputFluids; + return this; + } + + public ProcessingLogic setRecipeMap(GT_Recipe_Map recipeMap) { + this.recipeMap = recipeMap; + return this; + } + + public ProcessingLogic setDuration(long duration) { + this.duration = duration; + return this; + } + + public ProcessingLogic setEut(long eut) { + this.eut = eut; + return this; + } + + /** + * Clears everything stored in the Processing Logic other than the Recipe map used + */ + public ProcessingLogic clear() { + this.inputItems = null; + this.inputFluids = null; + this.outputItems = null; + this.outputFluids = null; + this.eut = 0; + this.duration = 0; + return this; + } + + public abstract boolean process(); + + public ItemStack[] getOutputItems() { + return outputItems; + } + + public FluidStack[] getOutputFluids() { + return outputFluids; + } + + public long getDuration() { + return duration; + } + + public long getEut() { + return eut; + } +} diff --git a/src/main/java/gregtech/api/logic/interfaces/PollutionLogicHost.java b/src/main/java/gregtech/api/logic/interfaces/PollutionLogicHost.java new file mode 100644 index 0000000000..657efbb74d --- /dev/null +++ b/src/main/java/gregtech/api/logic/interfaces/PollutionLogicHost.java @@ -0,0 +1,8 @@ +package gregtech.api.logic.interfaces; + +import gregtech.api.logic.PollutionLogic; + +public interface PollutionLogicHost { + + PollutionLogic getPollutionLogic(); +} diff --git a/src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java b/src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java new file mode 100644 index 0000000000..8e504674aa --- /dev/null +++ b/src/main/java/gregtech/api/logic/interfaces/PowerLogicHost.java @@ -0,0 +1,16 @@ +package gregtech.api.logic.interfaces; + +import gregtech.api.logic.PowerLogic; + +public interface PowerLogicHost { + + PowerLogic getPowerLogic(byte side); + + default boolean isEnergyReceiver() { + return false; + } + + default boolean isEnergyEmitter() { + return false; + } +} diff --git a/src/main/java/gregtech/api/logic/interfaces/ProcessingLogicHost.java b/src/main/java/gregtech/api/logic/interfaces/ProcessingLogicHost.java new file mode 100644 index 0000000000..55418208b0 --- /dev/null +++ b/src/main/java/gregtech/api/logic/interfaces/ProcessingLogicHost.java @@ -0,0 +1,8 @@ +package gregtech.api.logic.interfaces; + +import gregtech.api.logic.ProcessingLogic; + +public interface ProcessingLogicHost { + + ProcessingLogic getProcessingLogic(); +} diff --git a/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java b/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java index 84cbdfb529..195fed3100 100644 --- a/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java +++ b/src/main/java/gregtech/api/multitileentity/MultiTileEntityClassContainer.java @@ -8,9 +8,11 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.Tuple; import gregtech.api.enums.Materials; -import gregtech.api.multitileentity.base.BaseMultiTileEntity; -import gregtech.api.multitileentity.multiblock.casing.AdvancedCasing; +import gregtech.api.multitileentity.base.MultiTileEntity; +import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; +import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; import gregtech.api.util.GT_Util; +import gregtech.common.tileentities.casings.upgrade.InventoryUpgrade; public class MultiTileEntityClassContainer { @@ -19,9 +21,9 @@ public class MultiTileEntityClassContainer { private String mCategoryName; public final short mID; - public Class mClass; + public Class mClass; public MultiTileEntityBlock mBlock; - public BaseMultiTileEntity mCanonicalTileEntity; + public MultiTileEntity mCanonicalTileEntity; public NBTTagCompound mParameters; // These have defaults @@ -30,7 +32,7 @@ public class MultiTileEntityClassContainer { public boolean mHidden = false; public MultiTileEntityClassContainer(MultiTileEntityRegistry aRegistry, int aID, - Class aClass) { + Class aClass) { /* Start the Builder */ mRegistry = new WeakReference<>(aRegistry); mID = (short) aID; @@ -127,14 +129,13 @@ public class MultiTileEntityClassContainer { } public MultiTileEntityClassContainer tier(int aTier) { - verifyDescendentOf(AdvancedCasing.class); - + verifyDescendentOfMultiple(true, UpgradeCasing.class, FunctionalCasing.class); mParameters.setInteger(NBT.TIER, aTier); return this; } public MultiTileEntityClassContainer upgradeInventorySize(int aSize) { - verifyDescendentOf(AdvancedCasing.class); + verifyDescendentOf(InventoryUpgrade.class); mParameters.setInteger(NBT.UPGRADE_INVENTORY_SIZE, aSize); return this; @@ -161,4 +162,25 @@ public class MultiTileEntityClassContainer { "Expected a descendent of " + cls.getName() + " got " + mClass.getName() + " instead."); } } + + private void verifyDescendentOfMultiple(boolean onlyOne, Class... classes) { + boolean atLeastOne = false; + String classNames = ""; + for (Class cls : classes) { + classNames += cls.getName() + " "; + if (!onlyOne) { + verifyDescendentOf(cls); + atLeastOne = true; + } else { + if (cls.isAssignableFrom(mClass)) { + atLeastOne = true; + } + } + } + + if (!atLeastOne) { + throw new IllegalArgumentException( + "Expected a descendent of any of these " + classNames + " got " + mClass.getName() + " instead."); + } + } } diff --git a/src/main/java/gregtech/api/multitileentity/MultiTileEntityRegistry.java b/src/main/java/gregtech/api/multitileentity/MultiTileEntityRegistry.java index 589f7ef8a6..9fc35963b3 100644 --- a/src/main/java/gregtech/api/multitileentity/MultiTileEntityRegistry.java +++ b/src/main/java/gregtech/api/multitileentity/MultiTileEntityRegistry.java @@ -25,7 +25,7 @@ import com.gtnewhorizon.gtnhlib.util.map.ItemStackMap; import cpw.mods.fml.common.registry.GameRegistry; import gregtech.api.GregTech_API; import gregtech.api.enums.GT_Values; -import gregtech.api.multitileentity.base.BaseMultiTileEntity; +import gregtech.api.multitileentity.base.MultiTileEntity; import gregtech.api.multitileentity.interfaces.IMultiTileEntity; import gregtech.api.util.GT_LanguageManager; import gregtech.api.util.GT_Util; @@ -75,6 +75,7 @@ public class MultiTileEntityRegistry { "The MultiTileEntity Registry must be initialised during Preload Phase and not before"); mNameInternal = aNameInternal; mBlock = aBlock; + GT_FML_LOGGER.info(aNameInternal + " " + Block.getIdFromBlock(aBlock) + "This is the answer"); mBlock.mMultiTileEntityRegistry = this; REGISTRIES.put(new ItemStack(Item.getItemFromBlock(aBlock), 1, GT_Values.W), this); NAMED_REGISTRIES.put(mNameInternal, this); @@ -96,7 +97,7 @@ public class MultiTileEntityRegistry { return NAMED_REGISTRIES.get(aRegistryName); } - public MultiTileEntityClassContainer create(int aID, Class aClass) { + public MultiTileEntityClassContainer create(int aID, Class aClass) { return new MultiTileEntityClassContainer(this, aID, aClass); } diff --git a/src/main/java/gregtech/api/multitileentity/base/BaseMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/BaseMultiTileEntity.java deleted file mode 100644 index 06ae77afe1..0000000000 --- a/src/main/java/gregtech/api/multitileentity/base/BaseMultiTileEntity.java +++ /dev/null @@ -1,1414 +0,0 @@ -package gregtech.api.multitileentity.base; - -import static gregtech.GT_Mod.GT_FML_LOGGER; -import static gregtech.api.enums.GT_Values.NBT; -import static gregtech.api.enums.GT_Values.OPOS; -import static gregtech.api.enums.GT_Values.SIDE_WEST; -import static gregtech.api.enums.GT_Values.VALID_SIDES; -import static gregtech.api.enums.GT_Values.emptyIconContainerArray; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import mcp.mobius.waila.api.IWailaConfigHandler; -import mcp.mobius.waila.api.IWailaDataAccessor; - -import net.minecraft.block.Block; -import net.minecraft.client.renderer.RenderBlocks; -import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.init.Items; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.Packet; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.AxisAlignedBB; -import net.minecraft.util.ChunkCoordinates; -import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.MovingObjectPosition; -import net.minecraft.world.Explosion; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; -import net.minecraftforge.common.util.ForgeDirection; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTankInfo; -import net.minecraftforge.fluids.IFluidTank; - -import cpw.mods.fml.common.registry.GameRegistry; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import gregtech.api.GregTech_API; -import gregtech.api.enums.GT_Values; -import gregtech.api.enums.Materials; -import gregtech.api.enums.SoundResource; -import gregtech.api.enums.Textures; -import gregtech.api.gui.modularui.GT_UIInfos; -import gregtech.api.interfaces.IIconContainer; -import gregtech.api.interfaces.ITexture; -import gregtech.api.interfaces.tileentity.IGregtechWailaProvider; -import gregtech.api.interfaces.tileentity.IHasWorldObjectAndCoords; -import gregtech.api.metatileentity.CoverableTileEntity; -import gregtech.api.metatileentity.GregTechTileClientEvents; -import gregtech.api.multitileentity.MultiTileEntityBlockInternal; -import gregtech.api.multitileentity.MultiTileEntityClassContainer; -import gregtech.api.multitileentity.MultiTileEntityRegistry; -import gregtech.api.multitileentity.interfaces.IMultiBlockPart; -import gregtech.api.multitileentity.interfaces.IMultiTileEntity; -import gregtech.api.multitileentity.multiblock.casing.InventoryUpgrade; -import gregtech.api.net.GT_Packet_MultiTileEntity; -import gregtech.api.net.GT_Packet_New; -import gregtech.api.objects.GT_ItemStack; -import gregtech.api.objects.XSTR; -import gregtech.api.render.TextureFactory; -import gregtech.api.util.GT_Log; -import gregtech.api.util.GT_ModHandler; -import gregtech.api.util.GT_Util; -import gregtech.api.util.GT_Utility; -import gregtech.common.render.GT_MultiTexture; -import gregtech.common.render.IRenderedBlock; - -public abstract class BaseMultiTileEntity extends CoverableTileEntity - implements IMultiTileEntity, IHasWorldObjectAndCoords, IRenderedBlock, IGregtechWailaProvider { - - public IIconContainer[] mTextures = emptyIconContainerArray; - // public IIconContainer[] mTexturesFront = emptyIconContainerArray; - - // Makes a Bounding Box without having to constantly specify the Offset Coordinates. - protected static final float[] PX_BOX = { 0, 0, 0, 1, 1, 1 }; - - public Materials mMaterial = Materials._NULL; - protected final boolean mIsTicking; // If this TileEntity is ticking at all - - // This Variable checks if this TileEntity should refresh when the Block is being set. That way you - // can turn this check off any time you need it. - protected boolean mShouldRefresh = true; - - protected boolean mDoesBlockUpdate = false; // This Variable is for a buffered Block Update. - protected boolean mForceFullSelectionBoxes = false; // This Variable is for forcing the Selection Box to be full. - protected boolean mNeedsUpdate = false; - protected boolean mInventoryChanged = false; - protected boolean mIsPainted = false; - protected byte mFacing = SIDE_WEST; // Default to WEST, so it renders facing Left in the inventory - protected byte mColor; - protected int mRGBa = GT_Values.UNCOLORED; - private short mMTEID = GT_Values.W, mMTERegistry = GT_Values.W; - private String mCustomName = null; - private String mOwnerName = ""; - private UUID mOwnerUuid = GT_Utility.defaultUuid; - private boolean mLockUpgrade = false; - - public BaseMultiTileEntity(boolean mIsTicking) { - this.mIsTicking = mIsTicking; - } - - @Override - public short getMultiTileEntityID() { - return mMTEID; - } - - @Override - public short getMultiTileEntityRegistryID() { - return mMTERegistry; - } - - @Override - public void onRegistrationFirst(MultiTileEntityRegistry aRegistry, short aID) { - GameRegistry.registerTileEntity(getClass(), getTileEntityName()); - } - - @Override - public void initFromNBT(NBTTagCompound aNBT, short aMTEID, short aMTERegistry) { - // Set ID and Registry ID. - mMTEID = aMTEID; - mMTERegistry = aMTERegistry; - // Read the Default Parameters from NBT. - if (aNBT != null) readFromNBT(aNBT); - } - - @Override - public void loadTextureNBT(NBTTagCompound aNBT) { - // Loading the registry - final String textureName = aNBT.getString(NBT.TEXTURE); - mTextures = new IIconContainer[] { - new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/bottom"), - new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/top"), - new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/side"), }; - } - - @Override - public void copyTextures() { - // Loading an instance - final TileEntity tCanonicalTileEntity = MultiTileEntityRegistry - .getCanonicalTileEntity(getMultiTileEntityRegistryID(), getMultiTileEntityID()); - if (tCanonicalTileEntity instanceof BaseMultiTileEntity) - mTextures = ((BaseMultiTileEntity) tCanonicalTileEntity).mTextures; - } - - @Override - public void readFromNBT(NBTTagCompound aNBT) { - // Check if this is a World/Chunk Loading Process calling readFromNBT. - if (mMTEID == GT_Values.W || mMTERegistry == GT_Values.W) { - // Yes it is, so read the ID Tags first. - mMTEID = aNBT.getShort(NBT.MTE_ID); - mMTERegistry = aNBT.getShort(NBT.MTE_REG); - // And add additional Default Parameters, in case the Mod updated with new ones. - final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(mMTERegistry); - if (tRegistry != null) { - final MultiTileEntityClassContainer tClass = tRegistry.getClassContainer(mMTEID); - if (tClass != null) { - // Add the Default Parameters. Useful for things that differ between different tiers/types of the - // same machine - aNBT = GT_Util.fuseNBT(aNBT, tClass.mParameters); - } - } - } - // read the Coords if it has them. - if (aNBT.hasKey("x")) xCoord = aNBT.getInteger("x"); - if (aNBT.hasKey("y")) yCoord = aNBT.getInteger("y"); - if (aNBT.hasKey("z")) zCoord = aNBT.getInteger("z"); - // read the custom Name. - if (aNBT.hasKey(NBT.DISPAY)) mCustomName = aNBT.getCompoundTag(NBT.DISPAY).getString(NBT.CUSTOM_NAME); - - // And now everything else. - try { - if (aNBT.hasKey(NBT.MATERIAL)) mMaterial = Materials.get(aNBT.getString(NBT.MATERIAL)); - if (aNBT.hasKey(NBT.COLOR)) mRGBa = aNBT.getInteger(NBT.COLOR); - - mOwnerName = aNBT.getString(NBT.OWNER); - try { - mOwnerUuid = UUID.fromString(aNBT.getString(NBT.OWNER_UUID)); - } catch (IllegalArgumentException e) { - mOwnerUuid = null; - } - if (aNBT.hasKey(NBT.LOCK_UPGRADE)) mLockUpgrade = aNBT.getBoolean(NBT.LOCK_UPGRADE); - if (aNBT.hasKey(NBT.FACING)) mFacing = aNBT.getByte(NBT.FACING); - - readCoverNBT(aNBT); - readMultiTileNBT(aNBT); - - if (GregTech_API.sBlockIcons == null && aNBT.hasKey(NBT.TEXTURE)) { - loadTextureNBT(aNBT); - } else { - copyTextures(); - } - - if (mSidedRedstone.length != 6) mSidedRedstone = new byte[] { 15, 15, 15, 15, 15, 15 }; - - updateCoverBehavior(); - - } catch (Throwable e) { - GT_FML_LOGGER.error("readFromNBT", e); - } - } - - public void readMultiTileNBT(NBTTagCompound aNBT) { - /* Do Nothing */ - } - - @Override - public final void writeToNBT(NBTTagCompound aNBT) { - super.writeToNBT(aNBT); - // write the IDs - aNBT.setShort(NBT.MTE_ID, mMTEID); - aNBT.setShort(NBT.MTE_REG, mMTERegistry); - // write the Custom Name - if (GT_Utility.isStringValid(mCustomName)) { - final NBTTagCompound displayNBT; - if (aNBT.hasKey(NBT.DISPAY)) { - displayNBT = aNBT.getCompoundTag(NBT.DISPAY); - } else { - displayNBT = new NBTTagCompound(); - aNBT.setTag(NBT.DISPAY, displayNBT); - } - displayNBT.setString(NBT.CUSTOM_NAME, mCustomName); - } - - // write the rest - try { - aNBT.setString(NBT.OWNER, mOwnerName); - aNBT.setString(NBT.OWNER_UUID, mOwnerUuid == null ? "" : mOwnerUuid.toString()); - aNBT.setBoolean(NBT.LOCK_UPGRADE, mLockUpgrade); - aNBT.setByte(NBT.FACING, mFacing); - - writeCoverNBT(aNBT, false); - writeMultiTileNBT(aNBT); - } catch (Throwable e) { - GT_FML_LOGGER.error("writeToNBT", e); - } - } - - public void writeMultiTileNBT(NBTTagCompound aNBT) { - /* Do Nothing */ - } - - @Override - public NBTTagCompound writeItemNBT(NBTTagCompound aNBT) { - writeCoverNBT(aNBT, true); - - return aNBT; - } - - @Override - public boolean useModularUI() { - return false; - } - - @Override - public long getTimer() { - return 0; - } - - @Override - public int getRandomNumber(int aRange) { - return XSTR.XSTR_INSTANCE.nextInt(aRange); - } - - @Override - public TileEntity getTileEntity(int aX, int aY, int aZ) { - if (worldObj == null - || (ignoreUnloadedChunks && crossedChunkBorder(aX, aZ) && !worldObj.blockExists(aX, aY, aZ))) - return null; - return GT_Util.getTileEntity(worldObj, aX, aY, aZ, true); - } - - @Override - public boolean canUpdate() { - return mIsTicking && mShouldRefresh; - } - - @Override - public boolean shouldRefresh(Block aOldBlock, Block aNewBlock, int aOldMeta, int aNewMeta, World aWorld, int aX, - int aY, int aZ) { - return mShouldRefresh || aOldBlock != aNewBlock; - } - - @Override - public void updateEntity() { - super.updateEntity(); - if (mDoesBlockUpdate) doBlockUpdate(); - } - - public void doBlockUpdate() { - final Block tBlock = getBlock(getCoords()); - worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, tBlock); - if (this instanceof IMTE_IsProvidingStrongPower) for (byte tSide : GT_Values.ALL_VALID_SIDES) { - if (getBlockAtSide(tSide).isNormalCube( - worldObj, - xCoord + GT_Values.OFFX[tSide], - yCoord + GT_Values.OFFY[tSide], - zCoord + GT_Values.OFFZ[tSide])) { - worldObj.notifyBlocksOfNeighborChange( - xCoord + GT_Values.OFFX[tSide], - yCoord + GT_Values.OFFY[tSide], - zCoord + GT_Values.OFFZ[tSide], - tBlock, - OPOS[tSide]); - } - } - mDoesBlockUpdate = false; - } - - @Override - public boolean shouldSideBeRendered(byte aSide) { - final TileEntity tTileEntity = getTileEntityAtSideAndDistance(aSide, 1); - // TODO: check to an interface - // if (getBlockAtSide(aSide) == Blocks.glass) return false; - return tTileEntity instanceof IMultiTileEntity ? !((IMultiTileEntity) tTileEntity).isSurfaceOpaque(OPOS[aSide]) - : !getBlockAtSide(aSide).isOpaqueCube(); - } - - @Override - public boolean isSurfaceOpaque(byte aSide) { - return true; - } - - @Override - @SideOnly(Side.CLIENT) - public final IRenderedBlock passRenderingToObject(ItemStack aStack) { - return this; - } - - @Override - @SideOnly(Side.CLIENT) - public final IRenderedBlock passRenderingToObject(IBlockAccess aWorld, int aX, int aY, int aZ) { - return this; - } - - @Override - public int getRenderPasses(Block aBlock) { - return 1; - } - - @Override - public boolean usesRenderPass(int aRenderPass) { - return true; - } - - @Override - public boolean setBlockBounds(Block aBlock, int aRenderPass) { - return false; - } - - @Override - public boolean renderItem(Block aBlock, RenderBlocks aRenderer) { - return false; - } - - @Override - public boolean renderBlock(Block aBlock, RenderBlocks aRenderer, IBlockAccess aWorld, int aX, int aY, int aZ) { - return false; - } - - @Override - public ITexture[] getTexture(Block aBlock, byte aSide) { - return getTexture(aBlock, aSide, 1, VALID_SIDES); - } - - @Override - public final ITexture[] getTexture(Block aBlock, byte aSide, int aRenderPass, boolean[] aShouldSideBeRendered) { - if (!aShouldSideBeRendered[aSide]) return null; - - final ITexture coverTexture = getCoverTexture(aSide); - final ITexture[] textureUncovered = getTexture(aBlock, aSide, true, aRenderPass); - - if (coverTexture != null) { - return new ITexture[] { GT_MultiTexture.get(textureUncovered), coverTexture }; - } else { - return textureUncovered; - } - } - - @Override - public ITexture[] getTexture(Block aBlock, byte aSide, boolean isActive, int aRenderPass) { - // Top, bottom or side - aSide = (byte) Math.min(aSide, 2); - return new ITexture[] { TextureFactory.of(mTextures[aSide], GT_Util.getRGBaArray(mRGBa)) }; - } - - @Override - public void setCustomName(String aName) { - mCustomName = aName; - } - - @Override - public String getCustomName() { - return GT_Utility.isStringValid(mCustomName) ? mCustomName : null; - } - - @Override - public byte getColorization() { - // TODO - return 0; - } - - @Override - public boolean unpaint() { - return false; - } - - @Override - public byte setColorization(byte aColor) { - // TODO - return 0; - } - - @Override - public boolean isPainted() { - return false; - } - - @Override - public boolean paint(int aRGB) { - return false; - } - - @Override - public boolean isFacingValid(byte aFacing) { - return false; - } - - @Override - public byte getFrontFacing() { - return mFacing; - } - - /** - * Sets the main facing to {aSide} and update as appropriately - * - * @return Whether the facing was changed - */ - @Override - public boolean setMainFacing(byte aSide) { - if (!isValidFacing(aSide)) return false; - mFacing = aSide; - - issueClientUpdate(); - issueBlockUpdate(); - onFacingChange(); - checkDropCover(); - doEnetUpdate(); - - if (shouldTriggerBlockUpdate()) { - // If we're triggering a block update this will call onMachineBlockUpdate() - GregTech_API.causeMachineUpdate(worldObj, xCoord, yCoord, zCoord); - } else { - // If we're not trigger a cascading one, call the update here. - onMachineBlockUpdate(); - } - return true; - } - - @Override - public int getPaint() { - return this.mRGBa; - } - - @Override - public byte getBackFacing() { - return GT_Utility.getOppositeSide(mFacing); - } - - @Override - public boolean isValidFacing(byte aSide) { - return aSide >= 0 && aSide <= 6 && getValidFacings()[aSide]; - } - - @Override - public boolean[] getValidFacings() { - return VALID_SIDES; - } - - @Override - public void issueCoverUpdate(byte aSide) { - super.issueCoverUpdate(aSide); - issueClientUpdate(); - } - - public AxisAlignedBB box(double[] aBox) { - return AxisAlignedBB.getBoundingBox( - xCoord + aBox[0], - yCoord + aBox[1], - zCoord + aBox[2], - xCoord + aBox[3], - yCoord + aBox[4], - zCoord + aBox[5]); - } - - public boolean box(AxisAlignedBB aAABB, List aList, double aMinX, double aMinY, double aMinZ, - double aMaxX, double aMaxY, double aMaxZ) { - final AxisAlignedBB tBox = box(aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ); - return tBox.intersectsWith(aAABB) && aList.add(tBox); - } - - @Override - public void onFacingChange() { - /* Do nothing */ - } - - public AxisAlignedBB box(double aMinX, double aMinY, double aMinZ, double aMaxX, double aMaxY, double aMaxZ) { - return AxisAlignedBB.getBoundingBox( - xCoord + aMinX, - yCoord + aMinY, - zCoord + aMinZ, - xCoord + aMaxX, - yCoord + aMaxY, - zCoord + aMaxZ); - } - - @Override - public boolean shouldTriggerBlockUpdate() { - return false; - } - - public boolean box(AxisAlignedBB aAABB, List aList, double[] aBox) { - final AxisAlignedBB tBox = box(aBox[0], aBox[1], aBox[2], aBox[3], aBox[4], aBox[5]); - return tBox.intersectsWith(aAABB) && aList.add(tBox); - } - - @Override - public void onMachineBlockUpdate() { - /* Do nothing */ - } - - public boolean box(AxisAlignedBB aAABB, List aList, float[] aBox) { - final AxisAlignedBB tBox = box(aBox[0], aBox[1], aBox[2], aBox[3], aBox[4], aBox[5]); - return tBox.intersectsWith(aAABB) && aList.add(tBox); - } - - public boolean box(AxisAlignedBB aAABB, List aList) { - final AxisAlignedBB tBox = box(PX_BOX); - return tBox.intersectsWith(aAABB) && aList.add(tBox); - } - - public AxisAlignedBB box(float[] aBox) { - return AxisAlignedBB.getBoundingBox( - xCoord + aBox[0], - yCoord + aBox[1], - zCoord + aBox[2], - xCoord + aBox[3], - yCoord + aBox[4], - zCoord + aBox[5]); - } - - public boolean box(Block aBlock) { - aBlock.setBlockBounds(0, 0, 0, 1, 1, 1); - return true; - } - - /** - * Causes a general Texture update. - *

- * Only used Client Side to mark Blocks dirty. - */ - @Override - public void issueTextureUpdate() { - if (!mIsTicking) { - markBlockForUpdate(); - } else { - mNeedsUpdate = true; - } - } - - public boolean box(Block aBlock, double[] aBox) { - aBlock.setBlockBounds( - (float) aBox[0], - (float) aBox[1], - (float) aBox[2], - (float) aBox[3], - (float) aBox[4], - (float) aBox[5]); - return true; - } - - protected void markBlockForUpdate() { - worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); - // worldObj.func_147479_m(xCoord, yCoord, zCoord); - mNeedsUpdate = false; - } - - public boolean box(Block aBlock, float[] aBox) { - aBlock.setBlockBounds(aBox[0], aBox[1], aBox[2], aBox[3], aBox[4], aBox[5]); - return true; - } - - @Override - public void onTileEntityPlaced() { - /* empty */ - } - - public boolean box(Block aBlock, double aMinX, double aMinY, double aMinZ, double aMaxX, double aMaxY, - double aMaxZ) { - aBlock.setBlockBounds((float) aMinX, (float) aMinY, (float) aMinZ, (float) aMaxX, (float) aMaxY, (float) aMaxZ); - return true; - } - - @Override - public void setShouldRefresh(boolean aShouldRefresh) { - mShouldRefresh = aShouldRefresh; - } - - /** - * shouldJoinIc2Enet - defaults to false, override to change - */ - @Override - public boolean shouldJoinIc2Enet() { - return false; - } - - @Override - public final void addCollisionBoxesToList(AxisAlignedBB aAABB, List aList, Entity aEntity) { - box(getCollisionBoundingBoxFromPool(), aAABB, aList); - } - - /** - * Simple Function to prevent Block Updates from happening multiple times within the same Tick. - */ - @Override - public final void issueBlockUpdate() { - if (mIsTicking) mDoesBlockUpdate = true; - else doBlockUpdate(); - } - - @Override - public boolean isStillValid() { - return !isInvalid(); - } - - @Override - public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCoverID) { - return true; - } - - public AxisAlignedBB box() { - return AxisAlignedBB.getBoundingBox(xCoord, yCoord, zCoord, xCoord + 1, yCoord + 1, zCoord + 1); - } - - public boolean box(AxisAlignedBB aBox, AxisAlignedBB aAABB, List aList) { - return aBox != null && aBox.intersectsWith(aAABB) && aList.add(aBox); - } - - public float[] shrunkBox() { - return PX_BOX; - } - - @Override - public void setBlockBoundsBasedOnState(Block aBlock) { - box(aBlock); - } - - @Override - public AxisAlignedBB getCollisionBoundingBoxFromPool() { - return box(); - } - - @Override - public AxisAlignedBB getSelectedBoundingBoxFromPool() { - if (mForceFullSelectionBoxes) return box(); - return box(shrunkBox()); - } - - @Override - public ItemStack getPickBlock(MovingObjectPosition aTarget) { - final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(mMTERegistry); - return tRegistry == null ? null : tRegistry.getItem(mMTEID, writeItemNBT(new NBTTagCompound())); - } - - @Override - public void onBlockAdded() {} - - @Override - public String getOwnerName() { - if (GT_Utility.isStringInvalid(mOwnerName)) return "Player"; - return mOwnerName; - } - - @Override - public String setOwnerName(String aName) { - if (GT_Utility.isStringInvalid(aName)) return mOwnerName = "Player"; - return mOwnerName = aName; - } - - @Override - public UUID getOwnerUuid() { - return mOwnerUuid; - } - - @Override - public void setOwnerUuid(UUID uuid) { - mOwnerUuid = uuid; - } - - @Override - public boolean onPlaced(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ, byte aSide, - float aHitX, float aHitY, float aHitZ) { - mFacing = getSideForPlayerPlacing(aPlayer, mFacing, getValidFacings()); - onFacingChange(); - return true; - } - - @Override - public boolean allowInteraction(Entity aEntity) { - return true; - } - - public boolean allowRightclick(Entity aEntity) { - return allowInteraction(aEntity); - } - - @Override - public boolean onBlockActivated(EntityPlayer aPlayer, byte aSide, float aX, float aY, float aZ) { - try { - return allowRightclick(aPlayer) && onRightClick(aPlayer, aSide, aX, aY, aZ); - } catch (Throwable e) { - GT_FML_LOGGER.error("onBlockActivated Failed", e); - e.printStackTrace(GT_Log.err); - return true; - } - } - - @Override - public boolean onRightClick(EntityPlayer aPlayer, byte aSide, float aX, float aY, float aZ) { - if (isClientSide()) { - // Configure Cover, sneak can also be: screwdriver, wrench, side cutter, soldering iron - if (aPlayer.isSneaking()) { - final byte tSide = (getCoverIDAtSide(aSide) == 0) ? GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ) - : aSide; - return (getCoverBehaviorAtSideNew(tSide).hasCoverGUI()); - } else if (getCoverBehaviorAtSideNew(aSide).onCoverRightclickClient(aSide, this, aPlayer, aX, aY, aZ)) { - return true; - } - - if (!getCoverInfoAtSide(aSide).isGUIClickable()) return false; - } - if (isServerSide()) { - if (!privateAccess() || aPlayer.getDisplayName().equalsIgnoreCase(getOwnerName())) { - final ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem(); - final byte wrenchSide = GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ); - - if (tCurrentItem != null) { - if (getColorization() >= 0 - && GT_Utility.areStacksEqual(new ItemStack(Items.water_bucket, 1), tCurrentItem)) { - // TODO (Colorization) - } - if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWrenchList)) - return onWrenchRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); - if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sScrewdriverList)) - return onScrewdriverRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); - if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sHardHammerList)) - return onHammerRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); - if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSoftHammerList)) - return onMalletRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); - if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSolderingToolList)) - return onSolderingRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); - if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWireCutterList)) - return onWireCutterRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); - - final byte coverSide = getCoverIDAtSide(aSide) == 0 ? wrenchSide : aSide; - - if (getCoverIDAtSide(coverSide) == 0) { - if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sCovers.keySet())) { - if (GregTech_API.getCoverBehaviorNew(tCurrentItem) - .isCoverPlaceable(coverSide, tCurrentItem, this) - && allowCoverOnSide(coverSide, new GT_ItemStack(tCurrentItem))) { - setCoverItemAtSide(coverSide, tCurrentItem); - if (!aPlayer.capabilities.isCreativeMode) tCurrentItem.stackSize--; - GT_Utility.sendSoundToPlayers( - worldObj, - SoundResource.IC2_TOOLS_WRENCH, - 1.0F, - -1, - xCoord, - yCoord, - zCoord); - issueClientUpdate(); - } - sendCoverDataIfNeeded(); - return true; - } - } else { - if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sCrowbarList)) { - if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer)) { - GT_Utility.sendSoundToPlayers( - worldObj, - SoundResource.RANDOM_BREAK, - 1.0F, - -1, - xCoord, - yCoord, - zCoord); - dropCover(coverSide, aSide, false); - } - sendCoverDataIfNeeded(); - return true; - } - } - } else if (aPlayer.isSneaking()) { // Sneak click, no tool -> open cover config if possible. - aSide = (getCoverIDAtSide(aSide) == 0) ? GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ) - : aSide; - return getCoverIDAtSide(aSide) > 0 && getCoverBehaviorAtSideNew(aSide).onCoverShiftRightClick( - aSide, - getCoverIDAtSide(aSide), - getComplexCoverDataAtSide(aSide), - this, - aPlayer); - } - - if (getCoverBehaviorAtSideNew(aSide).onCoverRightClick( - aSide, - getCoverIDAtSide(aSide), - getComplexCoverDataAtSide(aSide), - this, - aPlayer, - aX, - aY, - aZ)) - return true; - - if (!getCoverInfoAtSide(aSide).isGUIClickable()) return false; - - return openModularUi(aPlayer, aSide); - } - } - return false; - } - - public boolean hasGui(byte aSide) { - return false; - } - - boolean openModularUi(EntityPlayer aPlayer, byte aSide) { - if (!hasGui(aSide) || !isServerSide()) { - System.out.println("No GUI or Not Serverside"); - return false; - } - - GT_UIInfos.openGTTileEntityUI(this, aPlayer); - System.out.println("Trying to open a UI"); - return true; - } - - public boolean onWrenchRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, - float aZ) { - if (setMainFacing(wrenchSide)) { - GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer); - GT_Utility.sendSoundToPlayers(worldObj, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1, xCoord, yCoord, zCoord); - } - return true; - } - - public boolean onScrewdriverRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, - float aY, float aZ) { - if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 200, aPlayer)) { - setCoverDataAtSide( - wrenchSide, - getCoverBehaviorAtSideNew(wrenchSide).onCoverScrewdriverClick( - wrenchSide, - getCoverIDAtSide(wrenchSide), - getComplexCoverDataAtSide(wrenchSide), - this, - aPlayer, - aX, - aY, - aZ)); - // TODO: Update connections! - GT_Utility.sendSoundToPlayers(worldObj, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1, xCoord, yCoord, zCoord); - } - return true; - } - - public boolean onHammerRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, - float aZ) { - - return true; - } - - public boolean onMalletRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, - float aZ) { - - return true; - } - - public boolean onSolderingRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, - float aY, float aZ) { - - return true; - } - - public boolean onWireCutterRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, - float aY, float aZ) { - - return true; - } - - @Override - public float getExplosionResistance(Entity aExploder, double aExplosionX, double aExplosionY, double aExplosionZ) { - return getExplosionResistance(); - } - - @Override - public float getExplosionResistance() { - return 10.0F; - } - - @Override - public void onExploded(Explosion aExplosion) {} - - @Override - public boolean isSideSolid(byte aSide) { - return true; - } - - @Override - public ArrayList getDrops(int aFortune, boolean aSilkTouch) { - final ArrayList rList = new ArrayList<>(); - final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(getMultiTileEntityRegistryID()); - if (tRegistry != null) rList.add(tRegistry.getItem(getMultiTileEntityID(), writeItemNBT(new NBTTagCompound()))); - - onBaseTEDestroyed(); - return rList; - } - - @Override - public boolean getSubItems(MultiTileEntityBlockInternal aBlock, Item aItem, CreativeTabs aTab, - List aList, short aID) { - return true; - } - - @Override - public boolean recolourBlock(byte aSide, byte aColor) { - // if (aColor > 15 || aColor < -1) aColor = -1; - // if(paint((byte) (aColor + 1))) { - //// updateClientData(); - //// causeBlockUpdate(); - // return true; - // } - // if (unpaint()) {updateClientData(); causeBlockUpdate(); return T;} - // mColor = (byte) (aColor + 1); - //// if (canAccessData()) mMetaTileEntity.onColorChangeServer(aColor); - return false; - } - - @Override - public boolean playerOwnsThis(EntityPlayer aPlayer, boolean aCheckPrecicely) { - if (aCheckPrecicely || privateAccess() || (mOwnerName.length() == 0)) - if ((mOwnerName.length() == 0) && isServerSide()) { - setOwnerName(aPlayer.getDisplayName()); - setOwnerUuid(aPlayer.getUniqueID()); - } else return !privateAccess() || aPlayer.getDisplayName().equals("Player") - || mOwnerName.equals("Player") - || mOwnerName.equals(aPlayer.getDisplayName()); - return true; - } - - @Override - public boolean privateAccess() { - return mLockUpgrade; - } - - /** - * @return a Packet containing all Data which has to be synchronised to the Client - Override as needed - */ - public GT_Packet_New getClientDataPacket() { - - final GT_Packet_MultiTileEntity packet = new GT_Packet_MultiTileEntity( - 0, - xCoord, - (short) yCoord, - zCoord, - getMultiTileEntityRegistryID(), - getMultiTileEntityID(), - (byte) ((mFacing & 7) | (mRedstone ? 16 : 0)), - mColor); - - packet.setCoverData( - getCoverInfoAtSide((byte) 0).getCoverID(), - getCoverInfoAtSide((byte) 1).getCoverID(), - getCoverInfoAtSide((byte) 2).getCoverID(), - getCoverInfoAtSide((byte) 3).getCoverID(), - getCoverInfoAtSide((byte) 4).getCoverID(), - getCoverInfoAtSide((byte) 5).getCoverID()); - - packet.setRedstoneData( - (byte) (((mSidedRedstone[0] > 0) ? 1 : 0) | ((mSidedRedstone[1] > 0) ? 2 : 0) - | ((mSidedRedstone[2] > 0) ? 4 : 0) - | ((mSidedRedstone[3] > 0) ? 8 : 0) - | ((mSidedRedstone[4] > 0) ? 16 : 0) - | ((mSidedRedstone[5] > 0) ? 32 : 0))); - - if (this instanceof IMTE_HasModes) { - final IMTE_HasModes mteModes = (IMTE_HasModes) this; - packet.setModes(mteModes.getMode(), mteModes.getAllowedModes()); - } - if (this instanceof IMultiBlockPart) { - final IMultiBlockPart mtePart = (IMultiBlockPart) this; - if (mtePart.getTargetPos() != null) { - final ChunkCoordinates aTarget = mtePart.getTargetPos(); - packet.setTargetPos(aTarget.posX, (short) aTarget.posY, aTarget.posZ); - } - packet.setInventoryIndex(mtePart.getLockedInventoryIndex()); - } - if (this instanceof InventoryUpgrade) { - String tName = ((InventoryUpgrade) this).getInventoryName(); - packet.setInventoryName(tName); - } - - return packet; - } - - @Override - public void sendClientData(EntityPlayerMP aPlayer) { - if (worldObj == null || worldObj.isRemote) return; - final GT_Packet_New tPacket = getClientDataPacket(); - if (aPlayer == null) { - GT_Values.NW.sendPacketToAllPlayersInRange(worldObj, tPacket, getXCoord(), getZCoord()); - } else { - GT_Values.NW.sendToPlayer(tPacket, aPlayer); - } - sendCoverDataIfNeeded(); - } - - @Override - public boolean receiveClientEvent(int aEventID, int aValue) { - super.receiveClientEvent(aEventID, aValue); - if (isClientSide()) { - issueTextureUpdate(); - switch (aEventID) { - case GregTechTileClientEvents.CHANGE_COMMON_DATA: - mFacing = (byte) (aValue & 7); - // mActive = ((aValue & 8) != 0); - mRedstone = ((aValue & 16) != 0); - // mLockUpgrade = ((aValue&32) != 0); - // mWorks = ((aValue & 64) != 0); - break; - case GregTechTileClientEvents.CHANGE_CUSTOM_DATA: - // Nothing here, currently - break; - case GregTechTileClientEvents.CHANGE_COLOR: - if (aValue > 16 || aValue < 0) aValue = 0; - mColor = (byte) aValue; - break; - case GregTechTileClientEvents.CHANGE_REDSTONE_OUTPUT: - mSidedRedstone[0] = (byte) ((aValue & 1) == 1 ? 15 : 0); - mSidedRedstone[1] = (byte) ((aValue & 2) == 2 ? 15 : 0); - mSidedRedstone[2] = (byte) ((aValue & 4) == 4 ? 15 : 0); - mSidedRedstone[3] = (byte) ((aValue & 8) == 8 ? 15 : 0); - mSidedRedstone[4] = (byte) ((aValue & 16) == 16 ? 15 : 0); - mSidedRedstone[5] = (byte) ((aValue & 32) == 32 ? 15 : 0); - break; - // case GregTechTileClientEvents.DO_SOUND: - // if (mTickTimer > 20) - // doSound((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5); - // break; - // case GregTechTileClientEvents.START_SOUND_LOOP: - // if (mTickTimer > 20) - // startSoundLoop((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5); - // break; - // case GregTechTileClientEvents.STOP_SOUND_LOOP: - // if (mTickTimer > 20) - // stopSoundLoop((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5); - // break; - // case GregTechTileClientEvents.CHANGE_LIGHT: - // mLightValue = (byte) aValue; - // break; - } - } - return true; - } - - @Override - public Packet getDescriptionPacket() { - issueClientUpdate(); - return null; - } - - @Override - public void getWailaBody(ItemStack itemStack, List currenttip, IWailaDataAccessor accessor, - IWailaConfigHandler config) { - super.getWailaBody(itemStack, currenttip, accessor, config); - currenttip.add(String.format("Facing: %s", ForgeDirection.getOrientation(getFrontFacing()).name())); - } - - @Override - public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y, - int z) { - super.getWailaNBTData(player, tile, tag, world, x, y, z); - } - - @Override - public boolean hasCustomInventoryName() { - return false; - } - - @Override - public ArrayList getDebugInfo(EntityPlayer aPlayer, int aLogLevel) { - final ArrayList tList = new ArrayList<>(); - if (aLogLevel > 2) { - tList.add( - "MultiTileRegistry-ID: " + EnumChatFormatting.BLUE - + mMTERegistry - + EnumChatFormatting.RESET - + " MultiTile-ID: " - + EnumChatFormatting.BLUE - + mMTEID - + EnumChatFormatting.RESET); - } - if (joinedIc2Enet) tList.add("Joined IC2 ENet"); - - addDebugInfo(aPlayer, aLogLevel, tList); - - return tList; - } - - protected void addDebugInfo(EntityPlayer aPlayer, int aLogLevel, ArrayList tList) { - /* Do nothing */ - } - - /** - * Fluid - A Default implementation of the Fluid Tank behaviour, so that every TileEntity can use this to simplify - * its Code. - */ - protected IFluidTank getFluidTankFillable(byte aSide, FluidStack aFluidToFill) { - return null; - } - - protected IFluidTank getFluidTankDrainable(byte aSide, FluidStack aFluidToDrain) { - return null; - } - - protected IFluidTank[] getFluidTanks(byte aSide) { - return GT_Values.emptyFluidTank; - } - - public boolean isLiquidInput(byte aSide) { - return true; - } - - public boolean isLiquidOutput(byte aSide) { - return true; - } - - @Override - public int fill(ForgeDirection aDirection, FluidStack aFluid, boolean aDoFill) { - if (aFluid == null || aFluid.amount <= 0) return 0; - final IFluidTank tTank = getFluidTankFillable((byte) aDirection.ordinal(), aFluid); - return (tTank == null) ? 0 : tTank.fill(aFluid, aDoFill); - } - - @Override - public FluidStack drain(ForgeDirection aDirection, FluidStack aFluid, boolean aDoDrain) { - if (aFluid == null || aFluid.amount <= 0) return null; - final IFluidTank tTank = getFluidTankDrainable((byte) aDirection.ordinal(), aFluid); - if (tTank == null || tTank.getFluid() == null - || tTank.getFluidAmount() == 0 - || !tTank.getFluid().isFluidEqual(aFluid)) - return null; - return tTank.drain(aFluid.amount, aDoDrain); - } - - @Override - public FluidStack drain(ForgeDirection aDirection, int aAmountToDrain, boolean aDoDrain) { - if (aAmountToDrain <= 0) return null; - final IFluidTank tTank = getFluidTankDrainable((byte) aDirection.ordinal(), null); - if (tTank == null || tTank.getFluid() == null || tTank.getFluidAmount() == 0) return null; - return tTank.drain(aAmountToDrain, aDoDrain); - } - - @Override - public boolean canFill(ForgeDirection aDirection, Fluid aFluid) { - if (aFluid == null) return false; - final IFluidTank tTank = getFluidTankFillable((byte) aDirection.ordinal(), new FluidStack(aFluid, 0)); - return tTank != null && (tTank.getFluid() == null || tTank.getFluid().getFluid() == aFluid); - } - - @Override - public boolean canDrain(ForgeDirection aDirection, Fluid aFluid) { - if (aFluid == null) return false; - final IFluidTank tTank = getFluidTankDrainable((byte) aDirection.ordinal(), new FluidStack(aFluid, 0)); - return tTank != null && (tTank.getFluid() != null && tTank.getFluid().getFluid() == aFluid); - } - - @Override - public FluidTankInfo[] getTankInfo(ForgeDirection aDirection) { - final IFluidTank[] tTanks = getFluidTanks((byte) aDirection.ordinal()); - if (tTanks == null || tTanks.length <= 0) return GT_Values.emptyFluidTankInfo; - final FluidTankInfo[] rInfo = new FluidTankInfo[tTanks.length]; - for (int i = 0; i < tTanks.length; i++) rInfo[i] = new FluidTankInfo(tTanks[i]); - return rInfo; - } - - /** - * Energy - Do nothing by Default - */ - @Override - public boolean isUniversalEnergyStored(long aEnergyAmount) { - return false; - } - - @Override - public long getUniversalEnergyStored() { - return 0; - } - - @Override - public long getUniversalEnergyCapacity() { - return 0; - } - - @Override - public long getOutputAmperage() { - return 0; - } - - @Override - public long getOutputVoltage() { - return 0; - } - - @Override - public long getInputAmperage() { - return 0; - } - - @Override - public long getInputVoltage() { - return 0; - } - - @Override - public boolean decreaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooLessEnergy) { - return false; - } - - @Override - public boolean increaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooMuchEnergy) { - return false; - } - - @Override - public boolean drainEnergyUnits(byte aSide, long aVoltage, long aAmperage) { - return false; - } - - @Override - public long getAverageElectricInput() { - return 0; - } - - @Override - public long getAverageElectricOutput() { - return 0; - } - - @Override - public long getStoredEU() { - return 0; - } - - @Override - public long getEUCapacity() { - return 0; - } - - @Override - public long injectEnergyUnits(byte aSide, long aVoltage, long aAmperage) { - return 0; - } - - @Override - public boolean inputEnergyFrom(byte aSide) { - return false; - } - - @Override - public boolean outputsEnergyTo(byte aSide) { - return false; - } - - /** - * Inventory - Do nothing by default - */ - @Override - public void openInventory() { - System.out.println("Open Inventory"); - /* Do nothing */ - } - - @Override - public void closeInventory() { - System.out.println("Close Inventory"); - /* Do nothing */ - } - - @Override - public boolean hasInventoryBeenModified() { - return false; - } - - @Override - public boolean isValidSlot(int aIndex) { - return false; - } - - @Override - public boolean addStackToSlot(int aIndex, ItemStack aStack) { - return false; - } - - @Override - public boolean addStackToSlot(int aIndex, ItemStack aStack, int aAmount) { - return false; - } - - @Override - public int[] getAccessibleSlotsFromSide(int aSide) { - return GT_Values.emptyIntArray; - } - - @Override - public boolean canInsertItem(int aSlot, ItemStack aStack, int aSide) { - return false; - } - - @Override - public boolean canExtractItem(int aSlot, ItemStack aStack, int aSide) { - return false; - } - - @Override - public int getSizeInventory() { - return 0; - } - - @Override - public ItemStack getStackInSlot(int aSlot) { - return null; - } - - @Override - public ItemStack decrStackSize(int aSlot, int aDecrement) { - return null; - } - - @Override - public ItemStack getStackInSlotOnClosing(int aSlot) { - return null; - } - - @Override - public void setInventorySlotContents(int aSlot, ItemStack aStack) { - /* Do nothing */ - } - - @Override - public int getInventoryStackLimit() { - return 0; - } - - @Override - public boolean isItemValidForSlot(int aSlot, ItemStack aStack) { - return false; - } - - @Override - public void markInventoryBeenModified() { - mInventoryChanged = true; - } - - /* - * Cover Helpers - */ - - public boolean coverLetsFluidIn(byte aSide, Fluid aFluid) { - return getCoverInfoAtSide(aSide).letsFluidIn(aFluid); - } - - public boolean coverLetsFluidOut(byte aSide, Fluid aFluid) { - return getCoverInfoAtSide(aSide).letsFluidOut(aFluid); - } - - public boolean coverLetsEnergyIn(byte aSide) { - return getCoverInfoAtSide(aSide).letsEnergyIn(); - } - - public boolean coverLetsEnergyOut(byte aSide) { - return getCoverInfoAtSide(aSide).letsEnergyOut(); - } - - public boolean coverLetsItemsIn(byte aSide, int aSlot) { - return getCoverInfoAtSide(aSide).letsItemsIn(aSlot); - } - - public boolean coverLetsItemsOut(byte aSide, int aSlot) { - return getCoverInfoAtSide(aSide).letsItemsOut(aSlot); - } - - @Override - public ItemStack getStackForm(long aAmount) { - return new ItemStack(Item.getItemById(getMultiTileEntityRegistryID()), (int) aAmount, getMultiTileEntityID()); - } -} diff --git a/src/main/java/gregtech/api/multitileentity/base/BaseNontickableMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/BaseNontickableMultiTileEntity.java deleted file mode 100644 index 29a24f9715..0000000000 --- a/src/main/java/gregtech/api/multitileentity/base/BaseNontickableMultiTileEntity.java +++ /dev/null @@ -1,58 +0,0 @@ -package gregtech.api.multitileentity.base; - -import static gregtech.api.enums.GT_Values.NW; - -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.network.Packet; - -import gregtech.api.net.GT_Packet_SendCoverData; -import gregtech.api.util.ISerializableObject; -import gregtech.common.covers.CoverInfo; - -public abstract class BaseNontickableMultiTileEntity extends BaseMultiTileEntity { - - boolean mConstructed = false; // Keeps track of whether this TE has been constructed and placed in the world - - public BaseNontickableMultiTileEntity() { - super(false); - } - - @Override - public void issueClientUpdate() { - if (worldObj != null && !worldObj.isRemote) sendClientData(null); - } - - @Override - public Packet getDescriptionPacket() { - // We should have a world object and have been constructed by this point - mConstructed = true; - - super.getDescriptionPacket(); - // We don't get ticked, so if we have any cover data that needs to be sent, send it now - sendCoverDataIfNeeded(); - return null; - } - - @Override - public void issueCoverUpdate(byte aSide) { - if (!mConstructed) { - // Queue these up and send them with the description packet - super.issueCoverUpdate(aSide); - } else { - // Otherwise, send the data right away - final CoverInfo coverInfo = getCoverInfoAtSide(aSide); - NW.sendPacketToAllPlayersInRange(worldObj, new GT_Packet_SendCoverData(coverInfo, this), xCoord, zCoord); - - // Just in case - coverInfo.setNeedsUpdate(false); - } - } - - @Override - public void receiveCoverData(byte aCoverSide, int aCoverID, ISerializableObject aCoverData, - EntityPlayerMP aPlayer) { - super.receiveCoverData(aCoverSide, aCoverID, aCoverData, aPlayer); - // We don't get ticked so issue the texture update right away - issueTextureUpdate(); - } -} diff --git a/src/main/java/gregtech/api/multitileentity/base/BaseTickableMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/BaseTickableMultiTileEntity.java deleted file mode 100644 index 0f124ae36e..0000000000 --- a/src/main/java/gregtech/api/multitileentity/base/BaseTickableMultiTileEntity.java +++ /dev/null @@ -1,121 +0,0 @@ -package gregtech.api.multitileentity.base; - -import static gregtech.GT_Mod.GT_FML_LOGGER; - -import net.minecraft.block.Block; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.world.World; - -import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_OnNeighborBlockChange; -import gregtech.api.util.GT_Log; -import gregtech.api.util.GT_Util; - -public abstract class BaseTickableMultiTileEntity extends BaseMultiTileEntity implements IMTE_OnNeighborBlockChange { - - /** Variable for seeing if the Tick Function is called right now. */ - public boolean mIsRunningTick = false; - /** Gets set to true when the Block received a Block Update. */ - public boolean mBlockUpdated = false; - /** Timer Value */ - protected long mTimer = 0; - /** Variable for updating Data to the Client */ - private boolean mSendClientData = false; - - public BaseTickableMultiTileEntity() { - super(true); - } - - @Override - public final void updateEntity() { - mIsRunningTick = true; - final boolean isServerSide = isServerSide(); - try { - if (mTimer++ == 0) { - markDirty(); - GT_Util.markChunkDirty(this); - onFirstTick(isServerSide); - } - if (!isDead()) onPreTick(mTimer, isServerSide); - if (!isDead()) { - mTimer++; - super.updateEntity(); - } - if (!isServerSide) { - if (mNeedsUpdate) { - worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); - // worldObj.func_147479_m(xCoord, yCoord, zCoord); - mNeedsUpdate = false; - } - } - if (!isDead()) onTick(mTimer, isServerSide); - if (!isDead() && isServerSide && mTimer > 2 && mSendClientData) { - sendClientData(null); - } - if (!isDead()) onPostTick(mTimer, isServerSide); - - } catch (Throwable e) { - GT_FML_LOGGER.error("UpdateEntity Failed", e); - e.printStackTrace(GT_Log.err); - try { - onTickFailed(mTimer, isServerSide); - } catch (Throwable e2) { - GT_FML_LOGGER.error("UpdateEntity:onTickFailed Failed", e); - } - } - - mIsRunningTick = false; - } - - @Override - public void sendClientData(EntityPlayerMP aPlayer) { - if (mSendClientData) { - GT_FML_LOGGER.info("Sending client data"); - super.sendClientData(aPlayer); - mSendClientData = false; - } - } - - /** The very first Tick happening to this TileEntity */ - public void onFirstTick(boolean isServerSide) { - if (isServerSide) { - checkDropCover(); - } else { - requestCoverDataIfNeeded(); - } - } - - /** The first part of the Tick. */ - public void onPreTick(long aTick, boolean isServerSide) { - /* Do nothing */ - } - - /** The regular Tick. */ - public void onTick(long aTimer, boolean isServerSide) { - /* Do nothing */ - } - - /** The absolute last part of the Tick. */ - public void onPostTick(long aTick, boolean isServerSide) { - /* Do nothing */ - } - - /** Gets called when there is an Exception happening during one of the Tick Functions. */ - public void onTickFailed(long aTimer, boolean isServerSide) { - /* Do nothing */ - } - - @Override - public void onNeighborBlockChange(World aWorld, Block aBlock) { - mBlockUpdated = true; - } - - @Override - public void issueClientUpdate() { - mSendClientData = true; - } - - @Override - public byte getComparatorValue(byte aSide) { - return 0; - } -} diff --git a/src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java new file mode 100644 index 0000000000..fdf72b4eab --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/base/MultiTileEntity.java @@ -0,0 +1,1392 @@ +package gregtech.api.multitileentity.base; + +import static gregtech.GT_Mod.GT_FML_LOGGER; +import static gregtech.api.enums.GT_Values.NBT; +import static gregtech.api.enums.GT_Values.OPOS; +import static gregtech.api.enums.GT_Values.SIDE_WEST; +import static gregtech.api.enums.GT_Values.VALID_SIDES; +import static gregtech.api.enums.GT_Values.emptyIconContainerArray; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import mcp.mobius.waila.api.IWailaConfigHandler; +import mcp.mobius.waila.api.IWailaDataAccessor; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.Packet; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.Explosion; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTankInfo; +import net.minecraftforge.fluids.IFluidTank; + +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.GregTech_API; +import gregtech.api.enums.GT_Values; +import gregtech.api.enums.Materials; +import gregtech.api.enums.SoundResource; +import gregtech.api.enums.Textures; +import gregtech.api.gui.modularui.GT_UIInfos; +import gregtech.api.interfaces.IIconContainer; +import gregtech.api.interfaces.ITexture; +import gregtech.api.metatileentity.CoverableTileEntity; +import gregtech.api.metatileentity.GregTechTileClientEvents; +import gregtech.api.multitileentity.MultiTileEntityBlockInternal; +import gregtech.api.multitileentity.MultiTileEntityClassContainer; +import gregtech.api.multitileentity.MultiTileEntityRegistry; +import gregtech.api.multitileentity.interfaces.IMultiTileEntity; +import gregtech.api.net.GT_Packet_MultiTileEntity; +import gregtech.api.net.GT_Packet_New; +import gregtech.api.objects.GT_ItemStack; +import gregtech.api.objects.XSTR; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GT_Log; +import gregtech.api.util.GT_ModHandler; +import gregtech.api.util.GT_Util; +import gregtech.api.util.GT_Utility; +import gregtech.common.render.GT_MultiTexture; +import gregtech.common.render.IRenderedBlock; + +public abstract class MultiTileEntity extends CoverableTileEntity implements IMultiTileEntity, IRenderedBlock { + + public IIconContainer[] textures = emptyIconContainerArray; + // public IIconContainer[] mTexturesFront = emptyIconContainerArray; + + // Makes a Bounding Box without having to constantly specify the Offset Coordinates. + protected static final float[] PX_BOX = { 0, 0, 0, 1, 1, 1 }; + + public Materials material = Materials._NULL; + protected final boolean isTicking; // If this TileEntity is ticking at all + + // This Variable checks if this TileEntity should refresh when the Block is being set. That way you + // can turn this check off any time you need it. + protected boolean shouldRefresh = true; + + protected boolean needsBlockUpdate = false; // This Variable is for a buffered Block Update. + protected boolean forceFullSelectionBox = false; // This Variable is for forcing the Selection Box to be full. + protected boolean needsUpdate = false; + protected boolean hasInventoryChanged = false; + protected boolean isPainted = false; + protected byte facing = SIDE_WEST; // Default to WEST, so it renders facing Left in the inventory + protected byte color; + protected int rgba = GT_Values.UNCOLORED; + private short mteID = GT_Values.W, mteRegistry = GT_Values.W; + private String customName = null; + private String ownerName = ""; + private UUID ownerUUID = GT_Utility.defaultUuid; + private boolean lockUpgrade = false; + + public MultiTileEntity(boolean isTicking) { + this.isTicking = isTicking; + } + + @Override + public short getMultiTileEntityID() { + return mteID; + } + + @Override + public short getMultiTileEntityRegistryID() { + return mteRegistry; + } + + @Override + public void onRegistrationFirst(MultiTileEntityRegistry registry, short id) { + GameRegistry.registerTileEntity(getClass(), getTileEntityName()); + } + + @Override + public void initFromNBT(NBTTagCompound nbt, short mteID, short mteRegistry) { + // Set ID and Registry ID. + this.mteID = mteID; + this.mteRegistry = mteRegistry; + // Read the Default Parameters from NBT. + if (nbt != null) readFromNBT(nbt); + } + + @Override + public void loadTextureNBT(NBTTagCompound nbt) { + // Loading the registry + final String textureName = nbt.getString(NBT.TEXTURE); + textures = new IIconContainer[] { + new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/bottom"), + new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/top"), + new Textures.BlockIcons.CustomIcon("multitileentity/base/" + textureName + "/side"), }; + } + + @Override + public void copyTextures() { + // Loading an instance + final TileEntity tCanonicalTileEntity = MultiTileEntityRegistry + .getCanonicalTileEntity(getMultiTileEntityRegistryID(), getMultiTileEntityID()); + if (tCanonicalTileEntity instanceof MultiTileEntity) + textures = ((MultiTileEntity) tCanonicalTileEntity).textures; + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + // Check if this is a World/Chunk Loading Process calling readFromNBT. + if (mteID == GT_Values.W || mteRegistry == GT_Values.W) { + // Yes it is, so read the ID Tags first. + mteID = nbt.getShort(NBT.MTE_ID); + mteRegistry = nbt.getShort(NBT.MTE_REG); + // And add additional Default Parameters, in case the Mod updated with new ones. + final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(mteRegistry); + if (tRegistry != null) { + final MultiTileEntityClassContainer tClass = tRegistry.getClassContainer(mteID); + if (tClass != null) { + // Add the Default Parameters. Useful for things that differ between different tiers/types of the + // same machine + nbt = GT_Util.fuseNBT(nbt, tClass.mParameters); + } + } + } + // read the Coords if it has them. + if (nbt.hasKey("x")) xCoord = nbt.getInteger("x"); + if (nbt.hasKey("y")) yCoord = nbt.getInteger("y"); + if (nbt.hasKey("z")) zCoord = nbt.getInteger("z"); + // read the custom Name. + if (nbt.hasKey(NBT.DISPAY)) customName = nbt.getCompoundTag(NBT.DISPAY).getString(NBT.CUSTOM_NAME); + + // And now everything else. + try { + if (nbt.hasKey(NBT.MATERIAL)) material = Materials.get(nbt.getString(NBT.MATERIAL)); + if (nbt.hasKey(NBT.COLOR)) rgba = nbt.getInteger(NBT.COLOR); + + ownerName = nbt.getString(NBT.OWNER); + try { + ownerUUID = UUID.fromString(nbt.getString(NBT.OWNER_UUID)); + } catch (IllegalArgumentException e) { + ownerUUID = null; + } + if (nbt.hasKey(NBT.LOCK_UPGRADE)) lockUpgrade = nbt.getBoolean(NBT.LOCK_UPGRADE); + if (nbt.hasKey(NBT.FACING)) facing = nbt.getByte(NBT.FACING); + + readCoverNBT(nbt); + readMultiTileNBT(nbt); + + if (GregTech_API.sBlockIcons == null && nbt.hasKey(NBT.TEXTURE)) { + loadTextureNBT(nbt); + } else { + copyTextures(); + } + + if (mSidedRedstone.length != 6) mSidedRedstone = new byte[] { 15, 15, 15, 15, 15, 15 }; + + updateCoverBehavior(); + + } catch (Throwable e) { + GT_FML_LOGGER.error("readFromNBT", e); + } + } + + public void readMultiTileNBT(NBTTagCompound aNBT) { + /* Do Nothing */ + } + + @Override + public final void writeToNBT(NBTTagCompound aNBT) { + super.writeToNBT(aNBT); + // write the IDs + aNBT.setShort(NBT.MTE_ID, mteID); + aNBT.setShort(NBT.MTE_REG, mteRegistry); + // write the Custom Name + if (GT_Utility.isStringValid(customName)) { + final NBTTagCompound displayNBT; + if (aNBT.hasKey(NBT.DISPAY)) { + displayNBT = aNBT.getCompoundTag(NBT.DISPAY); + } else { + displayNBT = new NBTTagCompound(); + aNBT.setTag(NBT.DISPAY, displayNBT); + } + displayNBT.setString(NBT.CUSTOM_NAME, customName); + } + + // write the rest + try { + aNBT.setString(NBT.OWNER, ownerName); + aNBT.setString(NBT.OWNER_UUID, ownerUUID == null ? "" : ownerUUID.toString()); + aNBT.setBoolean(NBT.LOCK_UPGRADE, lockUpgrade); + aNBT.setByte(NBT.FACING, facing); + + writeCoverNBT(aNBT, false); + writeMultiTileNBT(aNBT); + } catch (Throwable e) { + GT_FML_LOGGER.error("writeToNBT", e); + } + } + + public void writeMultiTileNBT(NBTTagCompound aNBT) { + /* Do Nothing */ + } + + @Override + public NBTTagCompound writeItemNBT(NBTTagCompound aNBT) { + writeCoverNBT(aNBT, true); + + return aNBT; + } + + @Override + public boolean useModularUI() { + return false; + } + + @Override + public long getTimer() { + return 0; + } + + @Override + public int getRandomNumber(int aRange) { + return XSTR.XSTR_INSTANCE.nextInt(aRange); + } + + @Override + public TileEntity getTileEntity(int aX, int aY, int aZ) { + if (worldObj == null + || (ignoreUnloadedChunks && crossedChunkBorder(aX, aZ) && !worldObj.blockExists(aX, aY, aZ))) + return null; + return GT_Util.getTileEntity(worldObj, aX, aY, aZ, true); + } + + @Override + public boolean canUpdate() { + return isTicking && shouldRefresh; + } + + @Override + public boolean shouldRefresh(Block aOldBlock, Block aNewBlock, int aOldMeta, int aNewMeta, World aWorld, int aX, + int aY, int aZ) { + return shouldRefresh || aOldBlock != aNewBlock; + } + + @Override + public void updateEntity() { + super.updateEntity(); + if (needsBlockUpdate) doBlockUpdate(); + } + + public void doBlockUpdate() { + final Block tBlock = getBlock(getCoords()); + worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, tBlock); + if (this instanceof IMTE_IsProvidingStrongPower) for (byte tSide : GT_Values.ALL_VALID_SIDES) { + if (getBlockAtSide(tSide).isNormalCube( + worldObj, + xCoord + GT_Values.OFFX[tSide], + yCoord + GT_Values.OFFY[tSide], + zCoord + GT_Values.OFFZ[tSide])) { + worldObj.notifyBlocksOfNeighborChange( + xCoord + GT_Values.OFFX[tSide], + yCoord + GT_Values.OFFY[tSide], + zCoord + GT_Values.OFFZ[tSide], + tBlock, + OPOS[tSide]); + } + } + needsBlockUpdate = false; + } + + @Override + public boolean shouldSideBeRendered(byte aSide) { + final TileEntity tTileEntity = getTileEntityAtSideAndDistance(aSide, 1); + // TODO: check to an interface + // if (getBlockAtSide(aSide) == Blocks.glass) return false; + return tTileEntity instanceof IMultiTileEntity ? !((IMultiTileEntity) tTileEntity).isSurfaceOpaque(OPOS[aSide]) + : !getBlockAtSide(aSide).isOpaqueCube(); + } + + @Override + public boolean isSurfaceOpaque(byte aSide) { + return true; + } + + @Override + @SideOnly(Side.CLIENT) + public final IRenderedBlock passRenderingToObject(ItemStack aStack) { + return this; + } + + @Override + @SideOnly(Side.CLIENT) + public final IRenderedBlock passRenderingToObject(IBlockAccess aWorld, int aX, int aY, int aZ) { + return this; + } + + @Override + public int getRenderPasses(Block aBlock) { + return 1; + } + + @Override + public boolean usesRenderPass(int aRenderPass) { + return true; + } + + @Override + public boolean setBlockBounds(Block aBlock, int aRenderPass) { + return false; + } + + @Override + public boolean renderItem(Block aBlock, RenderBlocks aRenderer) { + return false; + } + + @Override + public boolean renderBlock(Block aBlock, RenderBlocks aRenderer, IBlockAccess aWorld, int aX, int aY, int aZ) { + return false; + } + + @Override + public ITexture[] getTexture(Block aBlock, byte aSide) { + return getTexture(aBlock, aSide, 1, VALID_SIDES); + } + + @Override + public final ITexture[] getTexture(Block aBlock, byte aSide, int aRenderPass, boolean[] aShouldSideBeRendered) { + if (!aShouldSideBeRendered[aSide]) return null; + + final ITexture coverTexture = getCoverTexture(aSide); + final ITexture[] textureUncovered = getTexture(aBlock, aSide, true, aRenderPass); + + if (coverTexture != null) { + return new ITexture[] { GT_MultiTexture.get(textureUncovered), coverTexture }; + } else { + return textureUncovered; + } + } + + @Override + public ITexture[] getTexture(Block aBlock, byte aSide, boolean isActive, int aRenderPass) { + // Top, bottom or side + aSide = (byte) Math.min(aSide, 2); + return new ITexture[] { TextureFactory.of(textures[aSide], GT_Util.getRGBaArray(rgba)) }; + } + + @Override + public void setCustomName(String aName) { + customName = aName; + } + + @Override + public String getCustomName() { + return GT_Utility.isStringValid(customName) ? customName : null; + } + + @Override + public byte getColorization() { + // TODO + return 0; + } + + @Override + public boolean unpaint() { + return false; + } + + @Override + public byte setColorization(byte aColor) { + // TODO + return 0; + } + + @Override + public boolean isPainted() { + return false; + } + + @Override + public boolean paint(int aRGB) { + return false; + } + + @Override + public boolean isFacingValid(byte aFacing) { + return false; + } + + @Override + public byte getFrontFacing() { + return facing; + } + + /** + * Sets the main facing to {aSide} and update as appropriately + * + * @return Whether the facing was changed + */ + @Override + public boolean setMainFacing(byte aSide) { + if (!isValidFacing(aSide)) return false; + facing = aSide; + + issueClientUpdate(); + issueBlockUpdate(); + onFacingChange(); + checkDropCover(); + doEnetUpdate(); + + if (shouldTriggerBlockUpdate()) { + // If we're triggering a block update this will call onMachineBlockUpdate() + GregTech_API.causeMachineUpdate(worldObj, xCoord, yCoord, zCoord); + } else { + // If we're not trigger a cascading one, call the update here. + onMachineBlockUpdate(); + } + return true; + } + + @Override + public int getPaint() { + return this.rgba; + } + + @Override + public byte getBackFacing() { + return GT_Utility.getOppositeSide(facing); + } + + @Override + public boolean isValidFacing(byte aSide) { + return aSide >= 0 && aSide <= 6 && getValidFacings()[aSide]; + } + + @Override + public boolean[] getValidFacings() { + return VALID_SIDES; + } + + @Override + public void issueCoverUpdate(byte aSide) { + super.issueCoverUpdate(aSide); + issueClientUpdate(); + } + + public AxisAlignedBB box(double[] aBox) { + return AxisAlignedBB.getBoundingBox( + xCoord + aBox[0], + yCoord + aBox[1], + zCoord + aBox[2], + xCoord + aBox[3], + yCoord + aBox[4], + zCoord + aBox[5]); + } + + public boolean box(AxisAlignedBB aAABB, List aList, double aMinX, double aMinY, double aMinZ, + double aMaxX, double aMaxY, double aMaxZ) { + final AxisAlignedBB tBox = box(aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ); + return tBox.intersectsWith(aAABB) && aList.add(tBox); + } + + @Override + public void onFacingChange() { + /* Do nothing */ + } + + public AxisAlignedBB box(double aMinX, double aMinY, double aMinZ, double aMaxX, double aMaxY, double aMaxZ) { + return AxisAlignedBB.getBoundingBox( + xCoord + aMinX, + yCoord + aMinY, + zCoord + aMinZ, + xCoord + aMaxX, + yCoord + aMaxY, + zCoord + aMaxZ); + } + + @Override + public boolean shouldTriggerBlockUpdate() { + return false; + } + + public boolean box(AxisAlignedBB aAABB, List aList, double[] aBox) { + final AxisAlignedBB tBox = box(aBox[0], aBox[1], aBox[2], aBox[3], aBox[4], aBox[5]); + return tBox.intersectsWith(aAABB) && aList.add(tBox); + } + + @Override + public void onMachineBlockUpdate() { + /* Do nothing */ + } + + public boolean box(AxisAlignedBB aAABB, List aList, float[] aBox) { + final AxisAlignedBB tBox = box(aBox[0], aBox[1], aBox[2], aBox[3], aBox[4], aBox[5]); + return tBox.intersectsWith(aAABB) && aList.add(tBox); + } + + public boolean box(AxisAlignedBB aAABB, List aList) { + final AxisAlignedBB tBox = box(PX_BOX); + return tBox.intersectsWith(aAABB) && aList.add(tBox); + } + + public AxisAlignedBB box(float[] aBox) { + return AxisAlignedBB.getBoundingBox( + xCoord + aBox[0], + yCoord + aBox[1], + zCoord + aBox[2], + xCoord + aBox[3], + yCoord + aBox[4], + zCoord + aBox[5]); + } + + public boolean box(Block aBlock) { + aBlock.setBlockBounds(0, 0, 0, 1, 1, 1); + return true; + } + + /** + * Causes a general Texture update. + *

+ * Only used Client Side to mark Blocks dirty. + */ + @Override + public void issueTextureUpdate() { + if (!isTicking) { + markBlockForUpdate(); + } else { + needsUpdate = true; + } + } + + public boolean box(Block aBlock, double[] aBox) { + aBlock.setBlockBounds( + (float) aBox[0], + (float) aBox[1], + (float) aBox[2], + (float) aBox[3], + (float) aBox[4], + (float) aBox[5]); + return true; + } + + protected void markBlockForUpdate() { + worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); + // worldObj.func_147479_m(xCoord, yCoord, zCoord); + needsUpdate = false; + } + + public boolean box(Block aBlock, float[] aBox) { + aBlock.setBlockBounds(aBox[0], aBox[1], aBox[2], aBox[3], aBox[4], aBox[5]); + return true; + } + + @Override + public void onTileEntityPlaced() { + /* empty */ + } + + public boolean box(Block aBlock, double aMinX, double aMinY, double aMinZ, double aMaxX, double aMaxY, + double aMaxZ) { + aBlock.setBlockBounds((float) aMinX, (float) aMinY, (float) aMinZ, (float) aMaxX, (float) aMaxY, (float) aMaxZ); + return true; + } + + @Override + public void setShouldRefresh(boolean aShouldRefresh) { + shouldRefresh = aShouldRefresh; + } + + /** + * shouldJoinIc2Enet - defaults to false, override to change + */ + @Override + public boolean shouldJoinIc2Enet() { + return false; + } + + @Override + public final void addCollisionBoxesToList(AxisAlignedBB aAABB, List aList, Entity aEntity) { + box(getCollisionBoundingBoxFromPool(), aAABB, aList); + } + + /** + * Simple Function to prevent Block Updates from happening multiple times within the same Tick. + */ + @Override + public final void issueBlockUpdate() { + if (isTicking) needsBlockUpdate = true; + else doBlockUpdate(); + } + + @Override + public boolean isStillValid() { + return !isInvalid(); + } + + @Override + public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCoverID) { + return true; + } + + public AxisAlignedBB box() { + return AxisAlignedBB.getBoundingBox(xCoord, yCoord, zCoord, xCoord + 1, yCoord + 1, zCoord + 1); + } + + public boolean box(AxisAlignedBB aBox, AxisAlignedBB aAABB, List aList) { + return aBox != null && aBox.intersectsWith(aAABB) && aList.add(aBox); + } + + public float[] shrunkBox() { + return PX_BOX; + } + + @Override + public void setBlockBoundsBasedOnState(Block aBlock) { + box(aBlock); + } + + @Override + public AxisAlignedBB getCollisionBoundingBoxFromPool() { + return box(); + } + + @Override + public AxisAlignedBB getSelectedBoundingBoxFromPool() { + if (forceFullSelectionBox) return box(); + return box(shrunkBox()); + } + + @Override + public ItemStack getPickBlock(MovingObjectPosition aTarget) { + final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(mteRegistry); + return tRegistry == null ? null : tRegistry.getItem(mteID, writeItemNBT(new NBTTagCompound())); + } + + @Override + public void onBlockAdded() {} + + @Override + public String getOwnerName() { + if (GT_Utility.isStringInvalid(ownerName)) return "Player"; + return ownerName; + } + + @Override + public String setOwnerName(String aName) { + if (GT_Utility.isStringInvalid(aName)) return ownerName = "Player"; + return ownerName = aName; + } + + @Override + public UUID getOwnerUuid() { + return ownerUUID; + } + + @Override + public void setOwnerUuid(UUID uuid) { + ownerUUID = uuid; + } + + @Override + public boolean onPlaced(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ, byte aSide, + float aHitX, float aHitY, float aHitZ) { + facing = getSideForPlayerPlacing(aPlayer, facing, getValidFacings()); + onFacingChange(); + return true; + } + + @Override + public boolean allowInteraction(Entity aEntity) { + return true; + } + + public boolean allowRightclick(Entity aEntity) { + return allowInteraction(aEntity); + } + + @Override + public boolean onBlockActivated(EntityPlayer aPlayer, byte aSide, float aX, float aY, float aZ) { + try { + return allowRightclick(aPlayer) && onRightClick(aPlayer, aSide, aX, aY, aZ); + } catch (Throwable e) { + GT_FML_LOGGER.error("onBlockActivated Failed", e); + e.printStackTrace(GT_Log.err); + return true; + } + } + + @Override + public boolean onRightClick(EntityPlayer aPlayer, byte aSide, float aX, float aY, float aZ) { + if (isClientSide()) { + // Configure Cover, sneak can also be: screwdriver, wrench, side cutter, soldering iron + if (aPlayer.isSneaking()) { + final byte tSide = (getCoverIDAtSide(aSide) == 0) ? GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ) + : aSide; + return (getCoverBehaviorAtSideNew(tSide).hasCoverGUI()); + } else if (getCoverBehaviorAtSideNew(aSide).onCoverRightclickClient(aSide, this, aPlayer, aX, aY, aZ)) { + return true; + } + + if (!getCoverInfoAtSide(aSide).isGUIClickable()) return false; + } + if (isServerSide()) { + if (!privateAccess() || aPlayer.getDisplayName().equalsIgnoreCase(getOwnerName())) { + final ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem(); + final byte wrenchSide = GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ); + + if (tCurrentItem != null) { + if (getColorization() >= 0 + && GT_Utility.areStacksEqual(new ItemStack(Items.water_bucket, 1), tCurrentItem)) { + // TODO (Colorization) + } + if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWrenchList)) + return onWrenchRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); + if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sScrewdriverList)) + return onScrewdriverRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); + if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sHardHammerList)) + return onHammerRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); + if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSoftHammerList)) + return onMalletRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); + if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSolderingToolList)) + return onSolderingRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); + if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWireCutterList)) + return onWireCutterRightClick(aPlayer, tCurrentItem, wrenchSide, aX, aY, aZ); + + final byte coverSide = getCoverIDAtSide(aSide) == 0 ? wrenchSide : aSide; + + if (getCoverIDAtSide(coverSide) == 0) { + if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sCovers.keySet())) { + if (GregTech_API.getCoverBehaviorNew(tCurrentItem) + .isCoverPlaceable(coverSide, tCurrentItem, this) + && allowCoverOnSide(coverSide, new GT_ItemStack(tCurrentItem))) { + setCoverItemAtSide(coverSide, tCurrentItem); + if (!aPlayer.capabilities.isCreativeMode) tCurrentItem.stackSize--; + GT_Utility.sendSoundToPlayers( + worldObj, + SoundResource.IC2_TOOLS_WRENCH, + 1.0F, + -1, + xCoord, + yCoord, + zCoord); + issueClientUpdate(); + } + sendCoverDataIfNeeded(); + return true; + } + } else { + if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sCrowbarList)) { + if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer)) { + GT_Utility.sendSoundToPlayers( + worldObj, + SoundResource.RANDOM_BREAK, + 1.0F, + -1, + xCoord, + yCoord, + zCoord); + dropCover(coverSide, aSide, false); + } + sendCoverDataIfNeeded(); + return true; + } + } + } else if (aPlayer.isSneaking()) { // Sneak click, no tool -> open cover config if possible. + aSide = (getCoverIDAtSide(aSide) == 0) ? GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ) + : aSide; + return getCoverIDAtSide(aSide) > 0 && getCoverBehaviorAtSideNew(aSide).onCoverShiftRightClick( + aSide, + getCoverIDAtSide(aSide), + getComplexCoverDataAtSide(aSide), + this, + aPlayer); + } + + if (getCoverBehaviorAtSideNew(aSide).onCoverRightClick( + aSide, + getCoverIDAtSide(aSide), + getComplexCoverDataAtSide(aSide), + this, + aPlayer, + aX, + aY, + aZ)) + return true; + + if (!getCoverInfoAtSide(aSide).isGUIClickable()) return false; + + return openModularUi(aPlayer, aSide); + } + } + return false; + } + + public boolean hasGui(byte aSide) { + return false; + } + + boolean openModularUi(EntityPlayer aPlayer, byte aSide) { + if (!hasGui(aSide) || !isServerSide()) { + System.out.println("No GUI or Not Serverside"); + return false; + } + + GT_UIInfos.openGTTileEntityUI(this, aPlayer); + System.out.println("Trying to open a UI"); + return true; + } + + public boolean onWrenchRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, + float aZ) { + if (setMainFacing(wrenchSide)) { + GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer); + GT_Utility.sendSoundToPlayers(worldObj, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1, xCoord, yCoord, zCoord); + } + return true; + } + + public boolean onScrewdriverRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, + float aY, float aZ) { + if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 200, aPlayer)) { + setCoverDataAtSide( + wrenchSide, + getCoverBehaviorAtSideNew(wrenchSide).onCoverScrewdriverClick( + wrenchSide, + getCoverIDAtSide(wrenchSide), + getComplexCoverDataAtSide(wrenchSide), + this, + aPlayer, + aX, + aY, + aZ)); + // TODO: Update connections! + GT_Utility.sendSoundToPlayers(worldObj, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1, xCoord, yCoord, zCoord); + } + return true; + } + + public boolean onHammerRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, + float aZ) { + + return true; + } + + public boolean onMalletRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, float aY, + float aZ) { + + return true; + } + + public boolean onSolderingRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, + float aY, float aZ) { + + return true; + } + + public boolean onWireCutterRightClick(EntityPlayer aPlayer, ItemStack tCurrentItem, byte wrenchSide, float aX, + float aY, float aZ) { + + return true; + } + + @Override + public float getExplosionResistance(Entity aExploder, double aExplosionX, double aExplosionY, double aExplosionZ) { + return getExplosionResistance(); + } + + @Override + public float getExplosionResistance() { + return 10.0F; + } + + @Override + public void onExploded(Explosion aExplosion) {} + + @Override + public boolean isSideSolid(byte aSide) { + return true; + } + + @Override + public ArrayList getDrops(int aFortune, boolean aSilkTouch) { + final ArrayList rList = new ArrayList<>(); + final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(getMultiTileEntityRegistryID()); + if (tRegistry != null) rList.add(tRegistry.getItem(getMultiTileEntityID(), writeItemNBT(new NBTTagCompound()))); + + onBaseTEDestroyed(); + return rList; + } + + @Override + public boolean getSubItems(MultiTileEntityBlockInternal aBlock, Item aItem, CreativeTabs aTab, + List aList, short aID) { + return true; + } + + @Override + public boolean recolourBlock(byte aSide, byte aColor) { + // if (aColor > 15 || aColor < -1) aColor = -1; + // if(paint((byte) (aColor + 1))) { + //// updateClientData(); + //// causeBlockUpdate(); + // return true; + // } + // if (unpaint()) {updateClientData(); causeBlockUpdate(); return T;} + // mColor = (byte) (aColor + 1); + //// if (canAccessData()) mMetaTileEntity.onColorChangeServer(aColor); + return false; + } + + @Override + public boolean playerOwnsThis(EntityPlayer aPlayer, boolean aCheckPrecicely) { + if (aCheckPrecicely || privateAccess() || (ownerName.length() == 0)) + if ((ownerName.length() == 0) && isServerSide()) { + setOwnerName(aPlayer.getDisplayName()); + setOwnerUuid(aPlayer.getUniqueID()); + } else return !privateAccess() || aPlayer.getDisplayName().equals("Player") + || ownerName.equals("Player") + || ownerName.equals(aPlayer.getDisplayName()); + return true; + } + + @Override + public boolean privateAccess() { + return lockUpgrade; + } + + /** + * @return a Packet containing all Data which has to be synchronised to the Client - Override as needed + */ + public GT_Packet_MultiTileEntity getClientDataPacket() { + + final GT_Packet_MultiTileEntity packet = new GT_Packet_MultiTileEntity( + 0, + xCoord, + (short) yCoord, + zCoord, + getMultiTileEntityRegistryID(), + getMultiTileEntityID(), + (byte) ((facing & 7) | (mRedstone ? 16 : 0)), + color); + + packet.setCoverData( + getCoverInfoAtSide((byte) 0).getCoverID(), + getCoverInfoAtSide((byte) 1).getCoverID(), + getCoverInfoAtSide((byte) 2).getCoverID(), + getCoverInfoAtSide((byte) 3).getCoverID(), + getCoverInfoAtSide((byte) 4).getCoverID(), + getCoverInfoAtSide((byte) 5).getCoverID()); + + packet.setRedstoneData( + (byte) (((mSidedRedstone[0] > 0) ? 1 : 0) | ((mSidedRedstone[1] > 0) ? 2 : 0) + | ((mSidedRedstone[2] > 0) ? 4 : 0) + | ((mSidedRedstone[3] > 0) ? 8 : 0) + | ((mSidedRedstone[4] > 0) ? 16 : 0) + | ((mSidedRedstone[5] > 0) ? 32 : 0))); + return packet; + } + + @Override + public void sendClientData(EntityPlayerMP aPlayer) { + if (worldObj == null || worldObj.isRemote) return; + final GT_Packet_New tPacket = getClientDataPacket(); + if (aPlayer == null) { + GT_Values.NW.sendPacketToAllPlayersInRange(worldObj, tPacket, getXCoord(), getZCoord()); + } else { + GT_Values.NW.sendToPlayer(tPacket, aPlayer); + } + sendCoverDataIfNeeded(); + } + + @Override + public boolean receiveClientEvent(int aEventID, int aValue) { + super.receiveClientEvent(aEventID, aValue); + if (isClientSide()) { + issueTextureUpdate(); + switch (aEventID) { + case GregTechTileClientEvents.CHANGE_COMMON_DATA: + facing = (byte) (aValue & 7); + // mActive = ((aValue & 8) != 0); + mRedstone = ((aValue & 16) != 0); + // mLockUpgrade = ((aValue&32) != 0); + // mWorks = ((aValue & 64) != 0); + break; + case GregTechTileClientEvents.CHANGE_CUSTOM_DATA: + // Nothing here, currently + break; + case GregTechTileClientEvents.CHANGE_COLOR: + if (aValue > 16 || aValue < 0) aValue = 0; + color = (byte) aValue; + break; + case GregTechTileClientEvents.CHANGE_REDSTONE_OUTPUT: + mSidedRedstone[0] = (byte) ((aValue & 1) == 1 ? 15 : 0); + mSidedRedstone[1] = (byte) ((aValue & 2) == 2 ? 15 : 0); + mSidedRedstone[2] = (byte) ((aValue & 4) == 4 ? 15 : 0); + mSidedRedstone[3] = (byte) ((aValue & 8) == 8 ? 15 : 0); + mSidedRedstone[4] = (byte) ((aValue & 16) == 16 ? 15 : 0); + mSidedRedstone[5] = (byte) ((aValue & 32) == 32 ? 15 : 0); + break; + // case GregTechTileClientEvents.DO_SOUND: + // if (mTickTimer > 20) + // doSound((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5); + // break; + // case GregTechTileClientEvents.START_SOUND_LOOP: + // if (mTickTimer > 20) + // startSoundLoop((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5); + // break; + // case GregTechTileClientEvents.STOP_SOUND_LOOP: + // if (mTickTimer > 20) + // stopSoundLoop((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5); + // break; + // case GregTechTileClientEvents.CHANGE_LIGHT: + // mLightValue = (byte) aValue; + // break; + } + } + return true; + } + + @Override + public Packet getDescriptionPacket() { + issueClientUpdate(); + return null; + } + + @Override + public void getWailaBody(ItemStack itemStack, List currenttip, IWailaDataAccessor accessor, + IWailaConfigHandler config) { + super.getWailaBody(itemStack, currenttip, accessor, config); + currenttip.add(String.format("Facing: %s", ForgeDirection.getOrientation(getFrontFacing()).name())); + } + + @Override + public void getWailaNBTData(EntityPlayerMP player, TileEntity tile, NBTTagCompound tag, World world, int x, int y, + int z) { + super.getWailaNBTData(player, tile, tag, world, x, y, z); + } + + @Override + public boolean hasCustomInventoryName() { + return false; + } + + @Override + public ArrayList getDebugInfo(EntityPlayer aPlayer, int aLogLevel) { + final ArrayList tList = new ArrayList<>(); + if (aLogLevel > 2) { + tList.add( + "MultiTileRegistry-ID: " + EnumChatFormatting.BLUE + + mteRegistry + + EnumChatFormatting.RESET + + " MultiTile-ID: " + + EnumChatFormatting.BLUE + + mteID + + EnumChatFormatting.RESET); + } + if (joinedIc2Enet) tList.add("Joined IC2 ENet"); + + tList.add("Energy: " + getUniversalEnergyStored() + "/" + getUniversalEnergyCapacity()); + + addDebugInfo(aPlayer, aLogLevel, tList); + + return tList; + } + + protected void addDebugInfo(EntityPlayer aPlayer, int aLogLevel, ArrayList tList) { + /* Do nothing */ + } + + /** + * Fluid - A Default implementation of the Fluid Tank behaviour, so that every TileEntity can use this to simplify + * its Code. + */ + protected IFluidTank getFluidTankFillable(byte aSide, FluidStack aFluidToFill) { + return null; + } + + protected IFluidTank getFluidTankDrainable(byte aSide, FluidStack aFluidToDrain) { + return null; + } + + protected IFluidTank[] getFluidTanks(byte aSide) { + return GT_Values.emptyFluidTank; + } + + public boolean isLiquidInput(byte aSide) { + return true; + } + + public boolean isLiquidOutput(byte aSide) { + return true; + } + + @Override + public int fill(ForgeDirection aDirection, FluidStack aFluid, boolean aDoFill) { + if (aFluid == null || aFluid.amount <= 0) return 0; + final IFluidTank tTank = getFluidTankFillable((byte) aDirection.ordinal(), aFluid); + return (tTank == null) ? 0 : tTank.fill(aFluid, aDoFill); + } + + @Override + public FluidStack drain(ForgeDirection aDirection, FluidStack aFluid, boolean aDoDrain) { + if (aFluid == null || aFluid.amount <= 0) return null; + final IFluidTank tTank = getFluidTankDrainable((byte) aDirection.ordinal(), aFluid); + if (tTank == null || tTank.getFluid() == null + || tTank.getFluidAmount() == 0 + || !tTank.getFluid().isFluidEqual(aFluid)) + return null; + return tTank.drain(aFluid.amount, aDoDrain); + } + + @Override + public FluidStack drain(ForgeDirection aDirection, int aAmountToDrain, boolean aDoDrain) { + if (aAmountToDrain <= 0) return null; + final IFluidTank tTank = getFluidTankDrainable((byte) aDirection.ordinal(), null); + if (tTank == null || tTank.getFluid() == null || tTank.getFluidAmount() == 0) return null; + return tTank.drain(aAmountToDrain, aDoDrain); + } + + @Override + public boolean canFill(ForgeDirection aDirection, Fluid aFluid) { + if (aFluid == null) return false; + final IFluidTank tTank = getFluidTankFillable((byte) aDirection.ordinal(), new FluidStack(aFluid, 0)); + return tTank != null && (tTank.getFluid() == null || tTank.getFluid().getFluid() == aFluid); + } + + @Override + public boolean canDrain(ForgeDirection aDirection, Fluid aFluid) { + if (aFluid == null) return false; + final IFluidTank tTank = getFluidTankDrainable((byte) aDirection.ordinal(), new FluidStack(aFluid, 0)); + return tTank != null && (tTank.getFluid() != null && tTank.getFluid().getFluid() == aFluid); + } + + @Override + public FluidTankInfo[] getTankInfo(ForgeDirection aDirection) { + final IFluidTank[] tTanks = getFluidTanks((byte) aDirection.ordinal()); + if (tTanks == null || tTanks.length <= 0) return GT_Values.emptyFluidTankInfo; + final FluidTankInfo[] rInfo = new FluidTankInfo[tTanks.length]; + for (int i = 0; i < tTanks.length; i++) rInfo[i] = new FluidTankInfo(tTanks[i]); + return rInfo; + } + + /** + * Energy - Do nothing by Default + */ + @Override + public boolean isUniversalEnergyStored(long aEnergyAmount) { + return false; + } + + @Override + public long getUniversalEnergyStored() { + return 0; + } + + @Override + public long getUniversalEnergyCapacity() { + return 0; + } + + @Override + public long getOutputAmperage() { + return 0; + } + + @Override + public long getOutputVoltage() { + return 0; + } + + @Override + public long getInputAmperage() { + return 0; + } + + @Override + public long getInputVoltage() { + return 0; + } + + @Override + public boolean decreaseStoredEnergyUnits(long energy, boolean ignoreTooLittleEnergy) { + return false; + } + + @Override + public boolean increaseStoredEnergyUnits(long energy, boolean ignoreTooMuchEnergy) { + return false; + } + + @Override + public boolean drainEnergyUnits(byte aSide, long aVoltage, long aAmperage) { + return false; + } + + @Override + public long getAverageElectricInput() { + return 0; + } + + @Override + public long getAverageElectricOutput() { + return 0; + } + + @Override + public long getStoredEU() { + return 0; + } + + @Override + public long getEUCapacity() { + return 0; + } + + @Override + public long injectEnergyUnits(byte aSide, long aVoltage, long aAmperage) { + return 0; + } + + @Override + public boolean inputEnergyFrom(byte aSide) { + return false; + } + + @Override + public boolean outputsEnergyTo(byte aSide) { + return false; + } + + /** + * Inventory - Do nothing by default + */ + @Override + public void openInventory() { + System.out.println("Open Inventory"); + /* Do nothing */ + } + + @Override + public void closeInventory() { + System.out.println("Close Inventory"); + /* Do nothing */ + } + + @Override + public boolean hasInventoryBeenModified() { + return false; + } + + @Override + public boolean isValidSlot(int aIndex) { + return false; + } + + @Override + public boolean addStackToSlot(int aIndex, ItemStack aStack) { + return false; + } + + @Override + public boolean addStackToSlot(int aIndex, ItemStack aStack, int aAmount) { + return false; + } + + @Override + public int[] getAccessibleSlotsFromSide(int aSide) { + return GT_Values.emptyIntArray; + } + + @Override + public boolean canInsertItem(int aSlot, ItemStack aStack, int aSide) { + return false; + } + + @Override + public boolean canExtractItem(int aSlot, ItemStack aStack, int aSide) { + return false; + } + + @Override + public int getSizeInventory() { + return 0; + } + + @Override + public ItemStack getStackInSlot(int aSlot) { + return null; + } + + @Override + public ItemStack decrStackSize(int aSlot, int aDecrement) { + return null; + } + + @Override + public ItemStack getStackInSlotOnClosing(int aSlot) { + return null; + } + + @Override + public void setInventorySlotContents(int aSlot, ItemStack aStack) { + /* Do nothing */ + } + + @Override + public int getInventoryStackLimit() { + return 0; + } + + @Override + public boolean isItemValidForSlot(int aSlot, ItemStack aStack) { + return false; + } + + @Override + public void markInventoryBeenModified() { + hasInventoryChanged = true; + } + + /* + * Cover Helpers + */ + + public boolean coverLetsFluidIn(byte aSide, Fluid aFluid) { + return getCoverInfoAtSide(aSide).letsFluidIn(aFluid); + } + + public boolean coverLetsFluidOut(byte aSide, Fluid aFluid) { + return getCoverInfoAtSide(aSide).letsFluidOut(aFluid); + } + + public boolean coverLetsEnergyIn(byte aSide) { + return getCoverInfoAtSide(aSide).letsEnergyIn(); + } + + public boolean coverLetsEnergyOut(byte aSide) { + return getCoverInfoAtSide(aSide).letsEnergyOut(); + } + + public boolean coverLetsItemsIn(byte aSide, int aSlot) { + return getCoverInfoAtSide(aSide).letsItemsIn(aSlot); + } + + public boolean coverLetsItemsOut(byte aSide, int aSlot) { + return getCoverInfoAtSide(aSide).letsItemsOut(aSlot); + } + + @Override + public ItemStack getStackForm(long aAmount) { + return new ItemStack(Item.getItemById(getMultiTileEntityRegistryID()), (int) aAmount, getMultiTileEntityID()); + } +} diff --git a/src/main/java/gregtech/api/multitileentity/base/NonTickableMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/NonTickableMultiTileEntity.java new file mode 100644 index 0000000000..a4007ec85e --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/base/NonTickableMultiTileEntity.java @@ -0,0 +1,58 @@ +package gregtech.api.multitileentity.base; + +import static gregtech.api.enums.GT_Values.NW; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.Packet; + +import gregtech.api.net.GT_Packet_SendCoverData; +import gregtech.api.util.ISerializableObject; +import gregtech.common.covers.CoverInfo; + +public abstract class NonTickableMultiTileEntity extends MultiTileEntity { + + boolean mConstructed = false; // Keeps track of whether this TE has been constructed and placed in the world + + public NonTickableMultiTileEntity() { + super(false); + } + + @Override + public void issueClientUpdate() { + if (worldObj != null && !worldObj.isRemote) sendClientData(null); + } + + @Override + public Packet getDescriptionPacket() { + // We should have a world object and have been constructed by this point + mConstructed = true; + + super.getDescriptionPacket(); + // We don't get ticked, so if we have any cover data that needs to be sent, send it now + sendCoverDataIfNeeded(); + return null; + } + + @Override + public void issueCoverUpdate(byte aSide) { + if (!mConstructed) { + // Queue these up and send them with the description packet + super.issueCoverUpdate(aSide); + } else { + // Otherwise, send the data right away + final CoverInfo coverInfo = getCoverInfoAtSide(aSide); + NW.sendPacketToAllPlayersInRange(worldObj, new GT_Packet_SendCoverData(coverInfo, this), xCoord, zCoord); + + // Just in case + coverInfo.setNeedsUpdate(false); + } + } + + @Override + public void receiveCoverData(byte aCoverSide, int aCoverID, ISerializableObject aCoverData, + EntityPlayerMP aPlayer) { + super.receiveCoverData(aCoverSide, aCoverID, aCoverData, aPlayer); + // We don't get ticked so issue the texture update right away + issueTextureUpdate(); + } +} diff --git a/src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java b/src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java new file mode 100644 index 0000000000..25a9edd9ac --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/base/TickableMultiTileEntity.java @@ -0,0 +1,113 @@ +package gregtech.api.multitileentity.base; + +import static gregtech.GT_Mod.GT_FML_LOGGER; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.world.World; + +import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_OnNeighborBlockChange; +import gregtech.api.util.GT_Log; +import gregtech.api.util.GT_Util; + +public abstract class TickableMultiTileEntity extends MultiTileEntity implements IMTE_OnNeighborBlockChange { + + /** Variable for seeing if the Tick Function is called right now. */ + public boolean isRunningTick = false; + /** Gets set to true when the Block received a Block Update. */ + public boolean blockUpdated = false; + /** Timer Value */ + protected long timer = 0; + /** Variable for updating Data to the Client */ + private boolean sendClientData = false; + + public TickableMultiTileEntity() { + super(true); + } + + @Override + public final void updateEntity() { + isRunningTick = true; + final boolean isServerSide = isServerSide(); + try { + if (timer++ == 0) { + markDirty(); + GT_Util.markChunkDirty(this); + onFirstTick(isServerSide); + } + if (isDead()) { + return; + } + onPreTick(timer, isServerSide); + timer++; + super.updateEntity(); + if (!isServerSide && needsUpdate) { + worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); + needsUpdate = false; + } + onTick(timer, isServerSide); + if (isServerSide && timer > 2 && sendClientData) { + sendClientData(null); + } + onPostTick(timer, isServerSide); + + } catch (Throwable e) { + GT_FML_LOGGER.error("UpdateEntity Failed", e); + e.printStackTrace(GT_Log.err); + try { + onTickFailed(timer, isServerSide); + } catch (Throwable e2) { + GT_FML_LOGGER.error("UpdateEntity:onTickFailed Failed", e); + } + } + + isRunningTick = false; + } + + @Override + public void sendClientData(EntityPlayerMP aPlayer) { + if (sendClientData) { + GT_FML_LOGGER.info("Sending client data"); + super.sendClientData(aPlayer); + sendClientData = false; + } + } + + /** The very first Tick happening to this TileEntity */ + public void onFirstTick(boolean isServerSide) { + if (isServerSide) { + checkDropCover(); + } else { + requestCoverDataIfNeeded(); + } + } + + /** The first part of the Tick. */ + public void onPreTick(long aTick, boolean isServerSide) {} + + /** The regular Tick. */ + public void onTick(long tick, boolean isServerSide) { + + } + + /** The absolute last part of the Tick. */ + public void onPostTick(long aTick, boolean isServerSide) {} + + /** Gets called when there is an Exception happening during one of the Tick Functions. */ + public void onTickFailed(long aTimer, boolean isServerSide) {} + + @Override + public void onNeighborBlockChange(World aWorld, Block aBlock) { + blockUpdated = true; + } + + @Override + public void issueClientUpdate() { + sendClientData = true; + } + + @Override + public byte getComparatorValue(byte aSide) { + return 0; + } +} diff --git a/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java new file mode 100644 index 0000000000..be74ca3ef2 --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileCasing.java @@ -0,0 +1,19 @@ +package gregtech.api.multitileentity.enums; + +import gregtech.api.enums.GT_Values; + +public enum GT_MultiTileCasing { + + CokeOven(0), + NONE(GT_Values.W); + + private final short meta; + + GT_MultiTileCasing(int meta) { + this.meta = (short) meta; + } + + public short getId() { + return meta; + } +} diff --git a/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileMachine.java b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileMachine.java new file mode 100644 index 0000000000..0fc8f3dafd --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/enums/GT_MultiTileMachine.java @@ -0,0 +1,19 @@ +package gregtech.api.multitileentity.enums; + +import gregtech.api.enums.GT_Values; + +public enum GT_MultiTileMachine { + + CokeOven(0), + NONE(GT_Values.W); + + private final short meta; + + GT_MultiTileMachine(int meta) { + this.meta = (short) meta; + } + + public short getId() { + return meta; + } +} diff --git a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java index 22409563d9..21e1328d27 100644 --- a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java +++ b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiBlockController.java @@ -3,8 +3,9 @@ package gregtech.api.multitileentity.interfaces; import net.minecraft.util.ChunkCoordinates; import net.minecraftforge.fluids.FluidStack; -public interface IMultiBlockController - extends IMultiTileEntity, IMultiBlockFluidHandler, IMultiBlockInventory, IMultiBlockEnergy { +import gregtech.api.logic.PowerLogic; + +public interface IMultiBlockController extends IMultiTileEntity, IMultiBlockFluidHandler, IMultiBlockInventory { boolean checkStructure(boolean aForceReset); @@ -29,4 +30,6 @@ public interface IMultiBlockController void unregisterInventory(String aName, String aID, int aType); void changeInventoryName(String aName, String aID, int aType); + + PowerLogic getPowerLogic(IMultiBlockPart part, byte side); } diff --git a/src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileMachine.java b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileMachine.java new file mode 100644 index 0000000000..babb85d118 --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/interfaces/IMultiTileMachine.java @@ -0,0 +1,10 @@ +package gregtech.api.multitileentity.interfaces; + +public interface IMultiTileMachine { + + void setBooleans(int booleans); + + int getBooleans(); + + void setSound(byte soundEvent, int soundEventValue); +} diff --git a/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java b/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java index 3739854893..a3d94bd97c 100644 --- a/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java +++ b/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java @@ -1,49 +1,99 @@ package gregtech.api.multitileentity.machine; import static com.google.common.primitives.Ints.saturatedCast; +import static gregtech.api.enums.GT_Values.B; import static gregtech.api.enums.GT_Values.emptyIconContainerArray; +import java.util.ArrayList; + import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityFurnace; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidTank; import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable; import com.gtnewhorizons.modularui.api.forge.ItemStackHandler; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.enums.GT_Values; import gregtech.api.enums.GT_Values.NBT; +import gregtech.api.enums.SoundResource; import gregtech.api.enums.Textures; +import gregtech.api.enums.TickTime; import gregtech.api.fluid.FluidTankGT; import gregtech.api.interfaces.IIconContainer; import gregtech.api.interfaces.ITexture; +import gregtech.api.logic.PollutionLogic; +import gregtech.api.logic.PowerLogic; +import gregtech.api.logic.ProcessingLogic; +import gregtech.api.logic.interfaces.PollutionLogicHost; +import gregtech.api.logic.interfaces.PowerLogicHost; +import gregtech.api.logic.interfaces.ProcessingLogicHost; +import gregtech.api.metatileentity.GregTechTileClientEvents; import gregtech.api.multitileentity.MultiTileEntityRegistry; -import gregtech.api.multitileentity.base.BaseTickableMultiTileEntity; +import gregtech.api.multitileentity.base.TickableMultiTileEntity; +import gregtech.api.multitileentity.interfaces.IMultiTileMachine; +import gregtech.api.net.GT_Packet_MultiTileEntity; import gregtech.api.render.TextureFactory; import gregtech.api.util.GT_Util; import gregtech.api.util.GT_Utility; +import gregtech.client.GT_SoundLoop; +import gregtech.common.GT_Pollution; + +public abstract class MultiTileBasicMachine extends TickableMultiTileEntity implements IMultiTileMachine { -public class MultiTileBasicMachine extends BaseTickableMultiTileEntity { + protected static final int ACTIVE = B[0]; + protected static final int TICKS_BETWEEN_RECIPE_CHECKS = 5 * TickTime.SECOND; + protected static final int POLLUTION_TICK = TickTime.SECOND; + protected static final byte INTERRUPT_SOUND_INDEX = 8; + protected static final byte PROCESS_START_SOUND_INDEX = 1; protected static final IItemHandlerModifiable EMPTY_INVENTORY = new ItemStackHandler(0); private static final String TEXTURE_LOCATION = "multitileentity/machines/"; - public IIconContainer[] mTexturesInactive = emptyIconContainerArray; - public IIconContainer[] mTexturesActive = emptyIconContainerArray; - - protected int mParallel = 1; - protected boolean mActive = false; - protected long mStoredEnergy = 0; - protected FluidTankGT[] mTanksInput = GT_Values.emptyFluidTankGT, mTanksOutput = GT_Values.emptyFluidTankGT; - protected FluidStack[] mOutputFluids = GT_Values.emptyFluidStack; - - protected IItemHandlerModifiable mInputInventory = EMPTY_INVENTORY; - protected IItemHandlerModifiable mOutputInventory = EMPTY_INVENTORY; - protected boolean mOutputInventoryChanged = false; + public IIconContainer[] texturesInactive = emptyIconContainerArray; + public IIconContainer[] texturesActive = emptyIconContainerArray; + + protected int maxParallel = 1; + protected boolean active = false; + protected long storedEnergy = 0; + protected long voltage = 0; + protected long amperage = 2; + protected long eut = 0; + protected int tier = 0; + protected long maxProgressTime = 0; + protected long progressTime = 0; + protected long burnTime = 0; + protected long totalBurnTime = 0; + protected FluidTankGT[] inputTanks = GT_Values.emptyFluidTankGT; + protected FluidTankGT[] outputTanks = GT_Values.emptyFluidTankGT; + protected FluidStack[] fluidsToOutput = GT_Values.emptyFluidStack; + protected ItemStack[] itemsToOutput = GT_Values.emptyItemStackArray; + + protected IItemHandlerModifiable inputInventory = EMPTY_INVENTORY; + protected IItemHandlerModifiable outputInventory = EMPTY_INVENTORY; + protected boolean outputInventoryChanged = false; + private boolean powerShutDown = false; + private boolean wasEnabled = false; + private boolean canWork = true; + private boolean isElectric = true; + private boolean isSteam = false; + private boolean acceptsFuel = false; + private boolean isWireless = false; + private byte soundEvent = 0; + private int soundEventValue = 0; + + @SideOnly(Side.CLIENT) + protected GT_SoundLoop activitySoundLoop; @Override public String getTileEntityName() { @@ -51,20 +101,49 @@ public class MultiTileBasicMachine extends BaseTickableMultiTileEntity { } @Override - public void writeMultiTileNBT(NBTTagCompound aNBT) { - super.writeMultiTileNBT(aNBT); - if (mParallel > 0) aNBT.setInteger(NBT.PARALLEL, mParallel); - if (mActive) aNBT.setBoolean(NBT.ACTIVE, mActive); - if (mInputInventory != null && mInputInventory.getSlots() > 0) - writeInventory(aNBT, mInputInventory, NBT.INV_INPUT_LIST); - if (mOutputInventory != null && mOutputInventory.getSlots() > 0) - writeInventory(aNBT, mOutputInventory, NBT.INV_OUTPUT_LIST); - for (int i = 0; i < mTanksInput.length; i++) mTanksInput[i].writeToNBT(aNBT, NBT.TANK_IN + i); - for (int i = 0; i < mTanksOutput.length; i++) mTanksOutput[i].writeToNBT(aNBT, NBT.TANK_OUT + i); - if (mOutputFluids != null && mOutputFluids.length > 0) writeFluids(aNBT, mOutputFluids, NBT.FLUID_OUT); - } - - protected void writeFluids(NBTTagCompound aNBT, FluidStack[] fluids, String fluidListTag) { + public void writeMultiTileNBT(NBTTagCompound nbt) { + super.writeMultiTileNBT(nbt); + if (maxParallel > 0) { + nbt.setInteger(NBT.PARALLEL, maxParallel); + } + + if (active) { + nbt.setBoolean(NBT.ACTIVE, active); + } + + if (inputInventory != null && inputInventory.getSlots() > 0) { + writeInventory(nbt, inputInventory, NBT.INV_INPUT_LIST); + } + + if (outputInventory != null && outputInventory.getSlots() > 0) { + writeInventory(nbt, outputInventory, NBT.INV_OUTPUT_LIST); + } + + for (int i = 0; i < inputTanks.length; i++) { + inputTanks[i].writeToNBT(nbt, NBT.TANK_IN + i); + } + + for (int i = 0; i < outputTanks.length; i++) { + outputTanks[i].writeToNBT(nbt, NBT.TANK_OUT + i); + } + + if (fluidsToOutput != null && fluidsToOutput.length > 0) { + writeFluids(nbt, fluidsToOutput, NBT.FLUID_OUT); + } + + if (itemsToOutput != null) { + saveItemsToOutput(nbt); + } + + nbt.setInteger(NBT.TIER, tier); + nbt.setLong(NBT.EUT_CONSUMPTION, eut); + nbt.setLong(NBT.BURN_TIME_LEFT, burnTime); + nbt.setLong(NBT.TOTAL_BURN_TIME, totalBurnTime); + nbt.setBoolean(NBT.ALLOWED_WORK, canWork); + nbt.setBoolean(NBT.ACTIVE, active); + } + + protected void writeFluids(NBTTagCompound nbt, FluidStack[] fluids, String fluidListTag) { if (fluids != null && fluids.length > 0) { final NBTTagList tList = new NBTTagList(); for (final FluidStack tFluid : fluids) { @@ -74,54 +153,89 @@ public class MultiTileBasicMachine extends BaseTickableMultiTileEntity { tList.appendTag(tag); } } - aNBT.setTag(fluidListTag, tList); + nbt.setTag(fluidListTag, tList); } } - protected void writeInventory(NBTTagCompound aNBT, IItemHandlerModifiable inv, String invListTag) { + protected void writeInventory(NBTTagCompound nbt, IItemHandlerModifiable inv, String invListTag) { if (inv != null && inv.getSlots() > 0) { final NBTTagList tList = new NBTTagList(); - for (int tSlot = 0; tSlot < inv.getSlots(); tSlot++) { - final ItemStack tStack = inv.getStackInSlot(tSlot); + for (int slot = 0; slot < inv.getSlots(); slot++) { + final ItemStack tStack = inv.getStackInSlot(slot); if (tStack != null) { final NBTTagCompound tag = new NBTTagCompound(); - tag.setByte("s", (byte) tSlot); + tag.setByte("s", (byte) slot); tStack.writeToNBT(tag); tList.appendTag(tag); } } - aNBT.setTag(invListTag, tList); + nbt.setTag(invListTag, tList); } } + protected void saveItemsToOutput(NBTTagCompound aNBT) { + final NBTTagList nbtList = new NBTTagList(); + for (int slot = 0; slot < itemsToOutput.length; slot++) { + final ItemStack itemStack = itemsToOutput[slot]; + if (itemStack != null) { + final NBTTagCompound tag = new NBTTagCompound(); + tag.setByte("s", (byte) slot); + itemStack.writeToNBT(tag); + nbtList.appendTag(tag); + } + } + aNBT.setTag(NBT.ITEM_OUT, nbtList); + } + @Override - public void readMultiTileNBT(NBTTagCompound aNBT) { - super.readMultiTileNBT(aNBT); - if (aNBT.hasKey(NBT.PARALLEL)) mParallel = Math.max(1, aNBT.getInteger(NBT.PARALLEL)); - if (aNBT.hasKey(NBT.ACTIVE)) mActive = aNBT.getBoolean(NBT.ACTIVE); + public void readMultiTileNBT(NBTTagCompound nbt) { + super.readMultiTileNBT(nbt); + if (nbt.hasKey(NBT.PARALLEL)) { + maxParallel = Math.max(1, nbt.getInteger(NBT.PARALLEL)); + } + + if (nbt.hasKey(NBT.ACTIVE)) { + active = nbt.getBoolean(NBT.ACTIVE); + } /* Inventories */ - mInputInventory = new ItemStackHandler(Math.max(aNBT.getInteger(NBT.INV_INPUT_SIZE), 0)); - mOutputInventory = new ItemStackHandler(Math.max(aNBT.getInteger(NBT.INV_OUTPUT_SIZE), 0)); - loadInventory(aNBT, mInputInventory, NBT.INV_INPUT_LIST); - loadInventory(aNBT, mOutputInventory, NBT.INV_OUTPUT_LIST); + inputInventory = new ItemStackHandler(Math.max(nbt.getInteger(NBT.INV_INPUT_SIZE), 0)); + outputInventory = new ItemStackHandler(Math.max(nbt.getInteger(NBT.INV_OUTPUT_SIZE), 0)); + loadInventory(nbt, inputInventory, NBT.INV_INPUT_LIST); + loadInventory(nbt, outputInventory, NBT.INV_OUTPUT_LIST); /* Tanks */ - long tCapacity = 1000; - if (aNBT.hasKey(NBT.TANK_CAPACITY)) tCapacity = saturatedCast(aNBT.getLong(NBT.TANK_CAPACITY)); + long capacity = 1000; + if (nbt.hasKey(NBT.TANK_CAPACITY)) { + capacity = saturatedCast(nbt.getLong(NBT.TANK_CAPACITY)); + } - mTanksInput = new FluidTankGT[getFluidInputCount()]; - mTanksOutput = new FluidTankGT[getFluidOutputCount()]; - mOutputFluids = new FluidStack[getFluidOutputCount()]; + inputTanks = new FluidTankGT[getFluidInputCount()]; + outputTanks = new FluidTankGT[getFluidOutputCount()]; + fluidsToOutput = new FluidStack[getFluidOutputCount()]; // TODO: See if we need the adjustable map here `.setCapacity(mRecipes, mParallel * 2L)` in place of the // `setCapacityMultiplier` - for (int i = 0; i < mTanksInput.length; i++) mTanksInput[i] = new FluidTankGT(tCapacity) - .setCapacityMultiplier(mParallel * 2L).readFromNBT(aNBT, NBT.TANK_IN + i); - for (int i = 0; i < mTanksOutput.length; i++) - mTanksOutput[i] = new FluidTankGT().readFromNBT(aNBT, NBT.TANK_OUT + i); - for (int i = 0; i < mOutputFluids.length; i++) - mOutputFluids[i] = FluidStack.loadFluidStackFromNBT(aNBT.getCompoundTag(NBT.FLUID_OUT + "." + i)); + for (int i = 0; i < inputTanks.length; i++) { + inputTanks[i] = new FluidTankGT(capacity).setCapacityMultiplier(maxParallel * 2L) + .readFromNBT(nbt, NBT.TANK_IN + i); + } + for (int i = 0; i < outputTanks.length; i++) { + outputTanks[i] = new FluidTankGT().readFromNBT(nbt, NBT.TANK_OUT + i); + } + + for (int i = 0; i < fluidsToOutput.length; i++) { + fluidsToOutput[i] = FluidStack.loadFluidStackFromNBT(nbt.getCompoundTag(NBT.FLUID_OUT + "." + i)); + } + + loadItemsToOutput(nbt); + + tier = nbt.getInteger(NBT.TIER); + eut = nbt.getLong(NBT.EUT_CONSUMPTION); + burnTime = nbt.getLong(NBT.BURN_TIME_LEFT); + totalBurnTime = nbt.getLong(NBT.TOTAL_BURN_TIME); + canWork = nbt.getBoolean(NBT.ALLOWED_WORK); + active = nbt.getBoolean(NBT.ACTIVE); } protected void loadInventory(NBTTagCompound aNBT, IItemHandlerModifiable inv, String invListTag) { @@ -133,25 +247,35 @@ public class MultiTileBasicMachine extends BaseTickableMultiTileEntity { } } + protected void loadItemsToOutput(NBTTagCompound aNBT) { + final NBTTagList tList = aNBT.getTagList(NBT.ITEM_OUT, 10); + itemsToOutput = new ItemStack[tList.tagCount()]; + for (int i = 0; i < tList.tagCount(); i++) { + final NBTTagCompound tNBT = tList.getCompoundTagAt(i); + final int tSlot = tNBT.getByte("s"); + if (tSlot >= 0 && tSlot < itemsToOutput.length) itemsToOutput[tSlot] = GT_Utility.loadItem(tNBT); + } + } + @Override public void loadTextureNBT(NBTTagCompound aNBT) { // Loading the registry final String textureName = aNBT.getString(NBT.TEXTURE); - mTextures = new IIconContainer[] { + textures = new IIconContainer[] { new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/bottom"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/top"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/left"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/front"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/right"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/side") }; - mTexturesInactive = new IIconContainer[] { + texturesInactive = new IIconContainer[] { new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/bottom"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/top"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/left"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/front"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/right"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/inactive/back") }; - mTexturesActive = new IIconContainer[] { + texturesActive = new IIconContainer[] { new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/active/bottom"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/active/top"), new Textures.BlockIcons.CustomIcon(TEXTURE_LOCATION + textureName + "/overlay/active/left"), @@ -166,20 +290,33 @@ public class MultiTileBasicMachine extends BaseTickableMultiTileEntity { final TileEntity tCanonicalTileEntity = MultiTileEntityRegistry .getCanonicalTileEntity(getMultiTileEntityRegistryID(), getMultiTileEntityID()); if (tCanonicalTileEntity instanceof MultiTileBasicMachine) { - mTextures = ((MultiTileBasicMachine) tCanonicalTileEntity).mTextures; - mTexturesInactive = ((MultiTileBasicMachine) tCanonicalTileEntity).mTexturesInactive; - mTexturesActive = ((MultiTileBasicMachine) tCanonicalTileEntity).mTexturesActive; + textures = ((MultiTileBasicMachine) tCanonicalTileEntity).textures; + texturesInactive = ((MultiTileBasicMachine) tCanonicalTileEntity).texturesInactive; + texturesActive = ((MultiTileBasicMachine) tCanonicalTileEntity).texturesActive; } else { - mTextures = mTexturesInactive = mTexturesActive = emptyIconContainerArray; + textures = texturesInactive = texturesActive = emptyIconContainerArray; } } @Override public ITexture[] getTexture(Block aBlock, byte aSide, boolean isActive, int aRenderPass) { + if (aSide != facing) { + return new ITexture[] { TextureFactory + .of(textures[GT_Values.FACING_ROTATIONS[facing][aSide]], GT_Util.getRGBaArray(rgba)) }; + } return new ITexture[] { - TextureFactory.of(mTextures[GT_Values.FACING_ROTATIONS[mFacing][aSide]], GT_Util.getRGBaArray(mRGBa)), - TextureFactory.of( - (mActive ? mTexturesActive : mTexturesInactive)[GT_Values.FACING_ROTATIONS[mFacing][aSide]]) }; + TextureFactory.of(textures[GT_Values.FACING_ROTATIONS[facing][aSide]], GT_Util.getRGBaArray(rgba)), + TextureFactory + .of((active ? texturesActive : texturesInactive)[GT_Values.FACING_ROTATIONS[facing][aSide]]) }; + } + + @Override + public GT_Packet_MultiTileEntity getClientDataPacket() { + final GT_Packet_MultiTileEntity packet = super.getClientDataPacket(); + int booleans = getBooleans(); + packet.setBooleans(booleans); + packet.setSoundEvent(soundEvent, soundEventValue); + return packet; } /* @@ -221,12 +358,12 @@ public class MultiTileBasicMachine extends BaseTickableMultiTileEntity { @Override public boolean isLiquidInput(byte aSide) { - return aSide != mFacing; + return aSide != facing; } @Override public boolean isLiquidOutput(byte aSide) { - return aSide != mFacing; + return aSide != facing; } @Override @@ -235,14 +372,14 @@ public class MultiTileBasicMachine extends BaseTickableMultiTileEntity { final boolean fluidOutput = isLiquidOutput(aSide); if (fluidInput && fluidOutput) { - final IFluidTank[] rTanks = new IFluidTank[mTanksInput.length + mTanksOutput.length]; - System.arraycopy(mTanksInput, 0, rTanks, 0, mTanksInput.length); - System.arraycopy(mTanksOutput, 0, rTanks, mTanksInput.length, mTanksOutput.length); + final IFluidTank[] rTanks = new IFluidTank[inputTanks.length + outputTanks.length]; + System.arraycopy(inputTanks, 0, rTanks, 0, inputTanks.length); + System.arraycopy(outputTanks, 0, rTanks, inputTanks.length, outputTanks.length); return rTanks; } else if (fluidInput) { - return mTanksInput; + return inputTanks; } else if (fluidOutput) { - return mTanksOutput; + return outputTanks; } return GT_Values.emptyFluidTank; } @@ -250,127 +387,483 @@ public class MultiTileBasicMachine extends BaseTickableMultiTileEntity { @Override public IFluidTank getFluidTankFillable(byte aSide, FluidStack aFluidToFill) { if (!isLiquidInput(aSide)) return null; - for (FluidTankGT tankGT : mTanksInput) if (tankGT.contains(aFluidToFill)) return tankGT; + for (FluidTankGT tankGT : inputTanks) if (tankGT.contains(aFluidToFill)) return tankGT; // if (!mRecipes.containsInput(aFluidToFill, this, slot(mRecipes.mInputItemsCount + // mRecipes.mOutputItemsCount))) return null; - for (FluidTankGT fluidTankGT : mTanksInput) if (fluidTankGT.isEmpty()) return fluidTankGT; + for (FluidTankGT fluidTankGT : inputTanks) if (fluidTankGT.isEmpty()) return fluidTankGT; return null; } @Override protected IFluidTank getFluidTankDrainable(byte aSide, FluidStack aFluidToDrain) { if (!isLiquidOutput(aSide)) return null; - for (FluidTankGT fluidTankGT : mTanksOutput) + for (FluidTankGT fluidTankGT : outputTanks) if (aFluidToDrain == null ? fluidTankGT.has() : fluidTankGT.contains(aFluidToDrain)) return fluidTankGT; return null; } /* - * Energy + * Inventory */ @Override - public boolean isEnetInput() { - return true; + public boolean hasInventoryBeenModified() { + // True if the input inventory has changed + return hasInventoryChanged; } - @Override - public boolean isEnetOutput() { - return true; + public void markOutputInventoryBeenModified() { + outputInventoryChanged = true; } - @Override - public boolean isUniversalEnergyStored(long aEnergyAmount) { - return getUniversalEnergyStored() >= aEnergyAmount; + public boolean hasOutputInventoryBeenModified() { + // True if the output inventory has changed + return outputInventoryChanged; } - @Override - public long getUniversalEnergyStored() { - return mStoredEnergy; + public void markInputInventoryBeenModified() { + hasInventoryChanged = true; } @Override - public long getUniversalEnergyCapacity() { - return 0; + public boolean isItemValidForSlot(int aSlot, ItemStack aStack) { + return false; } @Override - public long getOutputAmperage() { - return 1; + public int getInventoryStackLimit() { + return 64; } + // #region Machine + @Override - public long getOutputVoltage() { - return 1; + public void onPostTick(long tick, boolean isServerSide) { + if (isServerSide) { + runMachine(tick); + } else { + doActivitySound(getActivitySoundLoop()); + } } - @Override - public long getInputAmperage() { - return 1; + /** + * Runs only on server side + * + * @param tick The current tick of the machine + */ + protected void runMachine(long tick) { + if (acceptsFuel() && isActive()) { + if (!consumeFuel()) { + stopMachine(); + return; + } + } + + if (hasThingsToDo()) { + markDirty(); + runningTick(tick); + } else { + if (tick % TICKS_BETWEEN_RECIPE_CHECKS == 0 || hasWorkJustBeenEnabled() || hasInventoryBeenModified()) { + if (isAllowedToWork()) { + wasEnabled = false; + if (checkRecipe()) { + setActive(true); + setSound(GregTechTileClientEvents.START_SOUND_LOOP, PROCESS_START_SOUND_INDEX); + updateSlots(); + markDirty(); + issueClientUpdate(); + } + } + } + } } - @Override - public long getInputVoltage() { - return 1; + /** + * Runs only on server side + * + * @param tick The current tick of the machine + */ + protected void runningTick(long tick) { + if (this instanceof PowerLogicHost) { + consumeEnergy(); + } + + if (maxProgressTime > 0 && ++progressTime >= maxProgressTime) { + progressTime = 0; + maxProgressTime = 0; + outputItems(); + outputFluids(); + if (isAllowedToWork()) { + if (!checkRecipe()) { + setActive(false); + issueClientUpdate(); + } + } + updateSlots(); + } + + if (this instanceof PollutionLogicHost && tick % POLLUTION_TICK == 0) { + doPollution(); + } + emitEnergy(); + } + + /** + * Runs only on server side + */ + protected boolean checkRecipe() { + if (!(this instanceof ProcessingLogicHost)) { + return false; + } + ProcessingLogic logic = ((ProcessingLogicHost) this).getProcessingLogic(); + logic.clear(); + boolean result = logic.setInputItems(inputInventory.getStacks().toArray(new ItemStack[0])) + .setCurrentOutputItems(outputInventory.getStacks().toArray(new ItemStack[0])).process(); + setDuration(logic.getDuration()); + setEut(logic.getEut()); + setItemOutputs(logic.getOutputItems()); + setFluidOutputs(logic.getOutputFluids()); + return result; + } + + /** + * Runs only on server side + */ + protected void doPollution() { + PollutionLogic logic = ((PollutionLogicHost) this).getPollutionLogic(); + + if (logic == null) { + return; + } + + GT_Pollution.addPollution(getWorld(), getXCoord() >> 4, getZCoord() >> 4, logic.getPollutionAmount()); + } + + /** + * Runs only on server side + */ + protected void emitEnergy() {} + + /** + * Runs only on server side + */ + protected void consumeEnergy() { + PowerLogic logic = ((PowerLogicHost) this).getPowerLogic(GT_Values.SIDE_UNKNOWN); + + if (logic == null) { + return; + } + + if (logic.removeEnergyUnsafe(eut)) { + stopMachine(); + } + } + + public void doSound(byte aIndex, double aX, double aY, double aZ) { + switch (aIndex) { + case PROCESS_START_SOUND_INDEX: + if (getProcessStartSound() != null) + GT_Utility.doSoundAtClient(getProcessStartSound(), getTimeBetweenProcessSounds(), 1.0F, aX, aY, aZ); + break; + case INTERRUPT_SOUND_INDEX: + GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_INTERRUPT_ONE, 100, 1.0F, aX, aY, aZ); + break; + } + } + + public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) { + if (aIndex == PROCESS_START_SOUND_INDEX) { + if (getProcessStartSound() != null) + GT_Utility.doSoundAtClient(getProcessStartSound(), getTimeBetweenProcessSounds(), 1.0F, aX, aY, aZ); + } + } + + protected ResourceLocation getProcessStartSound() { + return null; + } + + protected int getTimeBetweenProcessSounds() { + return 100; } - public boolean isEnergyInputSide(byte aSide) { + protected void doActivitySound(ResourceLocation activitySound) { + if (isActive() && activitySound != null) { + if (activitySoundLoop == null) { + activitySoundLoop = new GT_SoundLoop(activitySound, this, false, true); + Minecraft.getMinecraft().getSoundHandler().playSound(activitySoundLoop); + } + } else { + if (activitySoundLoop != null) { + activitySoundLoop = null; + } + } + } + + protected ResourceLocation getActivitySoundLoop() { + return null; + } + + protected void outputItems() { + if (itemsToOutput == null) { + return; + } + for (ItemStack item : itemsToOutput) { + int index = 0; + while (item != null && item.stackSize > 0 && index < outputInventory.getSlots()) { + item = outputInventory.insertItem(index++, item.copy(), false); + } + } + itemsToOutput = null; + } + + protected void outputFluids() { + if (fluidsToOutput == null) { + return; + } + for (FluidStack fluid : fluidsToOutput) { + tryToFillTanks(fluid, outputTanks); + } + } + + protected void tryToFillTanks(FluidStack fluid, FluidTankGT... tanks) { + for (FluidTankGT tank : tanks) { + if (tank.canFillAll(fluid)) { + tank.add(fluid.amount, fluid); + } + } + } + + public long getProgress() { + return progressTime; + } + + public long getMaxProgress() { + return maxProgressTime; + } + + public boolean increaseProgress(int aProgressAmountInTicks) { + progressTime += aProgressAmountInTicks; return true; } - public boolean isEnergyOutputSide(byte aSide) { + public boolean hasThingsToDo() { + return getMaxProgress() > 0; + } + + public boolean hasWorkJustBeenEnabled() { + return wasEnabled; + } + + public void enableWorking() { + wasEnabled = true; + canWork = true; + } + + public void disableWorking() { + canWork = false; + } + + public boolean wasShutdown() { + return powerShutDown; + } + + public boolean isAllowedToWork() { + return canWork; + } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } + + protected boolean isElectric() { + return isElectric; + } + + protected void setElectric(boolean isElectric) { + this.isElectric = isElectric; + } + + protected boolean isSteam() { + return isSteam; + } + + protected void setSteam(boolean isSteam) { + this.isSteam = isSteam; + } + + protected boolean acceptsFuel() { + return acceptsFuel; + } + + protected void setFuel(boolean acceptsFuel) { + this.acceptsFuel = acceptsFuel; + } + + protected boolean isWireless() { + return isWireless; + } + + protected void setWireless(boolean isWireless) { + this.isWireless = isWireless; + } + + protected boolean drainEut(long eut) { + return decreaseStoredEnergyUnits(eut, false); + } + + protected boolean generateEut(long eut) { + return increaseStoredEnergyUnits(eut, true); + } + + protected boolean isGenerator() { + return false; + } + + protected boolean consumeFuel() { + if (isActive() && burnTime <= 0) { + for (int i = 0; i < inputInventory.getSlots(); i++) { + if (inputInventory.getStackInSlot(i) != null) { + int checkBurnTime = TileEntityFurnace.getItemBurnTime(inputInventory.getStackInSlot(i)) / 10; + if (checkBurnTime <= 0) continue; + inputInventory.getStackInSlot(i).stackSize--; + burnTime = checkBurnTime; + totalBurnTime = checkBurnTime; + break; + } + } + updateSlots(); + } + + if (--burnTime < 0) { + burnTime = 0; + totalBurnTime = 0; + return false; + } + return true; } @Override - public boolean inputEnergyFrom(byte aSide) { - if (aSide == GT_Values.SIDE_UNKNOWN) return true; - if (aSide >= 0 && aSide < 6) { - if (isInvalid()) return false; - if (!getCoverInfoAtSide(aSide).letsEnergyIn()) return false; - if (isEnetInput()) return isEnergyInputSide(aSide); + protected void addDebugInfo(EntityPlayer player, int logLevel, ArrayList list) { + if (isElectric()) { + list.add( + "Energy: " + EnumChatFormatting.GOLD + + getUniversalEnergyStored() + + "/" + + getUniversalEnergyCapacity()); + } + + if (acceptsFuel()) { + list.add("Fuel: " + EnumChatFormatting.GOLD + burnTime + "/" + totalBurnTime); } - return false; } - @Override - public boolean outputsEnergyTo(byte aSide) { - if (aSide == GT_Values.SIDE_UNKNOWN) return true; - if (aSide >= 0 && aSide < 6) { - if (isInvalid()) return false; - if (!getCoverInfoAtSide(aSide).letsEnergyOut()) return false; - if (isEnetOutput()) return isEnergyOutputSide(aSide); + protected void stopMachine() { + progressTime = 0; + setActive(false); + disableWorking(); + setSound(GregTechTileClientEvents.STOP_SOUND_LOOP, INTERRUPT_SOUND_INDEX); + issueClientUpdate(); + } + + protected void updateSlots() { + for (int i = 0; i < inputInventory.getSlots(); i++) { + ItemStack item = inputInventory.getStackInSlot(i); + if (item != null && item.stackSize <= 0) { + inputInventory.setStackInSlot(i, null); + } } - return false; } - /* - * Inventory + /** + * Must always be a positive. If the multi generates Eu/t isGenerator() should be overridden to true */ + protected void setEut(long eut) { + if (eut < 0) { + eut = -eut; + } - @Override - public boolean hasInventoryBeenModified() { - // True if the input inventory has changed - return mInventoryChanged; + this.eut = eut; } - public void markOutputInventoryBeenModified() { - mOutputInventoryChanged = true; + protected void setDuration(long duration) { + if (duration < 0) { + duration = -duration; + } + + maxProgressTime = duration; } - public boolean hasOutputInventoryBeenModified() { - // True if the output inventory has changed - return mOutputInventoryChanged; + @Override + public int getBooleans() { + int booleans = 0; + if (isActive()) { + booleans |= ACTIVE; + } + return booleans; } @Override - public boolean isItemValidForSlot(int aSlot, ItemStack aStack) { - return false; + public void setBooleans(int booleans) { + if ((booleans & ACTIVE) == ACTIVE) { + setActive(true); + } + } + + protected boolean hasItemInput() { + return true; + } + + protected boolean hasItemOutput() { + return true; + } + + protected boolean hasFluidInput() { + return true; + } + + protected boolean hasFluidOutput() { + return true; + } + + protected void setItemOutputs(ItemStack... outputs) { + itemsToOutput = outputs; + } + + protected void setFluidOutputs(FluidStack... outputs) { + fluidsToOutput = outputs; } @Override - public int getInventoryStackLimit() { - return 64; + public void setSound(byte soundEvent, int soundEventValue) { + this.soundEvent = soundEvent; + this.soundEventValue = soundEventValue; + if (isClientSide()) { + switch (soundEventValue) { + case PROCESS_START_SOUND_INDEX: + if (getProcessStartSound() != null) GT_Utility.doSoundAtClient( + getProcessStartSound(), + getTimeBetweenProcessSounds(), + 1.0F, + getXCoord(), + getYCoord(), + getZCoord()); + break; + case INTERRUPT_SOUND_INDEX: + GT_Utility.doSoundAtClient( + SoundResource.IC2_MACHINES_INTERRUPT_ONE, + 100, + 1.0F, + getXCoord(), + getYCoord(), + getZCoord()); + break; + } + } } } diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java index 8eefc28a71..f5f36a7b0f 100644 --- a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockController.java @@ -15,12 +15,14 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IIcon; +import net.minecraft.util.StatCollector; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; @@ -36,20 +38,26 @@ import com.gtnewhorizon.structurelib.StructureLibAPI; import com.gtnewhorizon.structurelib.alignment.IAlignment; import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits; import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable; +import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing; import com.gtnewhorizon.structurelib.alignment.enumerable.Flip; import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation; import com.gtnewhorizon.structurelib.structure.IStructureDefinition; import com.gtnewhorizon.structurelib.structure.IStructureElement; +import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; import com.gtnewhorizon.structurelib.util.Vec3Impl; import com.gtnewhorizons.modularui.api.ModularUITextures; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; import com.gtnewhorizons.modularui.api.drawable.ItemDrawable; +import com.gtnewhorizons.modularui.api.drawable.UITexture; import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable; import com.gtnewhorizons.modularui.api.forge.ItemStackHandler; import com.gtnewhorizons.modularui.api.forge.ListItemHandler; import com.gtnewhorizons.modularui.api.screen.*; import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; import com.gtnewhorizons.modularui.common.widget.DrawableWidget; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget; import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; import com.gtnewhorizons.modularui.common.widget.Scrollable; @@ -61,48 +69,58 @@ import cpw.mods.fml.common.network.NetworkRegistry; import gnu.trove.list.TIntList; import gnu.trove.list.array.TIntArrayList; import gregtech.api.enums.GT_Values; +import gregtech.api.enums.GT_Values.NBT; import gregtech.api.enums.OrePrefixes; import gregtech.api.enums.TextureSet; +import gregtech.api.fluid.FluidTankGT; import gregtech.api.gui.modularui.GT_UITextures; import gregtech.api.interfaces.IDescribable; -import gregtech.api.interfaces.tileentity.IMachineProgress; +import gregtech.api.logic.PowerLogic; +import gregtech.api.logic.ProcessingLogic; +import gregtech.api.logic.interfaces.PowerLogicHost; +import gregtech.api.logic.interfaces.ProcessingLogicHost; import gregtech.api.multitileentity.MultiTileEntityContainer; import gregtech.api.multitileentity.MultiTileEntityRegistry; import gregtech.api.multitileentity.interfaces.IMultiBlockController; -import gregtech.api.multitileentity.interfaces.IMultiBlockFluidHandler; -import gregtech.api.multitileentity.interfaces.IMultiBlockInventory; import gregtech.api.multitileentity.interfaces.IMultiBlockPart; import gregtech.api.multitileentity.interfaces.IMultiTileEntity; import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_AddToolTips; import gregtech.api.multitileentity.machine.MultiTileBasicMachine; -import gregtech.api.multitileentity.multiblock.casing.AdvancedCasing; -import gregtech.api.multitileentity.multiblock.casing.InventoryUpgrade; +import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing; +import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing; import gregtech.api.objects.GT_ItemStack; import gregtech.api.util.GT_Multiblock_Tooltip_Builder; import gregtech.api.util.GT_Utility; +import gregtech.common.tileentities.casings.upgrade.InventoryUpgrade; -public abstract class MultiBlockController> extends MultiTileBasicMachine - implements IAlignment, IConstructable, IMultiBlockController, IDescribable, IMachineProgress, - IMultiBlockFluidHandler, IMultiBlockInventory, IMTE_AddToolTips { +public abstract class MultiBlockController> extends MultiTileBasicMachine implements + IAlignment, IConstructable, IMultiBlockController, IDescribable, IMTE_AddToolTips, ISurvivalConstructable { - private static final int TICKS_BETWEEN_RECIPE_CHECKS = 100; private static final Map tooltip = new ConcurrentHashMap<>(); - private final List mUpgradeCasings = new ArrayList(); + private final List upgradeCasings = new ArrayList<>(); + private final List functionalCasings = new ArrayList<>(); protected BuildState buildState = new BuildState(); protected Map multiBlockInputInventoryNames = new LinkedHashMap<>(); protected Map multiBlockOutputInventoryNames = new LinkedHashMap<>(); + protected Map multiBlockInputInventoryToTankLink = new LinkedHashMap<>(); protected Map multiBlockInputInventory = new LinkedHashMap<>(); protected Map multiBlockOutputInventory = new LinkedHashMap<>(); - protected int mMaxProgressTime = 0; - private int mProgressTime = 0; - private boolean mStructureOkay = false, mStructureChanged = false; - private boolean mWorks = true, mWorkUpdate = false, mWasShutdown = false, mActive = false, mSeparateInputs = true; - private ExtendedFacing mExtendedFacing = ExtendedFacing.DEFAULT; - private IAlignmentLimits mLimits = getInitialAlignmentLimits(); - private ItemStack[] mItemsToOutput; - private String mInventory; + protected Map multiBlockInputTankNames = new LinkedHashMap<>(); + protected Map multiBlockOutputTankNames = new LinkedHashMap<>(); + protected Map multiBlockInputTank = new LinkedHashMap<>(); + protected Map multiBlockOutputTank = new LinkedHashMap<>(); + + private boolean structureOkay = false, structureChanged = false; + private ExtendedFacing extendedFacing = ExtendedFacing.DEFAULT; + private IAlignmentLimits limits = getInitialAlignmentLimits(); + private String inventoryName; + private String tankName; + protected boolean separateInputs = false; + protected boolean voidExcess = false; + protected boolean batchMode = false; + protected boolean recipeLock = false; // A list of sides // Each side has a list of parts that have a cover that need to be ticked @@ -143,117 +161,95 @@ public abstract class MultiBlockController> ex *

* NOTE: If using `buildState` be sure to `startBuilding()` and either `endBuilding()` or `failBuilding()` */ - public abstract boolean checkMachine(); - - /** - * Checks the Recipe - */ - public abstract boolean checkRecipe(ItemStack aStack); + public boolean checkMachine() { + double sum = 0; + for (FunctionalCasing casing : functionalCasings) { + sum += casing.getPartTier(); + } + tier = (int) Math.floor(sum / functionalCasings.size()); + // Maximum Energy stores will have a cap of 2 minute work time of current voltage + return tier > 0; + } @Override - public void writeMultiTileNBT(NBTTagCompound aNBT) { - super.writeMultiTileNBT(aNBT); + public void writeMultiTileNBT(NBTTagCompound nbt) { + super.writeMultiTileNBT(nbt); - aNBT.setBoolean(NBT.STRUCTURE_OK, mStructureOkay); - aNBT.setByte(NBT.ROTATION, (byte) mExtendedFacing.getRotation().getIndex()); - aNBT.setByte(NBT.FLIP, (byte) mExtendedFacing.getFlip().getIndex()); + nbt.setBoolean(NBT.STRUCTURE_OK, structureOkay); + nbt.setByte(NBT.ROTATION, (byte) extendedFacing.getRotation().getIndex()); + nbt.setByte(NBT.FLIP, (byte) extendedFacing.getFlip().getIndex()); - saveUpgradeInventoriesToNBT(aNBT); - saveItemsToOutput(aNBT); + saveUpgradeInventoriesToNBT(nbt); } - private void saveUpgradeInventoriesToNBT(NBTTagCompound aNBT) { - final NBTTagList tListInputInvs = new NBTTagList(); - multiBlockInputInventory.forEach((tID, tInv) -> { - if (tID.equals("controller")) {} else { + private void saveUpgradeInventoriesToNBT(NBTTagCompound nbt) { + final NBTTagList inputInvList = new NBTTagList(); + multiBlockInputInventory.forEach((id, inv) -> { + if (!id.equals("controller")) { final NBTTagCompound tTag = new NBTTagCompound(); - tTag.setString(NBT.UPGRADE_INVENTORY_UUID, tID); - tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockInputInventoryNames.get(tID)); - tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, tInv.getSlots()); - writeInventory(tTag, tInv, NBT.INV_INPUT_LIST); - tListInputInvs.appendTag(tTag); + tTag.setString(NBT.UPGRADE_INVENTORY_UUID, id); + tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockInputInventoryNames.get(id)); + tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, inv.getSlots()); + writeInventory(tTag, inv, NBT.INV_INPUT_LIST); + inputInvList.appendTag(tTag); } }); - final NBTTagList tListOutputInvs = new NBTTagList(); - multiBlockOutputInventory.forEach((tID, tInv) -> { - if (tID.equals("controller")) {} else { + final NBTTagList outputInvList = new NBTTagList(); + multiBlockOutputInventory.forEach((id, inv) -> { + if (!id.equals("controller")) { final NBTTagCompound tTag = new NBTTagCompound(); - tTag.setString(NBT.UPGRADE_INVENTORY_UUID, tID); - tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockOutputInventoryNames.get(tID)); - tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, tInv.getSlots()); - writeInventory(tTag, tInv, NBT.INV_OUTPUT_LIST); - tListOutputInvs.appendTag(tTag); + tTag.setString(NBT.UPGRADE_INVENTORY_UUID, id); + tTag.setString(NBT.UPGRADE_INVENTORY_NAME, multiBlockOutputInventoryNames.get(id)); + tTag.setInteger(NBT.UPGRADE_INVENTORY_SIZE, inv.getSlots()); + writeInventory(tTag, inv, NBT.INV_OUTPUT_LIST); + outputInvList.appendTag(tTag); } }); - aNBT.setTag(NBT.UPGRADE_INVENTORIES_INPUT, tListInputInvs); - aNBT.setTag(NBT.UPGRADE_INVENTORIES_OUTPUT, tListOutputInvs); - } - - private void saveItemsToOutput(NBTTagCompound aNBT) { - final NBTTagList tList = new NBTTagList(); - for (int tSlot = 0; tSlot < mItemsToOutput.length; tSlot++) { - final ItemStack tStack = mItemsToOutput[tSlot]; - if (tStack != null) { - final NBTTagCompound tag = new NBTTagCompound(); - tag.setByte("s", (byte) tSlot); - tStack.writeToNBT(tag); - tList.appendTag(tag); - } - } - aNBT.setTag(NBT.ITEM_OUT, tList); + nbt.setTag(NBT.UPGRADE_INVENTORIES_INPUT, inputInvList); + nbt.setTag(NBT.UPGRADE_INVENTORIES_OUTPUT, outputInvList); } @Override - public void readMultiTileNBT(NBTTagCompound aNBT) { - super.readMultiTileNBT(aNBT); + public void readMultiTileNBT(NBTTagCompound nbt) { + super.readMultiTileNBT(nbt); // Multiblock inventories are a collection of inventories. The first inventory is the default internal // inventory, and the others are added by inventory extending blocks. - if (mInputInventory != null) multiBlockInputInventory.put("controller", mInputInventory); - if (mOutputInventory != null) multiBlockOutputInventory.put("controller", mOutputInventory); + if (inputInventory != null) multiBlockInputInventory.put("controller", inputInventory); + if (outputInventory != null) multiBlockOutputInventory.put("controller", outputInventory); - mStructureOkay = aNBT.getBoolean(NBT.STRUCTURE_OK); - mExtendedFacing = ExtendedFacing.of( + structureOkay = nbt.getBoolean(NBT.STRUCTURE_OK); + extendedFacing = ExtendedFacing.of( ForgeDirection.getOrientation(getFrontFacing()), - Rotation.byIndex(aNBT.getByte(NBT.ROTATION)), - Flip.byIndex(aNBT.getByte(NBT.FLIP))); - - loadUpgradeInventoriesFromNBT(aNBT); - loadItemsToOutput(aNBT); - } - - private void loadUpgradeInventoriesFromNBT(NBTTagCompound aNBT) { - final NBTTagList tListInput = aNBT.getTagList(NBT.UPGRADE_INVENTORIES_INPUT, 10); - for (int i = 0; i < tListInput.tagCount(); i++) { - final NBTTagCompound tNBT = tListInput.getCompoundTagAt(i); - String invUUID = tNBT.getString(NBT.UPGRADE_INVENTORY_UUID); - String invName = tNBT.getString(NBT.UPGRADE_INVENTORY_NAME); - int tInvSize = tNBT.getInteger(NBT.UPGRADE_INVENTORY_SIZE); - IItemHandlerModifiable tInv = new ItemStackHandler(tInvSize); - loadInventory(tNBT, tInv, NBT.INV_INPUT_LIST); - multiBlockInputInventory.put(invUUID, tInv); + Rotation.byIndex(nbt.getByte(NBT.ROTATION)), + Flip.byIndex(nbt.getByte(NBT.FLIP))); + + loadUpgradeInventoriesFromNBT(nbt); + } + + private void loadUpgradeInventoriesFromNBT(NBTTagCompound nbt) { + final NBTTagList listInputInventories = nbt.getTagList(NBT.UPGRADE_INVENTORIES_INPUT, 10); + for (int i = 0; i < listInputInventories.tagCount(); i++) { + final NBTTagCompound nbtInv = listInputInventories.getCompoundTagAt(i); + String invUUID = nbtInv.getString(NBT.UPGRADE_INVENTORY_UUID); + String invName = nbtInv.getString(NBT.UPGRADE_INVENTORY_NAME); + int invSize = nbtInv.getInteger(NBT.UPGRADE_INVENTORY_SIZE); + IItemHandlerModifiable inv = new ItemStackHandler(invSize); + loadInventory(nbtInv, inv, NBT.INV_INPUT_LIST); + multiBlockInputInventory.put(invUUID, inv); multiBlockInputInventoryNames.put(invUUID, invName); } - final NBTTagList tListOutput = aNBT.getTagList(NBT.UPGRADE_INVENTORIES_OUTPUT, 10); - for (int i = 0; i < tListOutput.tagCount(); i++) { - final NBTTagCompound tNBT = tListOutput.getCompoundTagAt(i); - String invUUID = tNBT.getString(NBT.UPGRADE_INVENTORY_UUID); - String invName = tNBT.getString(NBT.UPGRADE_INVENTORY_NAME); - int tInvSize = tNBT.getInteger(NBT.UPGRADE_INVENTORY_SIZE); - IItemHandlerModifiable tInv = new ItemStackHandler(tInvSize); - loadInventory(tNBT, tInv, NBT.INV_OUTPUT_LIST); - multiBlockOutputInventory.put(invUUID, tInv); - multiBlockOutputInventoryNames.put(invUUID, invName); - } - } - private void loadItemsToOutput(NBTTagCompound aNBT) { - final NBTTagList tList = aNBT.getTagList(NBT.ITEM_OUT, 10); - mItemsToOutput = new ItemStack[tList.tagCount()]; - for (int i = 0; i < tList.tagCount(); i++) { - final NBTTagCompound tNBT = tList.getCompoundTagAt(i); - final int tSlot = tNBT.getByte("s"); - if (tSlot >= 0 && tSlot < mItemsToOutput.length) mItemsToOutput[tSlot] = GT_Utility.loadItem(tNBT); + final NBTTagList listOutputInventories = nbt.getTagList(NBT.UPGRADE_INVENTORIES_OUTPUT, 10); + for (int i = 0; i < listOutputInventories.tagCount(); i++) { + final NBTTagCompound nbtInv = listOutputInventories.getCompoundTagAt(i); + String invUUID = nbtInv.getString(NBT.UPGRADE_INVENTORY_UUID); + String invName = nbtInv.getString(NBT.UPGRADE_INVENTORY_NAME); + int invSize = nbtInv.getInteger(NBT.UPGRADE_INVENTORY_SIZE); + IItemHandlerModifiable inv = new ItemStackHandler(invSize); + loadInventory(nbtInv, inv, NBT.INV_OUTPUT_LIST); + multiBlockOutputInventory.put(invUUID, inv); + multiBlockOutputInventoryNames.put(invUUID, invName); } } @@ -273,6 +269,7 @@ public abstract class MultiBlockController> ex @Override protected void addDebugInfo(EntityPlayer aPlayer, int aLogLevel, ArrayList tList) { + super.addDebugInfo(aPlayer, aLogLevel, tList); tList.add("Structure ok: " + checkStructure(false)); } @@ -286,19 +283,19 @@ public abstract class MultiBlockController> ex @Override public boolean checkStructure(boolean aForceReset) { - if (!isServerSide()) return mStructureOkay; + if (!isServerSide()) return structureOkay; // Only trigger an update if forced (from onPostTick, generally), or if the structure has changed - if ((mStructureChanged || aForceReset)) { - mStructureOkay = checkMachine(); + if ((structureChanged || aForceReset)) { + structureOkay = checkMachine(); } - mStructureChanged = false; - return mStructureOkay; + structureChanged = false; + return structureOkay; } @Override public void onStructureChange() { - mStructureChanged = true; + structureChanged = true; } public final boolean checkPiece(String piece, Vec3Impl offset) { @@ -329,7 +326,7 @@ public abstract class MultiBlockController> ex horizontalOffset, verticalOffset, depthOffset, - !mStructureOkay); + !structureOkay); } public final boolean buildPiece(String piece, ItemStack trigger, boolean hintsOnly, Vec3Impl offset) { @@ -353,6 +350,38 @@ public abstract class MultiBlockController> ex hintOnly); } + protected final int survivalBuildPiece(String piece, ItemStack trigger, Vec3Impl offset, int elementBudget, + ISurvivalBuildEnvironment env, boolean check) { + return survivalBuildPiece( + piece, + trigger, + offset.get0(), + offset.get1(), + offset.get2(), + elementBudget, + env, + check); + } + + protected final Integer survivalBuildPiece(String piece, ItemStack trigger, int horizontalOffset, + int verticalOffset, int depthOffset, int elementBudget, ISurvivalBuildEnvironment env, boolean check) { + return getCastedStructureDefinition().survivalBuild( + this, + trigger, + piece, + getWorld(), + getExtendedFacing(), + getXCoord(), + getYCoord(), + getZCoord(), + horizontalOffset, + verticalOffset, + depthOffset, + elementBudget, + env, + check); + } + @SuppressWarnings("unchecked") private IStructureDefinition> getCastedStructureDefinition() { return (IStructureDefinition>) getStructureDefinition(); @@ -360,16 +389,16 @@ public abstract class MultiBlockController> ex @Override public ExtendedFacing getExtendedFacing() { - return mExtendedFacing; + return extendedFacing; } @Override public void setExtendedFacing(ExtendedFacing newExtendedFacing) { - if (mExtendedFacing != newExtendedFacing) { + if (extendedFacing != newExtendedFacing) { onStructureChange(); - if (mStructureOkay) stopMachine(); - mExtendedFacing = newExtendedFacing; - mStructureOkay = false; + if (structureOkay) stopMachine(); + extendedFacing = newExtendedFacing; + structureOkay = false; if (isServerSide()) { StructureLibAPI.sendAlignment( this, @@ -423,9 +452,9 @@ public abstract class MultiBlockController> ex } @Override - public void onFirstTick(boolean aIsServerSide) { - super.onFirstTick(aIsServerSide); - if (aIsServerSide) { + public void onFirstTick(boolean isServerSide) { + super.onFirstTick(isServerSide); + if (isServerSide) { checkStructure(true); } else { StructureLibAPI.queryAlignment(this); @@ -451,57 +480,32 @@ public abstract class MultiBlockController> ex } @Override - public void onTick(long aTimer, boolean isServerSide) { - // Tick all covers! + public void onTick(long timer, boolean isServerSide) { if (!tickCovers()) { return; } } @Override - public void onPostTick(long aTick, boolean aIsServerSide) { - if (aIsServerSide) { - if (aTick % 600 == 5) { + public void onPostTick(long tick, boolean isServerSide) { + if (isServerSide) { + if (tick % 600 == 5) { clearSpecialLists(); // Recheck the structure every 30 seconds or so if (!checkStructure(false)) checkStructure(true); } - if (mStructureOkay) { - runMachine(aTick); + if (structureOkay) { + runMachine(tick); } else { stopMachine(); } - } - } - - protected void runMachine(long aTick) { - if (mMaxProgressTime > 0) { - markDirty(); - if (mMaxProgressTime > 0 && ++mProgressTime >= mMaxProgressTime) { - mProgressTime = 0; - mMaxProgressTime = 0; - outputItems(); - if (isAllowedToWork()) { - checkRecipe(); - } - } } else { - if (aTick % TICKS_BETWEEN_RECIPE_CHECKS == 0 || hasWorkJustBeenEnabled() || hasInventoryBeenModified()) { - if (isAllowedToWork()) { - if (checkRecipe()) { - markDirty(); - } - } - } + doActivitySound(getActivitySoundLoop()); } } - protected boolean checkRecipe() { - return checkRecipe(null); - } - protected void clearSpecialLists() { - mUpgradeCasings.clear(); + upgradeCasings.clear(); } @Override @@ -517,7 +521,7 @@ public abstract class MultiBlockController> ex @Override public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCoverID) { - return aSide != mFacing; + return aSide != facing; } @Override @@ -527,22 +531,22 @@ public abstract class MultiBlockController> ex @Override public IAlignmentLimits getAlignmentLimits() { - return mLimits; + return limits; } protected void setAlignmentLimits(IAlignmentLimits mLimits) { - this.mLimits = mLimits; + this.limits = mLimits; } // IMachineProgress @Override - public int getProgress() { - return mProgressTime; + public long getProgress() { + return progressTime; } @Override - public int getMaxProgress() { - return mMaxProgressTime; + public long getMaxProgress() { + return maxProgressTime; } @Override @@ -568,57 +572,16 @@ public abstract class MultiBlockController> ex return getMaxProgress() > 0; } - @Override - public boolean hasWorkJustBeenEnabled() { - return mWorkUpdate; - } - - @Override - public void enableWorking() { - if (!mWorks) mWorkUpdate = true; - mWorks = true; - mWasShutdown = false; - } - - @Override - public void disableWorking() { - mWorks = false; - } - - @Override - public boolean isAllowedToWork() { - return mWorks; - } - - @Override - public boolean isActive() { - return mActive; - } - - @Override - public void setActive(boolean aActive) { - mActive = aActive; - } - public boolean isSeparateInputs() { - return mSeparateInputs; + return separateInputs; } public void setSeparateInputs(boolean aSeparateInputs) { - mSeparateInputs = aSeparateInputs; - } - - @Override - public boolean wasShutdown() { - return mWasShutdown; + separateInputs = aSeparateInputs; } // End IMachineProgress - public void stopMachine() { - disableWorking(); - } - protected IAlignmentLimits getInitialAlignmentLimits() { return (d, r, f) -> !f.isVerticallyFliped(); } @@ -672,7 +635,13 @@ public abstract class MultiBlockController> ex } } - public IStructureElement addMultiTileCasing(int aRegistryID, int aBlockMeta, int aModes) { + public IStructureElement addMultiTileCasing(String registryName, int meta, int modes) { + MultiTileEntityRegistry registry = MultiTileEntityRegistry.getRegistry(registryName); + int registryID = Block.getIdFromBlock(registry.mBlock); + return addMultiTileCasing(registryID, meta, modes); + } + + public IStructureElement addMultiTileCasing(int registryID, int meta, int modes) { return new IStructureElement() { private final short[] DEFAULT = new short[] { 255, 255, 255, 0 }; @@ -684,17 +653,15 @@ public abstract class MultiBlockController> ex if (!(tileEntity instanceof MultiBlockPart)) return false; final MultiBlockPart part = (MultiBlockPart) tileEntity; - if (aRegistryID != part.getMultiTileEntityRegistryID() || aBlockMeta != part.getMultiTileEntityID()) + if (registryID != part.getMultiTileEntityRegistryID() || meta != part.getMultiTileEntityID()) return false; final IMultiBlockController tTarget = part.getTarget(false); if (tTarget != null && tTarget != MultiBlockController.this) return false; - part.setTarget(MultiBlockController.this, aModes); + part.setTarget(MultiBlockController.this, modes); - if (part instanceof AdvancedCasing) { - mUpgradeCasings.add((AdvancedCasing) part); - } + registerSpecialCasings(part); return true; } @@ -716,9 +683,9 @@ public abstract class MultiBlockController> ex @Override public boolean placeBlock(S t, World world, int x, int y, int z, ItemStack trigger) { - final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(aRegistryID); + final MultiTileEntityRegistry tRegistry = MultiTileEntityRegistry.getRegistry(registryID); final MultiTileEntityContainer tContainer = tRegistry - .getNewTileEntityContainer(world, x, y, z, aBlockMeta, null); + .getNewTileEntityContainer(world, x, y, z, meta, null); if (tContainer == null) { GT_FML_LOGGER.error("NULL CONTAINER"); return false; @@ -730,7 +697,7 @@ public abstract class MultiBlockController> ex } if (world.setBlock(x, y, z, tContainer.mBlock, 15 - tContainer.mBlockMetaData, 2)) { tContainer.setMultiTile(world, x, y, z); - ((MultiBlockPart) te).setTarget(MultiBlockController.this, aModes); + ((MultiBlockPart) te).setTarget(MultiBlockController.this, modes); registerSpecialCasings((MultiBlockPart) te); } @@ -744,9 +711,12 @@ public abstract class MultiBlockController> ex }; } - protected void registerSpecialCasings(MultiBlockPart aPart) { - if (aPart instanceof AdvancedCasing) { - mUpgradeCasings.add((AdvancedCasing) aPart); + protected void registerSpecialCasings(MultiBlockPart part) { + if (part instanceof UpgradeCasing) { + upgradeCasings.add((UpgradeCasing) part); + } + if (part instanceof FunctionalCasing) { + functionalCasings.add((FunctionalCasing) part); } } @@ -771,7 +741,7 @@ public abstract class MultiBlockController> ex final IFluidTank tTank = getFluidTankFillable(aPart, (byte) aDirection.ordinal(), aFluid); if (tTank == null) return 0; final int rFilledAmount = tTank.fill(aFluid, aDoFill); - if (rFilledAmount > 0 && aDoFill) mInventoryChanged = true; + if (rFilledAmount > 0 && aDoFill) hasInventoryChanged = true; return rFilledAmount; } @@ -823,108 +793,25 @@ public abstract class MultiBlockController> ex @Override public IFluidTank[] getFluidTanksForGUI(MultiBlockPart aPart) { - if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return mTanksInput; - if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return mTanksOutput; + if (aPart.modeSelected(MultiBlockPart.FLUID_IN)) return inputTanks; + if (aPart.modeSelected(MultiBlockPart.FLUID_OUT)) return outputTanks; return GT_Values.emptyFluidTank; } - /** - * Energy - MultiBlock related Energy behavior - */ - @Override - public boolean isUniversalEnergyStored(MultiBlockPart aPart, long aEnergyAmount) { - return getUniversalEnergyStored(aPart) >= aEnergyAmount; - } - - @Override - public long getUniversalEnergyStored(MultiBlockPart aPart) { - return Math.min(getUniversalEnergyStored(), getUniversalEnergyCapacity()); - } - + // #region Energy @Override - public long getUniversalEnergyCapacity(MultiBlockPart aPart) { - return getUniversalEnergyCapacity(); - } - - @Override - public long getOutputAmperage(MultiBlockPart aPart) { - return getOutputAmperage(); - } - - @Override - public long getOutputVoltage(MultiBlockPart aPart) { - return getOutputVoltage(); - } - - @Override - public long getInputAmperage(MultiBlockPart aPart) { - return getInputAmperage(); - } - - @Override - public long getInputVoltage(MultiBlockPart aPart) { - return getInputVoltage(); - } - - @Override - public boolean decreaseStoredEnergyUnits(MultiBlockPart aPart, long aEnergy, boolean aIgnoreTooLittleEnergy) { - return decreaseStoredEnergyUnits(aEnergy, aIgnoreTooLittleEnergy); - } - - @Override - public boolean increaseStoredEnergyUnits(MultiBlockPart aPart, long aEnergy, boolean aIgnoreTooMuchEnergy) { - return increaseStoredEnergyUnits(aEnergy, aIgnoreTooMuchEnergy); - } - - @Override - public boolean drainEnergyUnits(MultiBlockPart aPart, byte aSide, long aVoltage, long aAmperage) { - return drainEnergyUnits(aSide, aVoltage, aAmperage); - } - - @Override - public long injectEnergyUnits(MultiBlockPart aPart, byte aSide, long aVoltage, long aAmperage) { - return injectEnergyUnits(aSide, aVoltage, aAmperage); - } - - @Override - public long getAverageElectricInput(MultiBlockPart aPart) { - return getAverageElectricInput(); - } - - @Override - public long getAverageElectricOutput(MultiBlockPart aPart) { - return getAverageElectricOutput(); - } - - @Override - public long getStoredEU(MultiBlockPart aPart) { - return getStoredEU(); - } - - @Override - public long getEUCapacity(MultiBlockPart aPart) { - return getEUCapacity(); - } - - @Override - public boolean inputEnergyFrom(MultiBlockPart aPart, byte aSide) { - if (aSide == GT_Values.SIDE_UNKNOWN) return true; - if (aSide >= 0 && aSide < 6) { - if (isInvalid()) return false; - if (isEnetInput()) return isEnergyInputSide(aSide); + public PowerLogic getPowerLogic(IMultiBlockPart part, byte side) { + if (!(this instanceof PowerLogicHost)) { + return null; } - return false; - } - @Override - public boolean outputsEnergyTo(MultiBlockPart aPart, byte aSide) { - if (aSide == GT_Values.SIDE_UNKNOWN) return true; - if (aSide >= 0 && aSide < 6) { - if (isInvalid()) return false; - if (isEnetOutput()) return isEnergyOutputSide(aSide); + if (part.getFrontFacing() != side) { + return null; } - return false; + + return ((PowerLogicHost) this).getPowerLogic(side); } + // #endregion Energy /** * Item - MultiBlock related Item behaviour. @@ -985,7 +872,7 @@ public abstract class MultiBlockController> ex @Override public IItemHandlerModifiable getInventoryForGUI(MultiBlockPart aPart) { if (isServerSide()) { - for (AdvancedCasing tPart : mUpgradeCasings) { + for (UpgradeCasing tPart : upgradeCasings) { if (!(tPart instanceof InventoryUpgrade)) continue; tPart.issueClientUpdate(); } @@ -1087,7 +974,7 @@ public abstract class MultiBlockController> ex if (tInv == null) return false; final int tSlot = tInv.getRight(); - final IItemHandlerModifiable inv = tInv.getLeft();; + final IItemHandlerModifiable inv = tInv.getLeft(); return inv.getStackInSlot(tSlot) != null; // && allowPullStack(getBaseMetaTileEntity(), aIndex, (byte) aSide, // aStack); @@ -1243,33 +1130,115 @@ public abstract class MultiBlockController> ex return getInventoriesForInput().getStacks().toArray(new ItemStack[0]); } + protected ItemStack[] getAllOutputItems() { + return getInventoriesForOutput().getStacks().toArray(new ItemStack[0]); + } + protected Iterable> getItemInputsForEachInventory() { return multiBlockInputInventory.entrySet().stream() .map((entry) -> Pair.of(entry.getValue().getStacks().toArray(new ItemStack[0]), entry.getKey())) .collect(Collectors.toList()); } - protected void setItemOutputs(ItemStack[] aItemOutputs, String aInventory) { - mItemsToOutput = aItemOutputs; - mInventory = aInventory; + protected void setItemOutputs(String inventory, ItemStack... itemOutputs) { + itemsToOutput = itemOutputs; + inventoryName = inventory; } - private void outputItems() { - int index = 0; - if (mItemsToOutput == null) { + @Override + protected void setItemOutputs(ItemStack... outputs) { + super.setItemOutputs(outputs); + inventoryName = null; + } + + @Override + protected void outputItems() { + if (itemsToOutput == null) { return; } - if (mInventory != null) { - for (ItemStack tItem : mItemsToOutput) { - multiBlockOutputInventory.getOrDefault(mInventory, getInventoriesForOutput()) - .insertItem(index++, tItem.copy(), false); - } + + IItemHandlerModifiable inv; + if (inventoryName != null) { + inv = multiBlockOutputInventory.getOrDefault(inventoryName, getInventoriesForOutput()); } else { - for (ItemStack tItem : mItemsToOutput) { - getInventoriesForOutput().insertItem(index++, tItem.copy(), false); + inv = getInventoriesForOutput(); + } + for (ItemStack item : itemsToOutput) { + int index = 0; + while (item != null && item.stackSize > 0 && index < inv.getSlots()) { + item = inv.insertItem(index++, item.copy(), false); + } + } + itemsToOutput = null; + } + + protected void setFluidOutputs(String tank, FluidStack... fluidOuputs) { + fluidsToOutput = fluidOuputs; + tankName = tank; + } + + @Override + protected void setFluidOutputs(FluidStack... outputs) { + super.setFluidOutputs(outputs); + tankName = null; + } + + @Override + protected void outputFluids() { + if (fluidsToOutput == null) { + return; + } + + List tanks = new ArrayList<>(multiBlockOutputTank.values()); + for (FluidStack fluid : fluidsToOutput) { + int index = 0; + while (fluid != null && fluid.amount > 0 && index < tanks.size()) { + int filled = tanks.get(index++).fill(fluid, true); + fluid.amount -= filled; + } + } + } + + @Override + protected void updateSlots() { + IItemHandlerModifiable inv = getInventoriesForInput(); + for (int i = 0; i < inv.getSlots(); i++) { + if (inv.getStackInSlot(i).stackSize <= 0) { + inv.setStackInSlot(i, null); } } - mItemsToOutput = null; + } + + @Override + protected boolean checkRecipe() { + if (!(this instanceof ProcessingLogicHost)) { + return false; + } + ProcessingLogic logic = ((ProcessingLogicHost) this).getProcessingLogic(); + logic.clear(); + boolean result = false; + if (isSeparateInputs()) { + for (Pair inventory : getItemInputsForEachInventory()) { + IItemHandlerModifiable outputInventory = multiBlockOutputInventory + .getOrDefault(inventory.getLeft(), null); + result = logic.setInputItems(inventory.getLeft()) + .setCurrentOutputItems( + outputInventory != null ? outputInventory.getStacks().toArray(new ItemStack[0]) : null) + .process(); + if (result) { + inventoryName = inventory.getRight(); + break; + } + logic.clear(); + } + } else { + result = logic.setInputItems(getAllItemInputs()).setCurrentOutputItems(getAllOutputItems()).process(); + } + setDuration(logic.getDuration()); + setEut(logic.getEut()); + setItemOutputs(logic.getOutputItems()); + setFluidOutputs(logic.getOutputFluids()); + return result; } /* @@ -1283,7 +1252,19 @@ public abstract class MultiBlockController> ex @Override public ModularWindow createWindow(UIBuildContext buildContext) { System.out.println("MultiBlockController::createWindow"); - return super.createWindow(buildContext); + if (!useModularUI()) return null; + + buildContext.setValidator(getValidator()); + final ModularWindow.Builder builder = ModularWindow.builder(getGUIWidth(), getGUIHeight()); + builder.setBackground(getGUITextureSet().getMainBackground()); + builder.setGuiTint(getGUIColorization()); + if (doesBindPlayerInventory()) { + bindPlayerInventoryUI(builder, buildContext); + } + addUIWidgets(builder, buildContext); + addTitleToUI(builder); + addCoverTabs(builder, buildContext); + return builder.build(); } @Override @@ -1297,88 +1278,135 @@ public abstract class MultiBlockController> ex } @Override - public void addGregTechLogo(ModularWindow.Builder builder) { - builder.widget( - new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo()).setSize(17, 17).setPos(148, 60)); + public int getGUIHeight() { + return 192; + } + + protected Widget getGregTechLogo() { + return new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo()).setSize(17, 17); } @Override public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { if (isServerSide()) { - for (AdvancedCasing tPart : mUpgradeCasings) { + for (UpgradeCasing tPart : upgradeCasings) { if (!(tPart instanceof InventoryUpgrade)) continue; tPart.issueClientUpdate(); } } - builder.widget( - new TabContainer() - .setButtonSize( - 20, - 24) - .addTabButton( - new TabButton(0) - .setBackground( - false, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f)) - .setBackground( - true, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f)) - .addTooltip(getLocalName()).setPos(0, -20)) - .addTabButton( - new TabButton(1) - .setBackground( - false, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f)) - .setBackground( - true, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f)) - .setPos(20, -20)) - .addTabButton( - new TabButton(2) - .setBackground( - false, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f)) - .setBackground( - true, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f)) - .setPos(40, -20)) - .addTabButton( - new TabButton(3) - .setBackground( - false, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f)) - .setBackground( - true, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f)) - .setPos(60, -20)) - .addTabButton( - new TabButton(4) - .setBackground( - false, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f)) - .setBackground( - true, - ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f)) - .setPos(80, -20)) - .addPage( - new MultiChildWidget().addChild( - new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK) - .setPos(7, 4).setSize(160, 75))) - .addPage(new MultiChildWidget().addChild(getItemInventoryInputGUI())) - .addPage(new MultiChildWidget().addChild(getItemInventoryOutputGUI())) - .addPage(new MultiChildWidget().addChild(getFluidInventoryInputGUI())) - .addPage(new MultiChildWidget().addChild(getFluidInventoryOutputGUI()))) - .widget(new ItemDrawable(getStackForm(1)).asWidget().setSize(16, 16).setPos(2, -16)) - .widget(new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ITEM_IN).setSize(16, 16).setPos(22, -16)) - .widget( - new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ITEM_OUT).setSize(16, 16) - .setPos(42, -16)) - .widget( - new DrawableWidget().setDrawable(GT_UITextures.PICTURE_FLUID_IN).setSize(16, 16) - .setPos(62, -16)) - .widget( - new DrawableWidget().setDrawable(GT_UITextures.PICTURE_FLUID_OUT).setSize(16, 16) - .setPos(82, -16)); + int page = 0; + TabContainer tabs = new TabContainer().setButtonSize(20, 24); + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), + new ItemDrawable(getStackForm(1)).withFixedSize(16, 16).withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), + new ItemDrawable(getStackForm(1)).withFixedSize(16, 16).withOffset(2, 4)) + .addTooltip(getLocalName()).setPos(20 * (page - 1), -20)) + .addPage(createMainPage().setSize(getGUIWidth(), getGUIHeight())); + if (hasItemInput()) { + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), + GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16).withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_ITEM_IN.withFixedSize(16, 16).withOffset(2, 4)) + .setPos(20 * (page - 1), -20)) + .addPage( + new MultiChildWidget().addChild(getItemInventoryInputGUI()) + .addChild(getGregTechLogo().setPos(147, 86)) + .setSize(getGUIWidth(), getGUIHeight())); + } + + if (hasItemOutput()) { + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), + GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16).withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_ITEM_OUT.withFixedSize(16, 16).withOffset(2, 4)) + .setPos(20 * (page - 1), -20)) + .addPage( + new MultiChildWidget().addChild(getItemInventoryOutputGUI()) + .addChild(getGregTechLogo().setPos(147, 86)) + .setSize(getGUIWidth(), getGUIHeight())); + } + + if (hasFluidInput()) { + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), + GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16).withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_FLUID_IN.withFixedSize(16, 16).withOffset(2, 4)) + .setPos(20 * (page - 1), -20)) + .addPage( + new MultiChildWidget().addChild(getFluidInventoryInputGUI()) + .addChild(getGregTechLogo().setPos(147, 86)) + .setSize(getGUIWidth(), getGUIHeight())); + } + + if (hasFluidOutput()) { + tabs.addTabButton( + new TabButton(page++) + .setBackground( + false, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0, 1f, 0.5f), + GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16).withOffset(2, 4)) + .setBackground( + true, + ModularUITextures.VANILLA_TAB_TOP_START.getSubArea(0, 0.5f, 1f, 1f), + GT_UITextures.PICTURE_FLUID_OUT.withFixedSize(16, 16).withOffset(2, 4)) + .setPos(20 * (page - 1), -20)) + .addPage( + new MultiChildWidget().addChild(getFluidInventoryOutputGUI()) + .addChild(getGregTechLogo().setPos(147, 86)) + .setSize(getGUIWidth(), getGUIHeight())); + } + builder.widget(tabs); + } + + protected MultiChildWidget createMainPage() { + MultiChildWidget page = new MultiChildWidget(); + page.addChild( + new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK).setPos(7, 4).setSize(160, 75)) + .addChild(createButtons()); + return page; + } + + protected MultiChildWidget createButtons() { + MultiChildWidget buttons = new MultiChildWidget(); + buttons.setSize(16, 167).setPos(7, 86); + buttons.addChild(createPowerSwitchButton()) + .addChild(new FakeSyncWidget.BooleanSyncer(() -> isAllowedToWork(), val -> { + if (val) enableWorking(); + else disableWorking(); + })).addChild(createVoidExcessButton()) + .addChild(new FakeSyncWidget.BooleanSyncer(() -> voidExcess, val -> voidExcess = val)) + .addChild(createInputSeparationButton()) + .addChild(new FakeSyncWidget.BooleanSyncer(() -> separateInputs, val -> separateInputs = val)) + .addChild(createBatchModeButton()) + .addChild(new FakeSyncWidget.BooleanSyncer(() -> batchMode, val -> batchMode = val)) + .addChild(createLockToSingleRecipeButton()) + .addChild(new FakeSyncWidget.BooleanSyncer(() -> recipeLock, val -> recipeLock = val)); + + return buttons; } protected Widget getItemInventoryInputGUI() { @@ -1391,7 +1419,7 @@ public abstract class MultiBlockController> ex .widget(new SlotWidget(inv, rows * 4 + column).setPos(column * 18, rows * 18).setSize(18, 18)); } } - return scrollable.setSize(18 * 4 + 4, 18 * 4).setPos(52, 7); + return scrollable.setSize(18 * 4 + 4, 18 * 5).setPos(52, 7); } protected Widget getItemInventoryOutputGUI() { @@ -1404,7 +1432,7 @@ public abstract class MultiBlockController> ex .widget(new SlotWidget(inv, rows * 4 + column).setPos(column * 18, rows * 18).setSize(18, 18)); } } - return scrollable.setSize(18 * 4 + 4, 18 * 4).setPos(52, 7); + return scrollable.setSize(18 * 4 + 4, 18 * 5).setPos(52, 7); } protected IItemHandlerModifiable getInventoriesForInput() { @@ -1416,7 +1444,7 @@ public abstract class MultiBlockController> ex } protected Widget getFluidInventoryInputGUI() { - final IFluidTank[] tanks = mTanksInput; + final IFluidTank[] tanks = inputTanks; final Scrollable scrollable = new Scrollable().setVerticalScroll(); for (int rows = 0; rows * 4 < tanks.length; rows++) { final int columnsToMake = Math.min(tanks.length - rows * 4, 4); @@ -1429,7 +1457,7 @@ public abstract class MultiBlockController> ex } protected Widget getFluidInventoryOutputGUI() { - final IFluidTank[] tanks = mTanksOutput; + final IFluidTank[] tanks = outputTanks; final Scrollable scrollable = new Scrollable().setVerticalScroll(); for (int rows = 0; rows * 4 < tanks.length; rows++) { final int columnsToMake = Math.min(tanks.length - rows * 4, 4); @@ -1439,6 +1467,174 @@ public abstract class MultiBlockController> ex scrollable.widget(fluidSlot.setPos(column * 18, rows * 18).setSize(18, 18)); } } - return scrollable.setSize(18 * 4 + 4, 18 * 4).setPos(52, 7); + return scrollable.setSize(18 * 4 + 4, 18 * 5).setPos(52, 7); + } + + protected ButtonWidget createPowerSwitchButton() { + ButtonWidget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (isAllowedToWork()) { + disableWorking(); + } else { + enableWorking(); + } + }).setPlayClickSound(true); + button.setBackground(() -> { + List ret = new ArrayList<>(); + ret.add(GT_UITextures.BUTTON_STANDARD); + if (isAllowedToWork()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_POWER_SWITCH_OFF); + } + return ret.toArray(new IDrawable[0]); + }).setPos(144, 0).setSize(16, 16); + button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.power_switch")) + .setTooltipShowUpDelay(TOOLTIP_DELAY); + return button; + } + + protected ButtonWidget createVoidExcessButton() { + ButtonWidget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (isVoidExcessButtonEnabled()) { + voidExcess = !voidExcess; + } + }).setPlayClickSound(true); + button.setBackground(() -> { + List ret = new ArrayList<>(); + ret.add(GT_UITextures.BUTTON_STANDARD); + if (isVoidExcessButtonEnabled()) { + if (isVoidExcessEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF); + } + } else { + if (isVoidExcessEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_ON_DISABLED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_VOID_EXCESS_OFF_DISABLED); + } + } + return ret.toArray(new IDrawable[0]); + }).setPos(54, 0).setSize(16, 16); + button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.void_excess")) + .setTooltipShowUpDelay(TOOLTIP_DELAY); + return button; + } + + protected boolean isVoidExcessEnabled() { + return voidExcess; + } + + protected boolean isVoidExcessButtonEnabled() { + return true; + } + + protected ButtonWidget createInputSeparationButton() { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (isInputSeparationButtonEnabled()) { + separateInputs = !separateInputs; + } + }).setPlayClickSound(true).setBackground(() -> { + List ret = new ArrayList<>(); + ret.add(GT_UITextures.BUTTON_STANDARD); + if (isInputSeparationButtonEnabled()) { + if (isInputSeparationEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF); + } + } else { + if (isInputSeparationEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_ON_DISABLED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_INPUT_SEPARATION_OFF_DISABLED); + } + } + return ret.toArray(new IDrawable[0]); + }).setPos(36, 0).setSize(16, 16); + button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.input_separation")) + .setTooltipShowUpDelay(TOOLTIP_DELAY); + return (ButtonWidget) button; + } + + protected boolean isInputSeparationEnabled() { + return separateInputs; + } + + protected boolean isInputSeparationButtonEnabled() { + return true; + } + + protected ButtonWidget createBatchModeButton() { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (isBatchModeButtonEnabled()) { + batchMode = !batchMode; + } + }).setPlayClickSound(true).setBackground(() -> { + List ret = new ArrayList<>(); + ret.add(GT_UITextures.BUTTON_STANDARD); + if (isBatchModeButtonEnabled()) { + if (isBatchModeEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF); + } + } else { + if (isBatchModeEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_ON_DISABLED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_BATCH_MODE_OFF_DISABLED); + } + } + return ret.toArray(new IDrawable[0]); + }).setPos(18, 0).setSize(16, 16); + button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.batch_mode")) + .setTooltipShowUpDelay(TOOLTIP_DELAY); + return (ButtonWidget) button; + } + + protected boolean isBatchModeButtonEnabled() { + return true; + } + + protected boolean isBatchModeEnabled() { + return batchMode; + } + + protected ButtonWidget createLockToSingleRecipeButton() { + Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { + if (supportsSingleRecipeLocking()) { + recipeLock = !recipeLock; + } + }).setPlayClickSound(true).setBackground(() -> { + List ret = new ArrayList<>(); + ret.add(GT_UITextures.BUTTON_STANDARD); + if (supportsSingleRecipeLocking()) { + if (isRecipeLockingEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED); + } + } else { + if (isRecipeLockingEnabled()) { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_LOCKED_DISABLED); + } else { + ret.add(GT_UITextures.OVERLAY_BUTTON_RECIPE_UNLOCKED_DISABLED); + } + } + return ret.toArray(new IDrawable[0]); + }).setPos(0, 0).setSize(16, 16); + button.addTooltip(StatCollector.translateToLocal("GT5U.gui.button.lock_recipe")) + .setTooltipShowUpDelay(TOOLTIP_DELAY); + return (ButtonWidget) button; + } + + protected boolean supportsSingleRecipeLocking() { + return false; + } + + protected boolean isRecipeLockingEnabled() { + return recipeLock; } } diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java index 1c6c5a0e07..9d40732b74 100644 --- a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPart.java @@ -50,18 +50,21 @@ import gregtech.api.enums.GT_Values; import gregtech.api.enums.Textures; import gregtech.api.interfaces.IIconContainer; import gregtech.api.interfaces.ITexture; +import gregtech.api.logic.PowerLogic; +import gregtech.api.logic.interfaces.PowerLogicHost; import gregtech.api.multitileentity.MultiTileEntityRegistry; -import gregtech.api.multitileentity.base.BaseNontickableMultiTileEntity; +import gregtech.api.multitileentity.base.NonTickableMultiTileEntity; import gregtech.api.multitileentity.interfaces.IMultiBlockController; import gregtech.api.multitileentity.interfaces.IMultiBlockPart; import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_BreakBlock; import gregtech.api.multitileentity.interfaces.IMultiTileEntity.IMTE_HasModes; +import gregtech.api.net.GT_Packet_MultiTileEntity; import gregtech.api.render.TextureFactory; import gregtech.api.util.GT_Utility; import gregtech.common.covers.CoverInfo; -public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity - implements IMultiBlockPart, IMTE_BreakBlock, IMTE_HasModes { +public abstract class MultiBlockPart extends NonTickableMultiTileEntity + implements IMultiBlockPart, IMTE_BreakBlock, IMTE_HasModes, PowerLogicHost { public static final int NOTHING = 0, ENERGY_IN = B[0], ENERGY_OUT = B[1], FLUID_IN = B[2], FLUID_OUT = B[3], ITEM_IN = B[4], ITEM_OUT = B[5]; @@ -70,7 +73,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity Arrays.asList(NOTHING, ENERGY_IN, ENERGY_OUT, FLUID_IN, FLUID_OUT, ITEM_IN, ITEM_OUT)); protected ChunkCoordinates mTargetPos = null; - protected IMultiBlockController mTarget = null; + protected IMultiBlockController target = null; protected int mAllowedModes = NOTHING; // BITMASK - Modes allowed for this part protected byte mMode = 0; // Mode selected for this part @@ -99,10 +102,10 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity } public void setTarget(IMultiBlockController aTarget, int aAllowedModes) { - mTarget = aTarget; - mTargetPos = (mTarget == null ? null : mTarget.getCoords()); + target = aTarget; + mTargetPos = (target == null ? null : target.getCoords()); mAllowedModes = aAllowedModes; - if (mTarget != null) registerCovers(mTarget); + if (target != null) registerCovers(target); } @Override @@ -125,21 +128,22 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity public IMultiBlockController getTarget(boolean aCheckValidity) { if (mTargetPos == null) return null; - if (mTarget == null || mTarget.isDead()) { + if (target == null || target.isDead()) { if (worldObj.blockExists(mTargetPos.posX, mTargetPos.posY, mTargetPos.posZ)) { final TileEntity te = worldObj.getTileEntity(mTargetPos.posX, mTargetPos.posY, mTargetPos.posZ); if (te instanceof IMultiBlockController) { - mTarget = (IMultiBlockController) te; + target = (IMultiBlockController) te; // Register our covers with the controller - registerCovers(mTarget); + registerCovers(target); } else { mTargetPos = null; } } } if (aCheckValidity) { - return mTarget != null && mTarget.checkStructure(false) ? mTarget : null; - } else return mTarget; + return target != null && target.checkStructure(false) ? target : null; + } + return target; } public void registerCovers(IMultiBlockController controller) { @@ -218,6 +222,18 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity } } + @Override + public GT_Packet_MultiTileEntity getClientDataPacket() { + final GT_Packet_MultiTileEntity packet = super.getClientDataPacket(); + packet.setModes(getMode(), getAllowedModes()); + if (getTargetPos() != null) { + final ChunkCoordinates aTarget = getTargetPos(); + packet.setTargetPos(aTarget.posX, (short) aTarget.posY, aTarget.posZ); + } + packet.setInventoryIndex(getLockedInventoryIndex()); + return packet; + } + @Override public void setLockedInventoryIndex(int aIndex) { mLockedInventoryIndex = aIndex; @@ -305,7 +321,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity public void loadTextureNBT(NBTTagCompound aNBT) { // Loading the registry final String textureName = aNBT.getString(NBT.TEXTURE); - mTextures = new IIconContainer[] { + textures = new IIconContainer[] { new Textures.BlockIcons.CustomIcon("multitileentity/multiblockparts/" + textureName + "/bottom"), new Textures.BlockIcons.CustomIcon("multitileentity/multiblockparts/" + textureName + "/top"), new Textures.BlockIcons.CustomIcon("multitileentity/multiblockparts/" + textureName + "/side"), @@ -321,8 +337,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity // Loading an instance final TileEntity tCanonicalTileEntity = MultiTileEntityRegistry .getCanonicalTileEntity(getMultiTileEntityRegistryID(), getMultiTileEntityID()); - if (tCanonicalTileEntity instanceof MultiBlockPart) - mTextures = ((MultiBlockPart) tCanonicalTileEntity).mTextures; + if (tCanonicalTileEntity instanceof MultiBlockPart) textures = ((MultiBlockPart) tCanonicalTileEntity).textures; } @Override @@ -330,7 +345,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity // For normal parts - texture comes from BaseMTE; overlay based on current mode // TODO(MTE) - For Advanced parts they might come from somewhere else final ITexture baseTexture = TextureFactory.of(super.getTexture(aBlock, aSide, isActive, aRenderPass)); - if (mMode != 0 && aSide == mFacing) { + if (mMode != 0 && aSide == facing) { if (mMode == getModeOrdinal(ITEM_IN)) return new ITexture[] { baseTexture, TextureFactory.of(OVERLAY_PIPE_IN), TextureFactory.of(ITEM_IN_SIGN) }; if (mMode == getModeOrdinal(ITEM_OUT)) return new ITexture[] { baseTexture, @@ -418,7 +433,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity if (!modeSelected(FLUID_IN)) return 0; final byte aSide = (byte) aDirection.ordinal(); if (aDirection != ForgeDirection.UNKNOWN - && (aSide != mFacing || !coverLetsFluidIn(aSide, aFluidStack == null ? null : aFluidStack.getFluid()))) + && (aSide != facing || !coverLetsFluidIn(aSide, aFluidStack == null ? null : aFluidStack.getFluid()))) return 0; final IMultiBlockController controller = getTarget(true); return controller == null ? 0 : controller.fill(this, aDirection, aFluidStack, aDoFill); @@ -429,7 +444,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity if (!modeSelected(FLUID_OUT)) return null; final byte aSide = (byte) aDirection.ordinal(); if (aDirection != ForgeDirection.UNKNOWN - && (aSide != mFacing || !coverLetsFluidOut(aSide, aFluidStack == null ? null : aFluidStack.getFluid()))) + && (aSide != facing || !coverLetsFluidOut(aSide, aFluidStack == null ? null : aFluidStack.getFluid()))) return null; final IMultiBlockController controller = getTarget(true); return controller == null ? null : controller.drain(this, aDirection, aFluidStack, aDoDrain); @@ -443,7 +458,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity if (controller == null) return null; final FluidStack aFluidStack = controller.getDrainableFluid(aSide); if (aDirection != ForgeDirection.UNKNOWN - && (aSide != mFacing || !coverLetsFluidOut(aSide, aFluidStack == null ? null : aFluidStack.getFluid()))) + && (aSide != facing || !coverLetsFluidOut(aSide, aFluidStack == null ? null : aFluidStack.getFluid()))) return null; return controller.drain(this, aDirection, aAmountToDrain, aDoDrain); } @@ -452,8 +467,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity public boolean canFill(ForgeDirection aDirection, Fluid aFluid) { if (!modeSelected(FLUID_IN)) return false; final byte aSide = (byte) aDirection.ordinal(); - if (aDirection != ForgeDirection.UNKNOWN && (aSide != mFacing || !coverLetsFluidIn(aSide, aFluid))) - return false; + if (aDirection != ForgeDirection.UNKNOWN && (aSide != facing || !coverLetsFluidIn(aSide, aFluid))) return false; final IMultiBlockController controller = getTarget(true); return controller != null && controller.canFill(this, aDirection, aFluid); } @@ -462,7 +476,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity public boolean canDrain(ForgeDirection aDirection, Fluid aFluid) { if (!modeSelected(FLUID_OUT)) return false; final byte aSide = (byte) aDirection.ordinal(); - if (aDirection != ForgeDirection.UNKNOWN && (aSide != mFacing || !coverLetsFluidOut(aSide, aFluid))) + if (aDirection != ForgeDirection.UNKNOWN && (aSide != facing || !coverLetsFluidOut(aSide, aFluid))) return false; final IMultiBlockController controller = getTarget(true); return controller != null && controller.canDrain(this, aDirection, aFluid); @@ -471,7 +485,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity @Override public FluidTankInfo[] getTankInfo(ForgeDirection aDirection) { final byte aSide = (byte) aDirection.ordinal(); - if (!modeSelected(FLUID_IN, FLUID_OUT) || (aSide != SIDE_UNKNOWN && aSide != mFacing)) + if (!modeSelected(FLUID_IN, FLUID_OUT) || (aSide != SIDE_UNKNOWN && aSide != facing)) return GT_Values.emptyFluidTankInfo; final IMultiBlockController controller = getTarget(true); if (controller == null) return GT_Values.emptyFluidTankInfo; @@ -485,145 +499,25 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity return GT_Values.emptyFluidTankInfo; } - /** - * Energy - Depending on the part type - proxy to the multiblock controller, if we have one - */ - @Override - public boolean isEnetInput() { - return modeSelected(ENERGY_IN); - } - - @Override - public boolean isEnetOutput() { - return modeSelected(ENERGY_OUT); - } - - @Override - public boolean isUniversalEnergyStored(long aEnergyAmount) { - if (!modeSelected(ENERGY_OUT, ENERGY_IN)) return false; - final IMultiBlockController controller = getTarget(true); - return controller != null && controller.isUniversalEnergyStored(this, aEnergyAmount); - } - - @Override - public long getUniversalEnergyStored() { - if (!modeSelected(ENERGY_OUT, ENERGY_IN)) return 0; - final IMultiBlockController controller = getTarget(true); - return controller != null ? controller.getUniversalEnergyStored(this) : 0; - } + // #region Energy - Depending on the part type - proxy to the multiblock controller, if we have one @Override - public long getUniversalEnergyCapacity() { - if (!modeSelected(ENERGY_OUT, ENERGY_IN)) return 0; + public PowerLogic getPowerLogic(byte side) { final IMultiBlockController controller = getTarget(true); - return controller != null ? controller.getUniversalEnergyCapacity(this) : 0; + return controller.getPowerLogic(this, side); } @Override - public long getOutputAmperage() { - if (!modeSelected(ENERGY_OUT)) return 0; - final IMultiBlockController controller = getTarget(true); - return controller != null ? controller.getOutputAmperage(this) : 0; - } - - @Override - public long getOutputVoltage() { - if (!modeSelected(ENERGY_OUT)) return 0; - final IMultiBlockController controller = getTarget(true); - return controller != null ? controller.getOutputVoltage(this) : 0; - } - - @Override - public long getInputAmperage() { - if (!modeSelected(ENERGY_IN)) return 0; - final IMultiBlockController controller = getTarget(true); - return (controller != null && hasMode(ENERGY_IN)) ? controller.getInputAmperage(this) : 0; - } - - @Override - public long getInputVoltage() { - if (!modeSelected(ENERGY_IN)) return 0; - final IMultiBlockController controller = getTarget(true); - return (controller != null && hasMode(ENERGY_IN)) ? controller.getInputVoltage(this) : 0; - } - - @Override - public boolean decreaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooLittleEnergy) { - if (!modeSelected(ENERGY_OUT)) return false; - final IMultiBlockController controller = getTarget(true); - return controller != null && hasMode(ENERGY_OUT) - && controller.decreaseStoredEnergyUnits(this, aEnergy, aIgnoreTooLittleEnergy); - } - - @Override - public boolean increaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooMuchEnergy) { - if (!modeSelected(ENERGY_IN)) return false; - final IMultiBlockController controller = getTarget(true); - return controller != null && hasMode(ENERGY_IN) - && controller.increaseStoredEnergyUnits(this, aEnergy, aIgnoreTooMuchEnergy); - } - - @Override - public boolean drainEnergyUnits(byte aSide, long aVoltage, long aAmperage) { - if (!modeSelected(ENERGY_OUT) || (mFacing != SIDE_UNKNOWN && (mFacing != aSide || !coverLetsEnergyOut(aSide)))) - return false; - final IMultiBlockController controller = getTarget(true); - return controller != null && controller.drainEnergyUnits(this, aSide, aVoltage, aAmperage); - } - - @Override - public long injectEnergyUnits(byte aSide, long aVoltage, long aAmperage) { - if (!modeSelected(ENERGY_IN) || (mFacing != SIDE_UNKNOWN && (mFacing != aSide || !coverLetsEnergyIn(aSide)))) - return 0; - final IMultiBlockController controller = getTarget(true); - return controller != null ? controller.injectEnergyUnits(this, aSide, aVoltage, aAmperage) : 0; - } - - @Override - public long getAverageElectricInput() { - if (!modeSelected(ENERGY_IN)) return 0; - final IMultiBlockController controller = getTarget(true); - return controller != null ? controller.getAverageElectricInput(this) : 0; - } - - @Override - public long getAverageElectricOutput() { - if (!modeSelected(ENERGY_OUT)) return 0; - final IMultiBlockController controller = getTarget(true); - return controller != null ? controller.getAverageElectricOutput(this) : 0; - } - - @Override - public long getStoredEU() { - if (!modeSelected(ENERGY_OUT, ENERGY_IN)) return 0; - final IMultiBlockController controller = getTarget(true); - return controller != null ? controller.getStoredEU(this) : 0; - } - - @Override - public long getEUCapacity() { - if (!modeSelected(ENERGY_OUT, ENERGY_IN)) return 0; - final IMultiBlockController controller = getTarget(true); - return controller != null ? controller.getEUCapacity(this) : 0; - } - - @Override - public boolean inputEnergyFrom(byte aSide) { - if (!modeSelected(ENERGY_IN) || (mFacing != SIDE_UNKNOWN && (mFacing != aSide || !coverLetsEnergyIn(aSide)))) - return false; - final IMultiBlockController controller = getTarget(true); - return controller != null && controller.inputEnergyFrom(this, aSide); + public boolean isEnetInput() { + return modeSelected(ENERGY_IN); } @Override - public boolean outputsEnergyTo(byte aSide) { - if (!modeSelected(ENERGY_OUT) || (mFacing != SIDE_UNKNOWN && (mFacing != aSide || !coverLetsEnergyOut(aSide)))) - return false; - final IMultiBlockController controller = getTarget(true); - return controller != null && controller.outputsEnergyTo(this, aSide); + public boolean isEnetOutput() { + return modeSelected(ENERGY_OUT); } - // End Energy + // #endregion /** * Inventory - Depending on the part type - proxy to the multiblock controller, if we have one @@ -656,7 +550,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity @Override public int[] getAccessibleSlotsFromSide(int aSide) { - if (!modeSelected(ITEM_IN, ITEM_OUT) || (mFacing != SIDE_UNKNOWN && mFacing != aSide)) + if (!modeSelected(ITEM_IN, ITEM_OUT) || (facing != SIDE_UNKNOWN && facing != aSide)) return GT_Values.emptyIntArray; final IMultiBlockController controller = getTarget(true); return controller != null ? controller.getAccessibleSlotsFromSide(this, (byte) aSide) : GT_Values.emptyIntArray; @@ -665,7 +559,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity @Override public boolean canInsertItem(int aSlot, ItemStack aStack, int aSide) { if (!modeSelected(ITEM_IN, ITEM_OUT) - || (mFacing != SIDE_UNKNOWN && (mFacing != aSide || !coverLetsItemsIn((byte) aSide, aSlot)))) + || (facing != SIDE_UNKNOWN && (facing != aSide || !coverLetsItemsIn((byte) aSide, aSlot)))) return false; final IMultiBlockController controller = getTarget(true); return (controller != null && controller.canInsertItem(this, aSlot, aStack, (byte) aSide)); @@ -674,7 +568,7 @@ public abstract class MultiBlockPart extends BaseNontickableMultiTileEntity @Override public boolean canExtractItem(int aSlot, ItemStack aStack, int aSide) { if (!modeSelected(ITEM_IN, ITEM_OUT) - || (mFacing != SIDE_UNKNOWN && (mFacing != aSide || !coverLetsItemsOut((byte) aSide, aSlot)))) + || (facing != SIDE_UNKNOWN && (facing != aSide || !coverLetsItemsOut((byte) aSide, aSlot)))) return false; final IMultiBlockController controller = getTarget(true); return (controller != null && controller.canExtractItem(this, aSlot, aStack, (byte) aSide)); diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPowerController.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPowerController.java new file mode 100644 index 0000000000..0834c64b75 --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlockPowerController.java @@ -0,0 +1,44 @@ +package gregtech.api.multitileentity.multiblock.base; + +import net.minecraft.nbt.NBTTagCompound; + +import gregtech.api.enums.GT_Values; +import gregtech.api.logic.PowerLogic; +import gregtech.api.logic.interfaces.PowerLogicHost; + +public abstract class MultiBlockPowerController> extends MultiBlockController + implements PowerLogicHost { + + public MultiBlockPowerController() { + super(); + power = new PowerLogic().setType(PowerLogic.RECEIVER); + } + + protected PowerLogic power; + + @Override + public void writeMultiTileNBT(NBTTagCompound nbt) { + super.writeMultiTileNBT(nbt); + power.writeToNBT(nbt); + } + + @Override + public void readMultiTileNBT(NBTTagCompound nbt) { + super.readMultiTileNBT(nbt); + power.loadFromNBT(nbt); + } + + @Override + public PowerLogic getPowerLogic(byte side) { + return power; + } + + @Override + public boolean checkMachine() { + boolean result = super.checkMachine(); + power.setEnergyCapacity(GT_Values.V[tier] * 2 * 60 * 20); + power.setAmperage(2); + power.setMaxVoltage(GT_Values.V[tier]); + return result; + } +} diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlock_Stackable.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlock_Stackable.java index f40a993738..11d931433f 100644 --- a/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlock_Stackable.java +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/MultiBlock_Stackable.java @@ -4,7 +4,7 @@ import net.minecraft.item.ItemStack; import com.gtnewhorizon.structurelib.util.Vec3Impl; -public abstract class MultiBlock_Stackable> extends MultiBlockController { +public abstract class MultiBlock_Stackable> extends MultiBlockPowerController { protected static String STACKABLE_TOP = "STACKABLE_TOP"; protected static String STACKABLE_MIDDLE = "STACKABLE_MIDDLE"; @@ -103,6 +103,9 @@ public abstract class MultiBlock_Stackable> ex if (stackCount < getMinStacks()) return buildState.failBuilding(); buildState.addOffset(getAfterLastStackOffset()); - return checkPiece(STACKABLE_TOP, buildState.stopBuilding()); + if (!checkPiece(STACKABLE_TOP, buildState.stopBuilding())) { + return buildState.failBuilding(); + } + return super.checkMachine(); } } diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/WallShareablePart.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/WallShareablePart.java new file mode 100644 index 0000000000..a391f503dc --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/WallShareablePart.java @@ -0,0 +1,107 @@ +package gregtech.api.multitileentity.multiblock.base; + +import static gregtech.api.enums.GT_Values.ALL_VALID_SIDES; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ChunkCoordinates; + +import gregtech.api.multitileentity.interfaces.IMultiBlockController; + +public class WallShareablePart extends MultiBlockPart { + + protected List targetPositions = new ArrayList<>(); + protected List targets = new ArrayList<>(); + + @Override + public void setTarget(IMultiBlockController aTarget, int aAllowedModes) { + if (targets.size() > 1 || targetPositions.size() > 1) { + mAllowedModes = 0; + mMode = 0; + } else { + mAllowedModes = aAllowedModes; + } + + if (aTarget == null) { + return; + } + + targets.add(aTarget); + targetPositions.add(aTarget.getCoords()); + } + + @Override + public String getLockedInventory() { + issueClientUpdate(); + if (targets.size() > 1 || targetPositions.size() > 1) { + return null; + } + + IMultiBlockController controller = getTarget(false); + if (!getNameOfInventoryFromIndex(controller, mLockedInventoryIndex).equals(mLockedInventory)) { + mLockedInventory = getNameOfInventoryFromIndex(controller, mLockedInventoryIndex); + if (mLockedInventory.equals("all")) { + mLockedInventory = ""; + } + } + return mLockedInventory.equals("") ? null : mLockedInventory; + } + + @Override + public IMultiBlockController getTarget(boolean aCheckValidity) { + if (targets.size() > 1 || targetPositions.size() > 1 || targets.size() <= 0 || targetPositions.size() <= 0) { + return null; + } + + target = targets.get(0); + mTargetPos = targetPositions.get(0); + return super.getTarget(aCheckValidity); + } + + @Override + public String getTileEntityName() { + return "gt.multiTileEntity.casing.wallSharable"; + } + + @Override + public boolean breakBlock() { + for (ChunkCoordinates coordinates : targetPositions) { + IMultiBlockController target = getTarget(coordinates, false); + if (target == null) { + continue; + } + target.onStructureChange(); + } + return false; + } + + @Override + public void onBlockAdded() { + for (byte tSide : ALL_VALID_SIDES) { + final TileEntity te = getTileEntityAtSide(tSide); + if (te instanceof MultiBlockPart) { + final IMultiBlockController tController = ((MultiBlockPart) te).getTarget(false); + if (tController != null) tController.onStructureChange(); + } else if (te instanceof IMultiBlockController) { + ((IMultiBlockController) te).onStructureChange(); + } + } + } + + public IMultiBlockController getTarget(ChunkCoordinates coordinates, boolean aCheckValidity) { + IMultiBlockController target = null; + if (coordinates == null) return null; + if (worldObj.blockExists(coordinates.posX, coordinates.posY, coordinates.posZ)) { + final TileEntity te = worldObj.getTileEntity(coordinates.posX, coordinates.posY, coordinates.posZ); + if (te instanceof IMultiBlockController) { + target = (IMultiBlockController) te; + } + } + if (aCheckValidity) { + return target != null && target.checkStructure(false) ? target : null; + } + return target; + } +} diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/casing/AdvancedCasing.java b/src/main/java/gregtech/api/multitileentity/multiblock/casing/AdvancedCasing.java deleted file mode 100644 index 704cf9eb45..0000000000 --- a/src/main/java/gregtech/api/multitileentity/multiblock/casing/AdvancedCasing.java +++ /dev/null @@ -1,36 +0,0 @@ -package gregtech.api.multitileentity.multiblock.casing; - -import net.minecraft.nbt.NBTTagCompound; - -import gregtech.api.enums.GT_Values; -import gregtech.api.multitileentity.interfaces.IMultiBlockController; -import gregtech.api.multitileentity.multiblock.base.MultiBlockPart; - -public abstract class AdvancedCasing extends MultiBlockPart { - - protected int mTier = 0; - - @Override - public int getPartTier() { - return mTier; - } - - @Override - public void setTarget(IMultiBlockController aTarget, int aAllowedModes) { - super.setTarget(aTarget, aAllowedModes); - if (mTarget != null) customWork(mTarget); - } - - @Override - public void readMultiTileNBT(NBTTagCompound aNBT) { - super.readMultiTileNBT(aNBT); - mTier = aNBT.getInteger(GT_Values.NBT.TIER); - } - - @Override - public void writeMultiTileNBT(NBTTagCompound aNBT) { - super.writeMultiTileNBT(aNBT); - } - - protected abstract void customWork(IMultiBlockController aTarget); -} diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/casing/FunctionalCasing.java b/src/main/java/gregtech/api/multitileentity/multiblock/casing/FunctionalCasing.java new file mode 100644 index 0000000000..718e159d7a --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/multiblock/casing/FunctionalCasing.java @@ -0,0 +1,27 @@ +package gregtech.api.multitileentity.multiblock.casing; + +import net.minecraft.nbt.NBTTagCompound; + +import gregtech.api.enums.GT_Values; +import gregtech.api.multitileentity.multiblock.base.MultiBlockPart; + +public abstract class FunctionalCasing extends MultiBlockPart { + + private int tier = 0; + + @Override + public int getPartTier() { + return tier; + } + + @Override + public void readMultiTileNBT(NBTTagCompound nbt) { + super.readMultiTileNBT(nbt); + tier = nbt.getInteger(GT_Values.NBT.TIER); + } + + @Override + public void writeMultiTileNBT(NBTTagCompound nbt) { + super.writeMultiTileNBT(nbt); + } +} diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/casing/InventoryUpgrade.java b/src/main/java/gregtech/api/multitileentity/multiblock/casing/InventoryUpgrade.java deleted file mode 100644 index a0043bdf39..0000000000 --- a/src/main/java/gregtech/api/multitileentity/multiblock/casing/InventoryUpgrade.java +++ /dev/null @@ -1,94 +0,0 @@ -package gregtech.api.multitileentity.multiblock.casing; - -import java.util.UUID; - -import net.minecraft.nbt.NBTTagCompound; - -import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder; -import com.gtnewhorizons.modularui.api.screen.UIBuildContext; -import com.gtnewhorizons.modularui.common.widget.textfield.TextFieldWidget; - -import gregtech.api.enums.GT_Values.NBT; -import gregtech.api.multitileentity.interfaces.IMultiBlockController; - -public class InventoryUpgrade extends AdvancedCasing { - - public UUID mInventoryID; - public static final int INPUT = 0; - public static final int OUTPUT = 1; - public static final int BOTH = 2; - private String mInventoryName = "inventory"; - private int mInventorySize; - private int mType = BOTH; - - public String getInventoryName() { - return mInventoryName; - } - - public void setInventoryName(String aInventoryName) { - mInventoryName = aInventoryName; - } - - @Override - protected void customWork(IMultiBlockController aTarget) { - int tInvSize = mInventorySize; - if (mType == BOTH) { - tInvSize /= 2; - } - aTarget.registerInventory(mInventoryName, mInventoryID.toString(), tInvSize, mType); - } - - @Override - public String getTileEntityName() { - return "gt.multitileentity.multiblock.inventory"; - } - - @Override - public void readMultiTileNBT(NBTTagCompound aNBT) { - super.readMultiTileNBT(aNBT); - if (aNBT.hasKey(NBT.UPGRADE_INVENTORY_UUID)) { - mInventoryID = UUID.fromString(aNBT.getString(NBT.UPGRADE_INVENTORY_UUID)); - } else { - mInventoryID = UUID.randomUUID(); - } - mInventorySize = aNBT.getInteger(NBT.UPGRADE_INVENTORY_SIZE); - mInventoryName = aNBT.getString(NBT.UPGRADE_INVENTORY_NAME); - - } - - @Override - public void writeMultiTileNBT(NBTTagCompound aNBT) { - super.writeMultiTileNBT(aNBT); - aNBT.setString(NBT.UPGRADE_INVENTORY_UUID, mInventoryID.toString()); - aNBT.setString(NBT.UPGRADE_INVENTORY_NAME, mInventoryName); - } - - @Override - protected void onBaseTEDestroyed() { - super.onBaseTEDestroyed(); - unregisterInventories(); - } - - private void unregisterInventories() { - final IMultiBlockController controller = getTarget(false); - if (controller != null) { - controller.unregisterInventory(mInventoryName, mInventoryID.toString(), mType); - } - } - - @Override - public boolean hasGui(byte aSide) { - return true; - } - - @Override - public void addUIWidgets(Builder builder, UIBuildContext buildContext) { - builder.widget(new TextFieldWidget().setGetter(() -> mInventoryName).setSetter((val) -> { - mInventoryName = val; - final IMultiBlockController controller = getTarget(false); - if (controller != null) { - controller.changeInventoryName(mInventoryName, mInventoryID.toString(), mType); - } - }).setSize(100, 25).setPos(50, 30)); - } -} diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/casing/UpgradeCasing.java b/src/main/java/gregtech/api/multitileentity/multiblock/casing/UpgradeCasing.java new file mode 100644 index 0000000000..e3230eac02 --- /dev/null +++ b/src/main/java/gregtech/api/multitileentity/multiblock/casing/UpgradeCasing.java @@ -0,0 +1,31 @@ +package gregtech.api.multitileentity.multiblock.casing; + +import net.minecraft.nbt.NBTTagCompound; + +import gregtech.api.enums.GT_Values; +import gregtech.api.multitileentity.interfaces.IMultiBlockController; +import gregtech.api.multitileentity.multiblock.base.MultiBlockPart; + +public abstract class UpgradeCasing extends MultiBlockPart { + + protected int tier = 0; + + @Override + public int getPartTier() { + return tier; + } + + @Override + public void setTarget(IMultiBlockController aTarget, int aAllowedModes) { + super.setTarget(aTarget, aAllowedModes); + if (target != null) customWork(target); + } + + @Override + public void readMultiTileNBT(NBTTagCompound aNBT) { + super.readMultiTileNBT(aNBT); + tier = aNBT.getInteger(GT_Values.NBT.TIER); + } + + protected abstract void customWork(IMultiBlockController aTarget); +} diff --git a/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java b/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java index ffcc9d2a26..98f6f11aec 100644 --- a/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java +++ b/src/main/java/gregtech/api/net/GT_Packet_MultiTileEntity.java @@ -14,24 +14,28 @@ import gregtech.api.metatileentity.GregTechTileClientEvents; import gregtech.api.multitileentity.MultiTileEntityBlock; import gregtech.api.multitileentity.interfaces.IMultiBlockPart; import gregtech.api.multitileentity.interfaces.IMultiTileEntity; -import gregtech.api.multitileentity.multiblock.casing.InventoryUpgrade; +import gregtech.api.multitileentity.interfaces.IMultiTileMachine; +import gregtech.common.tileentities.casings.upgrade.InventoryUpgrade; import io.netty.buffer.ByteBuf; public class GT_Packet_MultiTileEntity extends GT_Packet_New { public static final int COVERS = B[0], REDSTONE = B[1], MODES = B[2], CONTROLLER = B[3], INVENTORY_INDEX = B[4], - INVENTORY_NAME = B[5]; + INVENTORY_NAME = B[5], BOOLEANS = B[6], SOUND = B[7]; private int features = 0; private int mX, mZ; private int mC0 = 0, mC1 = 0, mC2 = 0, mC3 = 0, mC4 = 0, mC5 = 0; private short mY, mID, mRID; - private byte mCommonData, mTexturePage, mUpdate, mRedstone, mColor; + private byte mCommonData, mRedstone, mColor; private ChunkCoordinates mTargetPos = null; private int mLockedInventoryIndex; private String mInventoryName; private int mInventoryLength; + private int booleans; + private byte soundEvent; + private int soundEventValue; // MultiBlockPart private byte mMode; @@ -95,6 +99,21 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New { mInventoryName = aInventoryName; } + /** + * + * @param boolToSync each bit of the integer will be a boolean. + */ + public void setBooleans(int boolToSync) { + features |= BOOLEANS; + this.booleans = boolToSync; + } + + public void setSoundEvent(byte soundEvent, int soundEventValue) { + features |= SOUND; + this.soundEvent = soundEvent; + this.soundEventValue = soundEventValue; + } + @Override public void encode(ByteBuf aOut) { // Features @@ -145,10 +164,13 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New { } } - if (false) { - aOut.writeByte(mTexturePage); - aOut.writeByte(mUpdate); - aOut.writeByte(mColor); + if ((features & BOOLEANS) == BOOLEANS) { + aOut.writeInt(booleans); + } + + if ((features & SOUND) == SOUND) { + aOut.writeByte(soundEvent); + aOut.writeInt(soundEventValue); } } @@ -202,6 +224,14 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New { packet.setInventoryName(tName); } + if ((packetFeatures & BOOLEANS) == BOOLEANS) { + packet.setBooleans(aData.readInt()); + } + + if ((packetFeatures & SOUND) == SOUND) { + packet.setSoundEvent(aData.readByte(), aData.readInt()); + } + return packet; } @@ -246,6 +276,16 @@ public class GT_Packet_MultiTileEntity extends GT_Packet_New { invUpg.setInventoryName(mInventoryName); } + if ((features & BOOLEANS) == BOOLEANS && mte instanceof IMultiTileMachine) { + final IMultiTileMachine machine = (IMultiTileMachine) mte; + machine.setBooleans(booleans); + } + + if ((features & SOUND) == SOUND && mte instanceof IMultiTileMachine) { + final IMultiTileMachine machine = (IMultiTileMachine) mte; + machine.setSound(soundEvent, soundEventValue); + } + } } catch (Exception e) { GT_Mod.GT_FML_LOGGER.error( -- cgit