diff options
author | Martin Robertz <dream-master@gmx.net> | 2021-11-17 18:00:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-17 18:00:30 +0100 |
commit | 1dd66efceca26d9931010adb24932bba408ca630 (patch) | |
tree | b2a778c8108323b32ead067a1714ca0e99cf438e /src/main/java/gregtech | |
parent | 9c933933f1d5e99fc618d2e6d5f07238ccb51ba3 (diff) | |
parent | c696e261ab826d711a09622aacff841a01cfeb2a (diff) | |
download | GT5-Unofficial-1dd66efceca26d9931010adb24932bba408ca630.tar.gz GT5-Unofficial-1dd66efceca26d9931010adb24932bba408ca630.tar.bz2 GT5-Unofficial-1dd66efceca26d9931010adb24932bba408ca630.zip |
Merge branch 'experimental' into lock-single-recipe
Diffstat (limited to 'src/main/java/gregtech')
41 files changed, 2621 insertions, 707 deletions
diff --git a/src/main/java/gregtech/GT_Mod.java b/src/main/java/gregtech/GT_Mod.java index 864ef31c8c..fc7b17e0c6 100644 --- a/src/main/java/gregtech/GT_Mod.java +++ b/src/main/java/gregtech/GT_Mod.java @@ -115,7 +115,7 @@ import static gregtech.api.enums.GT_Values.MOD_ID_FR; " after:TConstruct;" + " after:Translocator;") public class GT_Mod implements IGT_Mod { - public static final int VERSION = 509, SUBVERSION = 33; + public static final int VERSION = 509, SUBVERSION = 39; public static final int TOTAL_VERSION = calculateTotalGTVersion(VERSION, SUBVERSION); public static final int REQUIRED_IC2 = 624; @Mod.Instance("gregtech") @@ -286,6 +286,7 @@ public class GT_Mod implements IGT_Mod { GT_Values.debugBlockMiner = tMainConfig.get(aTextGeneral, "debugBlockMiner", false).getBoolean(false); GT_Values.debugBlockPump = tMainConfig.get(aTextGeneral, "debugBlockPump", false).getBoolean(false); GT_Values.debugEntityCramming = tMainConfig.get(aTextGeneral, "debugEntityCramming", false).getBoolean(false); + GT_Values.debugWorldData = tMainConfig.get(aTextGeneral, "debugWorldData", false).getBoolean(false); GT_Values.oreveinPercentage = tMainConfig.get(aTextGeneral, "oreveinPercentage_100", 100).getInt(100); GT_Values.oreveinAttempts = tMainConfig.get(aTextGeneral, "oreveinAttempts_64", 64).getInt(64); GT_Values.oreveinMaxPlacementAttempts = tMainConfig.get(aTextGeneral, "oreveinMaxPlacementAttempts_8", 8).getInt(8); diff --git a/src/main/java/gregtech/api/GregTech_API.java b/src/main/java/gregtech/api/GregTech_API.java index fe48f6506f..ff875c4884 100644 --- a/src/main/java/gregtech/api/GregTech_API.java +++ b/src/main/java/gregtech/api/GregTech_API.java @@ -113,7 +113,7 @@ public class GregTech_API { /** * The List of Cover Behaviors for the Covers */ - public static final Map<GT_ItemStack, GT_CoverBehavior> sCoverBehaviors = new ConcurrentHashMap<>(); + public static final Map<GT_ItemStack, GT_CoverBehaviorBase<?>> sCoverBehaviors = new ConcurrentHashMap<>(); /** * The List of Circuit Behaviors for the Redstone Circuit Block */ @@ -615,6 +615,10 @@ public class GregTech_API { } public static void registerCover(ItemStack aStack, ITexture aCover, GT_CoverBehavior aBehavior) { + registerCover(aStack, aCover, (GT_CoverBehaviorBase<?>) aBehavior); + } + + public static void registerCover(ItemStack aStack, ITexture aCover, GT_CoverBehaviorBase<?> aBehavior) { if (!sCovers.containsKey(new GT_ItemStack(aStack))) sCovers.put(new GT_ItemStack(aStack), aCover == null || !aCover.isValidTexture() ? Textures.BlockIcons.ERROR_RENDERING[0] : aCover); if (aBehavior != null) @@ -622,6 +626,10 @@ public class GregTech_API { } public static void registerCoverBehavior(ItemStack aStack, GT_CoverBehavior aBehavior) { + registerCoverBehavior(aStack, (GT_CoverBehaviorBase<?>) aBehavior); + } + + public static void registerCoverBehavior(ItemStack aStack, GT_CoverBehaviorBase<?> aBehavior) { sCoverBehaviors.put(new GT_ItemStack(aStack), aBehavior == null ? sDefaultBehavior : aBehavior); } @@ -631,6 +639,15 @@ public class GregTech_API { * @param aBehavior can be null */ public static void registerCover(Collection<ItemStack> aStackList, ITexture aCover, GT_CoverBehavior aBehavior) { + registerCover(aStackList, aCover, aBehavior); + } + + /** + * Registers multiple Cover Items. I use that for the OreDict Functionality. + * + * @param aBehavior can be null + */ + public static void registerCover(Collection<ItemStack> aStackList, ITexture aCover, GT_CoverBehaviorBase<?> aBehavior) { if (aCover.isValidTexture()) aStackList.forEach(tStack -> GregTech_API.registerCover(tStack, aCover, aBehavior)); } @@ -638,10 +655,24 @@ public class GregTech_API { /** * returns a Cover behavior, guaranteed to not return null after preload */ + @Deprecated public static GT_CoverBehavior getCoverBehavior(ItemStack aStack) { if (aStack == null || aStack.getItem() == null) return sNoBehavior; - GT_CoverBehavior rCover = sCoverBehaviors.get(new GT_ItemStack(aStack)); + GT_CoverBehaviorBase<?> rCover = sCoverBehaviors.get(new GT_ItemStack(aStack)); + if (!(rCover instanceof GT_CoverBehavior) || rCover == null) + return sDefaultBehavior; + return (GT_CoverBehavior) rCover; + } + + /** + * returns a Cover behavior, guaranteed to not return null after preload + * @return + */ + public static GT_CoverBehaviorBase<?> getCoverBehaviorNew(ItemStack aStack) { + if (aStack == null || aStack.getItem() == null) + return sNoBehavior; + GT_CoverBehaviorBase<?> rCover = sCoverBehaviors.get(new GT_ItemStack(aStack)); if (rCover == null) return sDefaultBehavior; return rCover; @@ -650,6 +681,7 @@ public class GregTech_API { /** * returns a Cover behavior, guaranteed to not return null */ + @Deprecated public static GT_CoverBehavior getCoverBehavior(int aStack) { if (aStack == 0) return sNoBehavior; @@ -657,6 +689,15 @@ public class GregTech_API { } /** + * returns a Cover behavior, guaranteed to not return null + */ + public static GT_CoverBehaviorBase<?> getCoverBehaviorNew(int aStack) { + if (aStack == 0) + return sNoBehavior; + return getCoverBehaviorNew(GT_Utility.intToStack(aStack)); + } + + /** * Register a Wrench to be usable on GregTech Machines. * The Wrench MUST have some kind of Durability unlike certain Buildcraft Wrenches. * <p/> diff --git a/src/main/java/gregtech/api/enums/GT_Values.java b/src/main/java/gregtech/api/enums/GT_Values.java index f30360ca58..6505c34423 100644 --- a/src/main/java/gregtech/api/enums/GT_Values.java +++ b/src/main/java/gregtech/api/enums/GT_Values.java @@ -272,6 +272,10 @@ public class GT_Values { */ public static boolean debugEntityCramming = false; /** + * Debug parameter for {@link gregtech.api.util.GT_ChunkAssociatedData} + */ + public static boolean debugWorldData = false; + /** * Number of ticks between sending sound packets to clients for electric machines. Default is 1.5 seconds. Trying to mitigate lag and FPS drops. */ public static int ticksBetweenSounds = 30; diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiIconCheckButton.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiIconCheckButton.java index 010ac78654..e7b6b9971d 100644 --- a/src/main/java/gregtech/api/gui/widgets/GT_GuiIconCheckButton.java +++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiIconCheckButton.java @@ -3,13 +3,22 @@ package gregtech.api.gui.widgets; import gregtech.api.interfaces.IGuiScreen; public class GT_GuiIconCheckButton extends GT_GuiIconButton { - private GT_GuiIcon checkedIcon, normalIcon; + private final GT_GuiIcon checkedIcon; + private final GT_GuiIcon normalIcon; + private final String checkedTooltip; + private final String normalTooltip; private boolean checked = false; public GT_GuiIconCheckButton(IGuiScreen gui, int id, int x, int y, GT_GuiIcon checkedIcon, GT_GuiIcon normalIcon) { + this(gui, id, x, y, checkedIcon, normalIcon, null, null); + } + + public GT_GuiIconCheckButton(IGuiScreen gui, int id, int x, int y, GT_GuiIcon checkedIcon, GT_GuiIcon normalIcon, String checkedTooltip, String normalTooltip) { super(gui, id, x, y, normalIcon); this.checkedIcon = checkedIcon; this.normalIcon = normalIcon; + this.checkedTooltip = checkedTooltip; + this.normalTooltip = normalTooltip; } @Override @@ -27,6 +36,7 @@ public class GT_GuiIconCheckButton extends GT_GuiIconButton { public void setChecked(boolean checked) { super.setIcon(checked ? checkedIcon : normalIcon); + super.setTooltipText(checked ? checkedTooltip : normalTooltip); this.checked = checked; } } diff --git a/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntityItemPipe.java b/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntityItemPipe.java index f136f4f32b..90933b501f 100644 --- a/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntityItemPipe.java +++ b/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntityItemPipe.java @@ -59,7 +59,7 @@ public interface IMetaTileEntityItemPipe extends IMetaTileEntity { continue; j = GT_Utility.getOppositeSide(i); if (aSuckItems) { - if (aBaseMetaTileEntity.getCoverBehaviorAtSide(i).letsItemsIn(i, aBaseMetaTileEntity.getCoverIDAtSide(i), aBaseMetaTileEntity.getCoverDataAtSide(i), -2, aBaseMetaTileEntity)) { + if (aBaseMetaTileEntity.getCoverBehaviorAtSideNew(i).letsItemsIn(i, aBaseMetaTileEntity.getCoverIDAtSide(i), aBaseMetaTileEntity.getComplexCoverDataAtSide(i), -2, aBaseMetaTileEntity)) { IGregTechTileEntity tItemPipe = aBaseMetaTileEntity.getIGregTechTileEntityAtSide(i); if (aBaseMetaTileEntity.getColorization() >= 0) { byte tColor = tItemPipe.getColorization(); @@ -69,13 +69,13 @@ public interface IMetaTileEntityItemPipe extends IMetaTileEntity { } if (tItemPipe instanceof BaseMetaPipeEntity) { IMetaTileEntity tMetaTileEntity = tItemPipe.getMetaTileEntity(); - if (tMetaTileEntity instanceof IMetaTileEntityItemPipe && tItemPipe.getCoverBehaviorAtSide(j).letsItemsOut(j, tItemPipe.getCoverIDAtSide(j), tItemPipe.getCoverDataAtSide(j), -2, tItemPipe)) { + if (tMetaTileEntity instanceof IMetaTileEntityItemPipe && tItemPipe.getCoverBehaviorAtSideNew(j).letsItemsOut(j, tItemPipe.getCoverIDAtSide(j), tItemPipe.getComplexCoverDataAtSide(j), -2, tItemPipe)) { scanPipes((IMetaTileEntityItemPipe) tMetaTileEntity, aMap, aStep, aSuckItems, aIgnoreCapacity); } } } } else { - if (aBaseMetaTileEntity.getCoverBehaviorAtSide(i).letsItemsOut(i, aBaseMetaTileEntity.getCoverIDAtSide(i), aBaseMetaTileEntity.getCoverDataAtSide(i), -2, aBaseMetaTileEntity)) { + if (aBaseMetaTileEntity.getCoverBehaviorAtSideNew(i).letsItemsOut(i, aBaseMetaTileEntity.getCoverIDAtSide(i), aBaseMetaTileEntity.getComplexCoverDataAtSide(i), -2, aBaseMetaTileEntity)) { IGregTechTileEntity tItemPipe = aBaseMetaTileEntity.getIGregTechTileEntityAtSide(i); if (tItemPipe != null) { if (aBaseMetaTileEntity.getColorization() >= 0) { @@ -86,7 +86,7 @@ public interface IMetaTileEntityItemPipe extends IMetaTileEntity { } if (tItemPipe instanceof BaseMetaPipeEntity) { IMetaTileEntity tMetaTileEntity = tItemPipe.getMetaTileEntity(); - if (tMetaTileEntity instanceof IMetaTileEntityItemPipe && tItemPipe.getCoverBehaviorAtSide(j).letsItemsIn(j, tItemPipe.getCoverIDAtSide(j), tItemPipe.getCoverDataAtSide(j), -2, tItemPipe)) { + if (tMetaTileEntity instanceof IMetaTileEntityItemPipe && tItemPipe.getCoverBehaviorAtSideNew(j).letsItemsIn(j, tItemPipe.getCoverIDAtSide(j), tItemPipe.getComplexCoverDataAtSide(j), -2, tItemPipe)) { scanPipes((IMetaTileEntityItemPipe) tMetaTileEntity, aMap, aStep, aSuckItems, aIgnoreCapacity); } } diff --git a/src/main/java/gregtech/api/interfaces/tileentity/ICoverable.java b/src/main/java/gregtech/api/interfaces/tileentity/ICoverable.java index 560d47c595..ebfae9d90e 100644 --- a/src/main/java/gregtech/api/interfaces/tileentity/ICoverable.java +++ b/src/main/java/gregtech/api/interfaces/tileentity/ICoverable.java @@ -1,6 +1,9 @@ package gregtech.api.interfaces.tileentity; import gregtech.api.util.GT_CoverBehavior; +import gregtech.api.util.GT_CoverBehaviorBase; +import gregtech.api.util.ISerializableObject; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; public interface ICoverable extends IRedstoneTileEntity, IHasInventory, IBasicEnergyContainer { @@ -10,20 +13,36 @@ public interface ICoverable extends IRedstoneTileEntity, IHasInventory, IBasicEn boolean dropCover(byte aSide, byte aDroppedSide, boolean aForced); + @Deprecated void setCoverDataAtSide(byte aSide, int aData); + default void setCoverDataAtSide(byte aSide, ISerializableObject aData) { + if (aData instanceof ISerializableObject.LegacyCoverData) + setCoverDataAtSide(aSide, ((ISerializableObject.LegacyCoverData) aData).get()); + } + void setCoverIDAtSide(byte aSide, int aID); void setCoverItemAtSide(byte aSide, ItemStack aCover); + @Deprecated int getCoverDataAtSide(byte aSide); + default ISerializableObject getComplexCoverDataAtSide(byte aSide) { + return new ISerializableObject.LegacyCoverData(getCoverDataAtSide(aSide)); + } + int getCoverIDAtSide(byte aSide); ItemStack getCoverItemAtSide(byte aSide); + @Deprecated GT_CoverBehavior getCoverBehaviorAtSide(byte aSide); + default GT_CoverBehaviorBase<?> getCoverBehaviorAtSideNew(byte aSide) { + return getCoverBehaviorAtSide(aSide); + } + /** * For use by the regular MetaTileEntities. Returns the Cover Manipulated input Redstone. * Don't use this if you are a Cover Behavior. Only for MetaTileEntities. @@ -46,4 +65,13 @@ public interface ICoverable extends IRedstoneTileEntity, IHasInventory, IBasicEn * Receiving a packet with cover data. */ void receiveCoverData(byte coverSide, int coverID, int coverData); + + /** + * Receiving a packet with cover data. + * @param aPlayer the player who made the change + */ + default void receiveCoverData(byte aCoverSide, int aCoverID, ISerializableObject aCoverData, EntityPlayerMP aPlayer) { + if (aCoverData instanceof ISerializableObject.LegacyCoverData) + receiveCoverData(aCoverSide, aCoverID, ((ISerializableObject.LegacyCoverData) aCoverData).get()); + } } diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java index c2465c1a53..475bee8eb9 100644 --- a/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java +++ b/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java @@ -1,5 +1,14 @@ package gregtech.api.metatileentity; +import static gregtech.GT_Mod.GT_FML_LOGGER; +import static gregtech.api.enums.GT_Values.NW; +import static gregtech.api.metatileentity.BaseMetaTileEntity.COVER_DATA_NBT_KEYS; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + import gregtech.GT_Mod; import gregtech.api.GregTech_API; import gregtech.api.enums.Textures; @@ -11,16 +20,22 @@ import gregtech.api.interfaces.metatileentity.IConnectable; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.interfaces.tileentity.IPipeRenderedTileEntity; -import gregtech.api.metatileentity.BaseMetaTileEntity.ClientEvents; import gregtech.api.net.GT_Packet_TileEntity; import gregtech.api.objects.GT_ItemStack; -import gregtech.api.util.*; +import gregtech.api.util.GT_CoverBehavior; +import gregtech.api.util.GT_CoverBehaviorBase; +import gregtech.api.util.GT_Log; +import gregtech.api.util.GT_ModHandler; +import gregtech.api.util.GT_OreDictUnificator; +import gregtech.api.util.GT_Utility; +import gregtech.api.util.ISerializableObject; import gregtech.common.GT_Client; import gregtech.common.covers.GT_Cover_Fluidfilter; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -32,27 +47,18 @@ import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; - -import static gregtech.GT_Mod.GT_FML_LOGGER; -import static gregtech.api.enums.GT_Values.NW; - /** * NEVER INCLUDE THIS FILE IN YOUR MOD!!! * <p/> * This is the main TileEntity for EVERYTHING. */ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileEntity, IPipeRenderedTileEntity { - private final GT_CoverBehavior[] mCoverBehaviors = new GT_CoverBehavior[]{GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior}; + private final GT_CoverBehaviorBase<?>[] mCoverBehaviors = new GT_CoverBehaviorBase<?>[]{GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior}; public byte mConnections = IConnectable.NO_CONNECTION; protected MetaPipeEntity mMetaTileEntity; private byte[] mSidedRedstone = new byte[]{0, 0, 0, 0, 0, 0}; - private int[] mCoverSides = new int[]{0, 0, 0, 0, 0, 0}; - private int[] mCoverData = new int[]{0, 0, 0, 0, 0, 0}; - private final int[] mTimeStatistics = new int[GregTech_API.TICKS_FOR_LAG_AVERAGING]; + private int[] mCoverSides = new int[]{0, 0, 0, 0, 0, 0}, mTimeStatistics = new int[GregTech_API.TICKS_FOR_LAG_AVERAGING]; + private ISerializableObject[] mCoverData = new ISerializableObject[6]; private boolean mInventoryChanged = false, mWorkUpdate = false, mWorks = true, mNeedsUpdate = true, mNeedsBlockUpdate = true, mSendClientData = false; private final boolean mCheckConnections = false; private byte mColor = 0, oColor = 0, mStrongRedstone = 0, oStrongRedstone = 0, oRedstoneData = 63, oTextureData = 0, oUpdateData = 0, mLagWarningCount = 0; @@ -92,27 +98,18 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE } try { aNBT.setInteger("mID", mID); - aNBT.setIntArray("mCoverData", mCoverData); + for (int i = 0; i < mCoverData.length; i++) { + if (mCoverData[i] != null) + aNBT.setTag(COVER_DATA_NBT_KEYS[i], mCoverData[i].saveDataToNBT()); + } aNBT.setIntArray("mCoverSides", mCoverSides); aNBT.setByteArray("mRedstoneSided", mSidedRedstone); aNBT.setByte("mConnections", mConnections); aNBT.setByte("mColor", mColor); aNBT.setByte("mStrongRedstone", mStrongRedstone); aNBT.setBoolean("mWorks", !mWorks); - - for(int i=0;i < mCoverData.length; i++) { - if (GregTech_API.getCoverBehavior(mCoverSides[i]) instanceof GT_Cover_Fluidfilter) { - final int fluidId = mCoverData[i] >>> 3; - final Fluid fluid = FluidRegistry.getFluid(fluidId); - if(fluid != null) { - final String fluidName = FluidRegistry.getFluidName(fluid); - aNBT.setString(String.format("fluidFilter%d", i), fluidName); - } - } - } - } catch (Throwable e) { - GT_Log.err.println("Encountered CRITICAL ERROR while saving MetaTileEntity, the Chunk whould've been corrupted by now, but I prevented that. Please report immediately to GregTech Intergalactical!!!"); + GT_Log.err.println("Encountered CRITICAL ERROR while saving MetaTileEntity, the Chunk would've been corrupted by now, but I prevented that. Please report immediately to GregTech Intergalactical!!!"); e.printStackTrace(GT_Log.err); } try { @@ -158,28 +155,61 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE if (aID <= 0) mID = (short) aNBT.getInteger("mID"); else mID = aID; mCoverSides = aNBT.getIntArray("mCoverSides"); - mCoverData = aNBT.getIntArray("mCoverData"); mSidedRedstone = aNBT.getByteArray("mRedstoneSided"); mConnections = aNBT.getByte("mConnections"); mColor = aNBT.getByte("mColor"); mStrongRedstone = aNBT.getByte("mStrongRedstone"); mWorks = !aNBT.getBoolean("mWorks"); - if (mCoverData.length != 6) mCoverData = new int[]{0, 0, 0, 0, 0, 0}; if (mCoverSides.length != 6) mCoverSides = new int[]{0, 0, 0, 0, 0, 0}; + // check old form of data + mCoverData = null; + if (aNBT.hasKey("mCoverData", 11)) { + int[] tOldData = aNBT.getIntArray("mCoverData"); + if (tOldData.length == 6) + mCoverData = Arrays.stream(tOldData).mapToObj(ISerializableObject.LegacyCoverData::new).toArray(ISerializableObject[]::new); + } + // if no old data + if (mCoverData == null) { + mCoverData = new ISerializableObject[6]; + for (byte i = 0; i<6; i++) { + GT_CoverBehaviorBase<?> tBehavior = getCoverBehaviorAtSideNew(i); + if (tBehavior == null) + continue; + mCoverData[i] = tBehavior.createDataObject(); + if (aNBT.hasKey(COVER_DATA_NBT_KEYS[i])) + mCoverData[i].loadDataFromNBT(aNBT.getTag(COVER_DATA_NBT_KEYS[i])); + } + } if (mSidedRedstone.length != 6) mSidedRedstone = new byte[]{0, 0, 0, 0, 0, 0}; - for (byte i = 0; i < 6; i++) { - mCoverBehaviors[i] = GregTech_API.getCoverBehavior(mCoverSides[i]); - if(mCoverBehaviors[i] instanceof GT_Cover_Fluidfilter) { - final String filterKey = String.format("fluidFilter%d", i); - if (aNBT.hasKey(filterKey)) { - mCoverData[i] = (mCoverData[i] & 7) | (FluidRegistry.getFluidID(aNBT.getString(filterKey)) << 3); + for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehaviorNew(mCoverSides[i]); + + // check old form of data + mCoverData = new ISerializableObject[6]; + if (aNBT.hasKey("mCoverData", 11) && aNBT.getIntArray("mCoverData").length == 6) { + int[] tOldData = aNBT.getIntArray("mCoverData"); + for (int i = 0; i < tOldData.length; i++) { + if(mCoverBehaviors[i] instanceof GT_Cover_Fluidfilter) { + final String filterKey = String.format("fluidFilter%d", i); + if (aNBT.hasKey(filterKey)) { + mCoverData[i] = mCoverBehaviors[i].createDataObject((tOldData[i] & 7) | (FluidRegistry.getFluidID(aNBT.getString(filterKey)) << 3)); + } + } else if (mCoverBehaviors[i] != null && mCoverBehaviors[i] != GregTech_API.sNoBehavior) { + mCoverData[i] = mCoverBehaviors[i].createDataObject(tOldData[i]); } } + } else { + // no old data + for (byte i = 0; i<6; i++) { + if (mCoverBehaviors[i] == null) + continue; + if (aNBT.hasKey(COVER_DATA_NBT_KEYS[i])) + mCoverData[i] = mCoverBehaviors[i].createDataObject(aNBT.getTag(COVER_DATA_NBT_KEYS[i])); + else + mCoverData[i] = mCoverBehaviors[i].createDataObject(); + } } - - if (mID != 0 && createNewMetatileEntity(mID)) { NBTTagList tItemList = aNBT.getTagList("Inventory", 10); for (int i = 0; i < tItemList.tagCount(); i++) { @@ -199,11 +229,11 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE } } - if (mCoverData.length != 6) mCoverData = new int[]{0, 0, 0, 0, 0, 0}; + if (mCoverData == null || mCoverData.length != 6) mCoverData = new ISerializableObject[6]; if (mCoverSides.length != 6) mCoverSides = new int[]{0, 0, 0, 0, 0, 0}; if (mSidedRedstone.length != 6) mSidedRedstone = new byte[]{0, 0, 0, 0, 0, 0}; - for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehavior(mCoverSides[i]); + for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehaviorNew(mCoverSides[i]); } private boolean createNewMetatileEntity(short aID) { @@ -271,7 +301,7 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE for (byte i = (byte) (tCode - 2); i < 6; i++) if (getCoverIDAtSide(i) != 0) { tCode++; - GT_CoverBehavior tCover = getCoverBehaviorAtSide(i); + GT_CoverBehaviorBase<?> tCover = getCoverBehaviorAtSideNew(i); int tCoverTickRate = tCover.getTickRate(i, getCoverIDAtSide(i), mCoverData[i], this); if (tCoverTickRate > 0 && mTickTimer % tCoverTickRate == 0) { byte tRedstone = tCover.isRedstoneSensitive(i, getCoverIDAtSide(i), mCoverData[i], this, mTickTimer) ? getInputRedstoneSignal(i) : 0; @@ -298,7 +328,7 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE if (isServerSide()) { if (mTickTimer == 10) { for (byte i = 0; i < 6; i++) - mCoverBehaviors[i] = GregTech_API.getCoverBehavior(mCoverSides[i]); + mCoverBehaviors[i] = GregTech_API.getCoverBehaviorNew(mCoverSides[i]); issueBlockUpdate(); joinEnet(); } @@ -326,15 +356,12 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE } if (mTickTimer > 10) { - if (mConnections != oTextureData) - sendBlockEvent(ClientEvents.CHANGE_COMMON_DATA, oTextureData = mConnections); + if (mConnections != oTextureData) sendBlockEvent((byte) 0, oTextureData = mConnections); byte tData = mMetaTileEntity.getUpdateData(); - if (tData != oUpdateData) - sendBlockEvent(ClientEvents.CHANGE_CUSTOM_DATA, oUpdateData = tData); - if (mColor != oColor) sendBlockEvent(ClientEvents.CHANGE_COLOR, oColor = mColor); + if (tData != oUpdateData) sendBlockEvent((byte) 1, oUpdateData = tData); + if (mColor != oColor) sendBlockEvent((byte) 2, oColor = mColor); tData = (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 (tData != oRedstoneData) - sendBlockEvent(ClientEvents.CHANGE_REDSTONE_OUTPUT, oRedstoneData = tData); + if (tData != oRedstoneData) sendBlockEvent((byte) 3, oRedstoneData = tData); } if (mNeedsBlockUpdate) { @@ -384,7 +411,7 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE mCoverSides[4] = aCover4; mCoverSides[5] = aCover5; - for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehavior(mCoverSides[i]); + for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehaviorNew(mCoverSides[i]); receiveClientEvent(0, aTextureData); receiveClientEvent(1, aUpdateData); @@ -498,6 +525,12 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE } @Override + public void receiveCoverData(byte aCoverSide, int aCoverID, ISerializableObject aCoverData, EntityPlayerMP aPlayer) { + if ((aCoverSide >= 0 && aCoverSide < 6) && (mCoverSides[aCoverSide] == aCoverID)) + setCoverDataAtSide(aCoverSide, aCoverData); + } + + @Override public byte getStrongestRedstone() { return (byte) Math.max(getInternalInputRedstoneSignal((byte) 0), Math.max(getInternalInputRedstoneSignal((byte) 1), Math.max(getInternalInputRedstoneSignal((byte) 2), Math.max(getInternalInputRedstoneSignal((byte) 3), Math.max(getInternalInputRedstoneSignal((byte) 4), getInternalInputRedstoneSignal((byte) 5)))))); } @@ -869,7 +902,8 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE if (mStrongRedstone > 0) tNBT.setByte("mStrongRedstone", mStrongRedstone); for (byte i = 0; i < mCoverSides.length; i++) { if (mCoverSides[i] != 0) { - tNBT.setIntArray("mCoverData", mCoverData); + if (mCoverData[i] != null) // this really shouldn't be null if a cover is there already, but whatever + tNBT.setTag(COVER_DATA_NBT_KEYS[i], mCoverData[i].saveDataToNBT()); tNBT.setIntArray("mCoverSides", mCoverSides); break; } @@ -909,13 +943,13 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sScrewdriverList)) { if (getCoverIDAtSide(aSide) == 0 && getCoverIDAtSide(tSide) != 0) { if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 200, aPlayer)) { - setCoverDataAtSide(tSide, getCoverBehaviorAtSide(tSide).onCoverScrewdriverclick(tSide, getCoverIDAtSide(tSide), getCoverDataAtSide(tSide), this, aPlayer, 0.5F, 0.5F, 0.5F)); + setCoverDataAtSide(tSide, getCoverBehaviorAtSideNew(tSide).onCoverScrewdriverClick(tSide, getCoverIDAtSide(tSide), getComplexCoverDataAtSide(tSide), this, aPlayer, 0.5F, 0.5F, 0.5F)); mMetaTileEntity.onScrewdriverRightClick(tSide, aPlayer, aX, aY, aZ); GT_Utility.sendSoundToPlayers(worldObj, GregTech_API.sSoundList.get(100), 1.0F, -1, xCoord, yCoord, zCoord); } } else { if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer)) { - setCoverDataAtSide(aSide, getCoverBehaviorAtSide(aSide).onCoverScrewdriverclick(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this, aPlayer, aX, aY, aZ)); + setCoverDataAtSide(aSide, getCoverBehaviorAtSideNew(aSide).onCoverScrewdriverClick(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this, aPlayer, aX, aY, aZ)); mMetaTileEntity.onScrewdriverRightClick(aSide, aPlayer, aX, aY, aZ); GT_Utility.sendSoundToPlayers(worldObj, GregTech_API.sSoundList.get(100), 1.0F, -1, xCoord, yCoord, zCoord); } @@ -968,7 +1002,7 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE if (getCoverIDAtSide(coverSide) == 0) { if (GregTech_API.sCovers.containsKey(new GT_ItemStack(tCurrentItem))) { - if (GregTech_API.getCoverBehavior(tCurrentItem).isCoverPlaceable(coverSide, new GT_ItemStack(tCurrentItem), this) && + if (GregTech_API.getCoverBehaviorNew(tCurrentItem).isCoverPlaceable(coverSide, new GT_ItemStack(tCurrentItem), this) && mMetaTileEntity.allowCoverOnSide(coverSide, new GT_ItemStack(tCurrentItem))) { setCoverItemAtSide(coverSide, tCurrentItem); @@ -989,14 +1023,14 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE } else if (aPlayer.isSneaking()) { //Sneak click, no tool -> open cover config or turn back. aSide = (getCoverIDAtSide(aSide) == 0) ? GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ) : aSide; - return getCoverIDAtSide(aSide) > 0 && getCoverBehaviorAtSide(aSide).onCoverShiftRightclick(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this, aPlayer); + return getCoverIDAtSide(aSide) > 0 && getCoverBehaviorAtSideNew(aSide).onCoverShiftRightClick(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this, aPlayer); } - if (getCoverBehaviorAtSide(aSide).onCoverRightclick(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this, aPlayer, aX, aY, aZ)) + if (getCoverBehaviorAtSideNew(aSide).onCoverRightClick(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this, aPlayer, aX, aY, aZ)) return true; } - if (!getCoverBehaviorAtSide(aSide).isGUIClickable(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this)) + if (!getCoverBehaviorAtSideNew(aSide).isGUIClickable(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this)) return false; try { @@ -1053,7 +1087,7 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE */ @Override public int[] getAccessibleSlotsFromSide(int aSide) { - if (canAccessData() && (getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, getCoverIDAtSide((byte) aSide), getCoverDataAtSide((byte) aSide), -1, this) || getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, getCoverIDAtSide((byte) aSide), getCoverDataAtSide((byte) aSide), -1, this))) + if (canAccessData() && (getCoverBehaviorAtSideNew((byte) aSide).letsItemsOut((byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), -1, this) || getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), -1, this))) return mMetaTileEntity.getAccessibleSlotsFromSide(aSide); return new int[0]; } @@ -1063,7 +1097,7 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE */ @Override public boolean canInsertItem(int aIndex, ItemStack aStack, int aSide) { - return canAccessData() && getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, getCoverIDAtSide((byte) aSide), getCoverDataAtSide((byte) aSide), aIndex, this) && mMetaTileEntity.canInsertItem(aIndex, aStack, aSide); + return canAccessData() && getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), aIndex, this) && mMetaTileEntity.canInsertItem(aIndex, aStack, aSide); } /** @@ -1071,7 +1105,7 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE */ @Override public boolean canExtractItem(int aIndex, ItemStack aStack, int aSide) { - return canAccessData() && getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, getCoverIDAtSide((byte) aSide), getCoverDataAtSide((byte) aSide), aIndex, this) && mMetaTileEntity.canExtractItem(aIndex, aStack, aSide); + return canAccessData() && getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), aIndex, this) && mMetaTileEntity.canExtractItem(aIndex, aStack, aSide); } @Override @@ -1081,7 +1115,7 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE @Override public byte getInternalInputRedstoneSignal(byte aSide) { - return (byte) (getCoverBehaviorAtSide(aSide).getRedstoneInput(aSide, getInputRedstoneSignal(aSide), getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this) & 15); + return (byte) (getCoverBehaviorAtSide(aSide).getRedstoneInput(aSide, getInputRedstoneSignal(aSide), getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this) & 15); } @Override @@ -1091,12 +1125,12 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE @Override public byte getOutputRedstoneSignal(byte aSide) { - return (byte) (getCoverBehaviorAtSide(aSide).manipulatesSidedRedstoneOutput(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this) || (getCoverBehaviorAtSide(aSide).letsRedstoneGoOut(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this)) ? mSidedRedstone[aSide] & 15 : 0); + return (byte) (getCoverBehaviorAtSideNew(aSide).manipulatesSidedRedstoneOutput(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this) || (getCoverBehaviorAtSideNew(aSide).letsRedstoneGoOut(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this)) ? mSidedRedstone[aSide] & 15 : 0); } @Override public void setInternalOutputRedstoneSignal(byte aSide, byte aStrength) { - if (!getCoverBehaviorAtSide(aSide).manipulatesSidedRedstoneOutput(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this)) + if (!getCoverBehaviorAtSideNew(aSide).manipulatesSidedRedstoneOutput(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this)) setOutputRedstoneSignal(aSide, aStrength); } @@ -1159,16 +1193,19 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE } @Override + @Deprecated public GT_CoverBehavior getCoverBehaviorAtSide(byte aSide) { - return aSide >= 0 && aSide < mCoverBehaviors.length ? mCoverBehaviors[aSide] : GregTech_API.sNoBehavior; + if (aSide >= 0 && aSide < mCoverBehaviors.length && mCoverBehaviors[aSide] instanceof GT_CoverBehavior) + return (GT_CoverBehavior) mCoverBehaviors[aSide]; + return GregTech_API.sNoBehavior; } @Override public void setCoverIDAtSide(byte aSide, int aID) { if (aSide >= 0 && aSide < 6) { mCoverSides[aSide] = aID; - mCoverData[aSide] = 0; - mCoverBehaviors[aSide] = GregTech_API.getCoverBehavior(aID); + mCoverBehaviors[aSide] = GregTech_API.getCoverBehaviorNew(aID); + mCoverData[aSide] = mCoverBehaviors[aSide].createDataObject(); issueCoverUpdate(aSide); issueBlockUpdate(); } @@ -1176,7 +1213,7 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE @Override public void setCoverItemAtSide(byte aSide, ItemStack aCover) { - GregTech_API.getCoverBehavior(aCover).placeCover(aSide, aCover, this); + GregTech_API.getCoverBehaviorNew(aCover).placeCover(aSide, aCover, this); } @Override @@ -1201,17 +1238,36 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE } @Override + @Deprecated public void setCoverDataAtSide(byte aSide, int aData) { - if (aSide >= 0 && aSide < 6) mCoverData[aSide] = aData; + if (aSide >= 0 && aSide < 6 && mCoverData[aSide] instanceof ISerializableObject.LegacyCoverData) + mCoverData[aSide] = new ISerializableObject.LegacyCoverData(aData); } @Override + @Deprecated public int getCoverDataAtSide(byte aSide) { - if (aSide >= 0 && aSide < 6) return mCoverData[aSide]; + if (aSide >= 0 && aSide < 6 && mCoverData[aSide] instanceof ISerializableObject.LegacyCoverData) + return ((ISerializableObject.LegacyCoverData) mCoverData[aSide]).get(); return 0; } @Override + public void setCoverDataAtSide(byte aSide, ISerializableObject aData) { + mCoverData[aSide] = aData; + } + + @Override + public ISerializableObject getComplexCoverDataAtSide(byte aSide) { + return mCoverData[aSide]; + } + + @Override + public GT_CoverBehaviorBase<?> getCoverBehaviorAtSideNew(byte aSide) { + return mCoverBehaviors[aSide]; + } + + @Override public void setLightValue(byte aLightValue) { // } @@ -1228,8 +1284,8 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE @Override public boolean dropCover(byte aSide, byte aDroppedSide, boolean aForced) { - if (getCoverBehaviorAtSide(aSide).onCoverRemoval(aSide, getCoverIDAtSide(aSide), mCoverData[aSide], this, aForced) || aForced) { - ItemStack tStack = getCoverBehaviorAtSide(aSide).getDrop(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this); + if (getCoverBehaviorAtSideNew(aSide).onCoverRemoval(aSide, getCoverIDAtSide(aSide), mCoverData[aSide], this, aForced) || aForced) { + ItemStack tStack = getCoverBehaviorAtSideNew(aSide).getDrop(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this); if (tStack != null) { tStack.setTagCompound(null); EntityItem tEntity = new EntityItem(worldObj, getOffsetX(aDroppedSide, 1) + 0.5, getOffsetY(aDroppedSide, 1) + 0.5, getOffsetZ(aDroppedSide, 1) + 0.5, tStack); @@ -1323,12 +1379,15 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE if (tTileEntity != null && !mMetaTileEntity.isConnectedAtSide((byte) aSide.ordinal())) return false; - if (isFill && mMetaTileEntity.isLiquidInput((byte) aSide.ordinal()) - && getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidIn((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getCoverDataAtSide((byte) aSide.ordinal()), aFluid, this)) + if(isFill && mMetaTileEntity.isLiquidInput((byte) aSide.ordinal()) + && getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidIn((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), aFluid, this)) return true; - return !isFill && mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) - && getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getCoverDataAtSide((byte) aSide.ordinal()), aFluid, this); + if (!isFill && mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) + && getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()),aFluid, this)) + return true; + + return false; } @Override @@ -1371,8 +1430,8 @@ public class BaseMetaPipeEntity extends BaseTileEntity implements IGregTechTileE if (canAccessData() && (aSide == ForgeDirection.UNKNOWN || (mMetaTileEntity.isLiquidInput((byte) aSide.ordinal()) - && getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidIn((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getCoverDataAtSide((byte) aSide.ordinal()), null, this)) - || (mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) && getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getCoverDataAtSide((byte) aSide.ordinal()), null, this)) + && getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidIn((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), null, this)) + || (mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) && getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), null, this)) // Doesn't need to be connected to get Tank Info -- otherwise things can't connect ) ) diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java index 10d5ec774a..a56c0020a3 100644 --- a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java @@ -40,6 +40,7 @@ import net.minecraft.block.BlockFire; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -74,23 +75,22 @@ import static gregtech.api.objects.XSTR.XSTR_INSTANCE; * This is the main TileEntity for EVERYTHING. */ @Optional.InterfaceList(value = { - @Optional.Interface(iface = "appeng.api.networking.security.IActionHost", modid = "appliedenergistics2", striprefs = true), - @Optional.Interface(iface = "appeng.me.helpers.IGridProxyable", modid = "appliedenergistics2", striprefs = true)}) + @Optional.Interface(iface = "appeng.api.networking.security.IActionHost", modid = "appliedenergistics2", striprefs = true), + @Optional.Interface(iface = "appeng.me.helpers.IGridProxyable", modid = "appliedenergistics2", striprefs = true)}) public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileEntity, IActionHost, IGridProxyable, IAlignmentProvider, IConstructableProvider { - private final GT_CoverBehavior[] mCoverBehaviors = new GT_CoverBehavior[]{GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior}; + static final String[] COVER_DATA_NBT_KEYS = Arrays.stream(ForgeDirection.VALID_DIRECTIONS).mapToInt(Enum::ordinal).mapToObj(i -> "mCoverData" + i).toArray(String[]::new); + private final GT_CoverBehaviorBase<?>[] mCoverBehaviors = new GT_CoverBehaviorBase<?>[]{GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior, GregTech_API.sNoBehavior}; protected MetaTileEntity mMetaTileEntity; protected long mStoredEnergy = 0, mStoredSteam = 0; protected int mAverageEUInputIndex = 0, mAverageEUOutputIndex = 0; protected boolean mReleaseEnergy = false; protected long[] mAverageEUInput = new long[]{0, 0, 0, 0, 0}, mAverageEUOutput = new long[]{0, 0, 0, 0, 0}; - private final boolean[] mActiveEUInputs = new boolean[]{false, false, false, false, false, false}; - private final boolean[] mActiveEUOutputs = new boolean[]{false, false, false, false, false, false}; + private boolean[] mActiveEUInputs = new boolean[]{false, false, false, false, false, false}, mActiveEUOutputs = new boolean[]{false, false, false, false, false, false}; private byte[] mSidedRedstone = new byte[]{15, 15, 15, 15, 15, 15}; - private int[] mCoverSides = new int[]{0, 0, 0, 0, 0, 0}; - private int[] mCoverData = new int[]{0, 0, 0, 0, 0, 0}; - private final int[] mTimeStatistics = new int[GregTech_API.TICKS_FOR_LAG_AVERAGING]; + private int[] mCoverSides = new int[]{0, 0, 0, 0, 0, 0}, mTimeStatistics = new int[GregTech_API.TICKS_FOR_LAG_AVERAGING]; + private ISerializableObject[] mCoverData = new ISerializableObject[6]; private boolean mHasEnoughEnergy = true, mRunningThroughTick = false, mInputDisabled = false, mOutputDisabled = false, mMuffler = false, mLockUpgrade = false, mActive = false, mRedstone = false, mWorkUpdate = false, mSteamConverter = false, mInventoryChanged = false, mWorks = true, mNeedsUpdate = true, mNeedsBlockUpdate = true, mSendClientData = false, oRedstone = false; - private byte mColor = 0, oColor = 0, oStrongRedstone = 0, mStrongRedstone = 0, oRedstoneData = 63, oTextureData = 0, oUpdateData = 0, oTexturePage = 0, oLightValueClient = -1, oLightValue = -1, mLightValue = 0, mOtherUpgrades = 0, mFacing = 0, oFacing = 0, mWorkData = 0; + private byte mColor = 0, oColor = 0, oStrongRedstone = 0, mStrongRedstone = 0, oRedstoneData = 63, oTextureData = 0, oUpdateData = 0, oTexturePage=0, oLightValueClient = -1, oLightValue = -1, mLightValue = 0, mOtherUpgrades = 0, mFacing = 0, oFacing = 0, mWorkData = 0; private int mDisplayErrorCode = 0, oX = 0, oY = 0, oZ = 0, mTimeStatisticsIndex = 0, mLagWarningCount = 0; private short mID = 0; public long mTickTimer = 0; @@ -139,7 +139,10 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE aNBT.setInteger("mID", mID); aNBT.setLong("mStoredSteam", mStoredSteam); aNBT.setLong("mStoredEnergy", mStoredEnergy); - aNBT.setIntArray("mCoverData", mCoverData); + for (int i = 0; i < mCoverData.length; i++) { + if (mCoverData[i] != null) + aNBT.setTag(COVER_DATA_NBT_KEYS[i], mCoverData[i].saveDataToNBT()); + } aNBT.setIntArray("mCoverSides", mCoverSides); aNBT.setByteArray("mRedstoneSided", mSidedRedstone); aNBT.setByte("mColor", mColor); @@ -230,19 +233,37 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE mOutputDisabled = aNBT.getBoolean("mOutputDisabled"); mOtherUpgrades = (byte) (aNBT.getByte("mOtherUpgrades") + aNBT.getByte("mBatteries") + aNBT.getByte("mLiBatteries")); mCoverSides = aNBT.getIntArray("mCoverSides"); - mCoverData = aNBT.getIntArray("mCoverData"); mSidedRedstone = aNBT.getByteArray("mRedstoneSided"); mRecipeStuff = aNBT.getCompoundTag("GT.CraftingComponents"); int nbtVersion = aNBT.getInteger("nbtVersion"); - if (mCoverData.length != 6) mCoverData = new int[]{0, 0, 0, 0, 0, 0}; if (mCoverSides.length != 6) mCoverSides = new int[]{0, 0, 0, 0, 0, 0}; if (mSidedRedstone.length != 6) if (hasValidMetaTileEntity() && mMetaTileEntity.hasSidedRedstoneOutputBehavior()) mSidedRedstone = new byte[]{0, 0, 0, 0, 0, 0}; else mSidedRedstone = new byte[]{15, 15, 15, 15, 15, 15}; - for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehavior(mCoverSides[i]); + for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehaviorNew(mCoverSides[i]); + + // check legacy data + mCoverData = new ISerializableObject[6]; + if (aNBT.hasKey("mCoverData", 11) && aNBT.getIntArray("mCoverData").length == 6) { + int[] tOldData = aNBT.getIntArray("mCoverData"); + for (int i = 0; i < tOldData.length; i++) { + if (mCoverBehaviors[i] != null) + mCoverData[i] = mCoverBehaviors[i].createDataObject(tOldData[i]); + } + } else { + // no old data + for (byte i = 0; i<6; i++) { + if (mCoverBehaviors[i] == null) + continue; + if (aNBT.hasKey(COVER_DATA_NBT_KEYS[i])) + mCoverData[i] = mCoverBehaviors[i].createDataObject(aNBT.getTag(COVER_DATA_NBT_KEYS[i])); + else + mCoverData[i] = mCoverBehaviors[i].createDataObject(); + } + } if (mID != 0 && createNewMetatileEntity(mID)) { NBTTagList tItemList = aNBT.getTagList("Inventory", 10); @@ -264,14 +285,14 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE } } - if (mCoverData.length != 6) mCoverData = new int[]{0, 0, 0, 0, 0, 0}; + if (mCoverData == null || mCoverData.length != 6) mCoverData = new ISerializableObject[6]; if (mCoverSides.length != 6) mCoverSides = new int[]{0, 0, 0, 0, 0, 0}; if (mSidedRedstone.length != 6) if (hasValidMetaTileEntity() && mMetaTileEntity.hasSidedRedstoneOutputBehavior()) mSidedRedstone = new byte[]{0, 0, 0, 0, 0, 0}; else mSidedRedstone = new byte[]{15, 15, 15, 15, 15, 15}; - for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehavior(mCoverSides[i]); + for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehaviorNew(mCoverSides[i]); } private boolean createNewMetatileEntity(short aID) { @@ -380,7 +401,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE for (byte i = (byte) (tCode - 2); i < 6; i++) if (getCoverIDAtSide(i) != 0) { tCode++; - GT_CoverBehavior tCover = getCoverBehaviorAtSide(i); + GT_CoverBehaviorBase<?> tCover = getCoverBehaviorAtSideNew(i); int tCoverTickRate = tCover.getTickRate(i, getCoverIDAtSide(i), mCoverData[i], this); if (tCoverTickRate > 0 && mTickTimer % tCoverTickRate == 0) { byte tRedstone = tCover.isRedstoneSensitive(i, getCoverIDAtSide(i), mCoverData[i], this, mTickTimer) ? getInputRedstoneSignal(i) : 0; @@ -414,7 +435,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE if (aSideServer) { if (mRedstone != oRedstone || mTickTimer == 10) { for (byte i = 0; i < 6; i++) - mCoverBehaviors[i] = GregTech_API.getCoverBehavior(mCoverSides[i]); + mCoverBehaviors[i] = GregTech_API.getCoverBehaviorNew(mCoverSides[i]); oRedstone = mRedstone; issueBlockUpdate(); } @@ -492,7 +513,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE if (GregTech_API.sMachineRainExplosions && worldObj.isRaining() && getBiome().rainfall > 0) { if (getRandomNumber(10) == 0) { try{ - GT_Mod.achievements.issueAchievement(this.getWorldObj().getPlayerEntityByName(mOwnerName), "badweather"); + GT_Mod.instance.achievements.issueAchievement(this.getWorldObj().getPlayerEntityByName(mOwnerName), "badweather"); }catch(Exception e){ } @@ -508,9 +529,9 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE return; } if (GregTech_API.sMachineThunderExplosions && worldObj.isThundering() && getBiome().rainfall > 0 && getRandomNumber(3) == 0) { - try { - GT_Mod.achievements.issueAchievement(this.getWorldObj().getPlayerEntityByName(mOwnerName), "badweather"); - }catch(Exception e){ + try{ + GT_Mod.instance.achievements.issueAchievement(this.getWorldObj().getPlayerEntityByName(mOwnerName), "badweather"); + }catch(Exception e){ } GT_Log.exp.println("Machine at: "+ this.getXCoord()+" | "+ this.getYCoord()+" | "+ this.getZCoord()+" DIMID: " +this.worldObj.provider.dimensionId + " explosion due to Thunderstorm!"); @@ -678,7 +699,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE mCoverSides[4] = aCover4; mCoverSides[5] = aCover5; - for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehavior(mCoverSides[i]); + for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehaviorNew(mCoverSides[i]); receiveClientEvent(ClientEvents.CHANGE_COMMON_DATA, aTextureData); receiveClientEvent(ClientEvents.CHANGE_CUSTOM_DATA, aUpdateData & 0x7F); @@ -702,7 +723,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE mCoverSides[4] = aCover4; mCoverSides[5] = aCover5; - for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehavior(mCoverSides[i]); + for (byte i = 0; i < 6; i++) mCoverBehaviors[i] = GregTech_API.getCoverBehaviorNew(mCoverSides[i]); receiveClientEvent(ClientEvents.CHANGE_COMMON_DATA, aTextureData); receiveClientEvent(ClientEvents.CHANGE_CUSTOM_DATA, aUpdateData & 0x7F); @@ -851,6 +872,12 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE } @Override + public void receiveCoverData(byte aCoverSide, int aCoverID, ISerializableObject aCoverData, EntityPlayerMP aPlayer) { + if ((aCoverSide >= 0 && aCoverSide < 6) && (mCoverSides[aCoverSide] == aCoverID)) + setCoverDataAtSide(aCoverSide, aCoverData); + } + + @Override public byte getStrongestRedstone() { return (byte) Math.max(getInternalInputRedstoneSignal((byte) 0), Math.max(getInternalInputRedstoneSignal((byte) 1), Math.max(getInternalInputRedstoneSignal((byte) 2), Math.max(getInternalInputRedstoneSignal((byte) 3), Math.max(getInternalInputRedstoneSignal((byte) 4), getInternalInputRedstoneSignal((byte) 5)))))); } @@ -1028,7 +1055,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE @Override public boolean increaseProgress(int aProgressAmountInTicks) { - return canAccessData() && mMetaTileEntity.increaseProgress(aProgressAmountInTicks) != aProgressAmountInTicks; + return canAccessData() ? mMetaTileEntity.increaseProgress(aProgressAmountInTicks) != aProgressAmountInTicks : false; } @Override @@ -1252,7 +1279,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE private boolean isEnergyInputSide(byte aSide) { if (aSide >= 0 && aSide < 6) { - if (!getCoverBehaviorAtSide(aSide).letsEnergyIn(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this)) + if (!getCoverBehaviorAtSideNew(aSide).letsEnergyIn(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this)) return false; if (isInvalid() || mReleaseEnergy) return false; if (canAccessData() && mMetaTileEntity.isElectric() && mMetaTileEntity.isEnetInput()) @@ -1263,7 +1290,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE private boolean isEnergyOutputSide(byte aSide) { if (aSide >= 0 && aSide < 6) { - if (!getCoverBehaviorAtSide(aSide).letsEnergyOut(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this)) + if (!getCoverBehaviorAtSideNew(aSide).letsEnergyOut(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this)) return false; if (isInvalid() || mReleaseEnergy) return mReleaseEnergy; if (canAccessData() && mMetaTileEntity.isElectric() && mMetaTileEntity.isEnetOutput()) @@ -1413,7 +1440,8 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE if (mStrongRedstone > 0) tNBT.setByte("mStrongRedstone", mStrongRedstone); for (byte i = 0; i < mCoverSides.length; i++) { if (mCoverSides[i] != 0) { - tNBT.setIntArray("mCoverData", mCoverData); + if (mCoverData[i] != null) // this really shouldn't be null if a cover is there already, but whatever + tNBT.setTag(COVER_DATA_NBT_KEYS[i], mCoverData[i].saveDataToNBT()); tNBT.setIntArray("mCoverSides", mCoverSides); break; } @@ -1433,12 +1461,12 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE //Configure Cover, sneak can also be: screwdriver, wrench, side cutter, soldering iron if (aPlayer.isSneaking()) { byte tSide = (getCoverIDAtSide(aSide) == 0) ? GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ) : aSide; - return (getCoverBehaviorAtSide(tSide).hasCoverGUI()); - } else if (getCoverBehaviorAtSide(aSide).onCoverRightclickClient(aSide, this, aPlayer, aX, aY, aZ)) { + return (getCoverBehaviorAtSideNew(tSide).hasCoverGUI()); + } else if (getCoverBehaviorAtSideNew(aSide).onCoverRightclickClient(aSide, this, aPlayer, aX, aY, aZ)) { return true; } - if (!getCoverBehaviorAtSide(aSide).isGUIClickable(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this)) + if (!getCoverBehaviorAtSideNew(aSide).isGUIClickable(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this)) return false; } if (isServerSide()) { @@ -1465,7 +1493,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sScrewdriverList)) { if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 200, aPlayer)) { - setCoverDataAtSide(aSide, getCoverBehaviorAtSide(aSide).onCoverScrewdriverclick(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this, aPlayer, aX, aY, aZ)); + setCoverDataAtSide(aSide, getCoverBehaviorAtSideNew(aSide).onCoverScrewdriverClick(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this, aPlayer, aX, aY, aZ)); mMetaTileEntity.onScrewdriverRightClick(aSide, aPlayer, aX, aY, aZ); GT_Utility.sendSoundToPlayers(worldObj, GregTech_API.sSoundList.get(100), 1.0F, -1, xCoord, yCoord, zCoord); } @@ -1529,7 +1557,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE if (getCoverIDAtSide(coverSide) == 0) { if (GregTech_API.sCovers.containsKey(new GT_ItemStack(tCurrentItem))) { - if (GregTech_API.getCoverBehavior(tCurrentItem).isCoverPlaceable(coverSide, new GT_ItemStack(tCurrentItem), this) && + if (GregTech_API.getCoverBehaviorNew(tCurrentItem).isCoverPlaceable(coverSide, new GT_ItemStack(tCurrentItem), this) && mMetaTileEntity.allowCoverOnSide(coverSide, new GT_ItemStack(tCurrentItem))) { setCoverItemAtSide(coverSide, tCurrentItem); @@ -1550,13 +1578,13 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE } 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 && getCoverBehaviorAtSide(aSide).onCoverShiftRightclick(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this, aPlayer); + return getCoverIDAtSide(aSide) > 0 && getCoverBehaviorAtSideNew(aSide).onCoverShiftRightClick(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this, aPlayer); } - if (getCoverBehaviorAtSide(aSide).onCoverRightclick(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this, aPlayer, aX, aY, aZ)) + if (getCoverBehaviorAtSideNew(aSide).onCoverRightClick(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this, aPlayer, aX, aY, aZ)) return true; - if (!getCoverBehaviorAtSide(aSide).isGUIClickable(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this)) + if (!getCoverBehaviorAtSideNew(aSide).isGUIClickable(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this)) return false; if (isUpgradable() && tCurrentItem != null) {/* @@ -1645,7 +1673,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE */ @Override public int[] getAccessibleSlotsFromSide(int aSide) { - if (canAccessData() && (getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, getCoverIDAtSide((byte) aSide), getCoverDataAtSide((byte) aSide), -1, this) || getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, getCoverIDAtSide((byte) aSide), getCoverDataAtSide((byte) aSide), -1, this))) + if (canAccessData() && (getCoverBehaviorAtSideNew((byte) aSide).letsItemsOut((byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), -1, this) || getCoverBehaviorAtSideNew((byte) aSide).letsItemsIn((byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), -1, this))) return mMetaTileEntity.getAccessibleSlotsFromSide(aSide); return new int[0]; } @@ -1655,7 +1683,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE */ @Override public boolean canInsertItem(int aIndex, ItemStack aStack, int aSide) { - return canAccessData() && (mRunningThroughTick || !mInputDisabled) && getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, getCoverIDAtSide((byte) aSide), getCoverDataAtSide((byte) aSide), aIndex, this) && mMetaTileEntity.canInsertItem(aIndex, aStack, aSide); + return canAccessData() && (mRunningThroughTick || !mInputDisabled) && getCoverBehaviorAtSideNew((byte) aSide).letsItemsIn((byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), aIndex, this) && mMetaTileEntity.canInsertItem(aIndex, aStack, aSide); } /** @@ -1663,7 +1691,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE */ @Override public boolean canExtractItem(int aIndex, ItemStack aStack, int aSide) { - return canAccessData() && (mRunningThroughTick || !mOutputDisabled) && getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, getCoverIDAtSide((byte) aSide), getCoverDataAtSide((byte) aSide), aIndex, this) && mMetaTileEntity.canExtractItem(aIndex, aStack, aSide); + return canAccessData() && (mRunningThroughTick || !mOutputDisabled) && getCoverBehaviorAtSideNew((byte) aSide).letsItemsOut((byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), aIndex, this) && mMetaTileEntity.canExtractItem(aIndex, aStack, aSide); } @Override @@ -1673,7 +1701,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE @Override public byte getInternalInputRedstoneSignal(byte aSide) { - return (byte) (getCoverBehaviorAtSide(aSide).getRedstoneInput(aSide, getInputRedstoneSignal(aSide), getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this) & 15); + return (byte) (getCoverBehaviorAtSideNew(aSide).getRedstoneInput(aSide, getInputRedstoneSignal(aSide), getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this) & 15); } @Override @@ -1683,7 +1711,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE @Override public byte getOutputRedstoneSignal(byte aSide) { - return getCoverBehaviorAtSide(aSide).manipulatesSidedRedstoneOutput(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this) ? mSidedRedstone[aSide] : getGeneralRS(aSide); + return getCoverBehaviorAtSideNew(aSide).manipulatesSidedRedstoneOutput(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this) ? mSidedRedstone[aSide] : getGeneralRS(aSide); } public byte getGeneralRS(byte aSide){ @@ -1693,7 +1721,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE @Override public void setInternalOutputRedstoneSignal(byte aSide, byte aStrength) { - if (!getCoverBehaviorAtSide(aSide).manipulatesSidedRedstoneOutput(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this)) + if (!getCoverBehaviorAtSideNew(aSide).manipulatesSidedRedstoneOutput(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this)) setOutputRedstoneSignal(aSide, aStrength); } @@ -1779,16 +1807,19 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE } @Override + @Deprecated public GT_CoverBehavior getCoverBehaviorAtSide(byte aSide) { - return aSide >= 0 && aSide < mCoverBehaviors.length ? mCoverBehaviors[aSide] : GregTech_API.sNoBehavior; + if (aSide >= 0 && aSide < mCoverBehaviors.length && mCoverBehaviors[aSide] instanceof GT_CoverBehavior) + return (GT_CoverBehavior) mCoverBehaviors[aSide]; + return GregTech_API.sNoBehavior; } @Override public void setCoverIDAtSide(byte aSide, int aID) { if (aSide >= 0 && aSide < 6) { mCoverSides[aSide] = aID; - mCoverData[aSide] = 0; - mCoverBehaviors[aSide] = GregTech_API.getCoverBehavior(aID); + mCoverBehaviors[aSide] = GregTech_API.getCoverBehaviorNew(aID); + mCoverData[aSide] = mCoverBehaviors[aSide].createDataObject(); issueCoverUpdate(aSide); issueBlockUpdate(); } @@ -1796,7 +1827,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE @Override public void setCoverItemAtSide(byte aSide, ItemStack aCover) { - GregTech_API.getCoverBehavior(aCover).placeCover(aSide, aCover, this); + GregTech_API.getCoverBehaviorNew(aCover).placeCover(aSide, aCover, this); } @Override @@ -1821,16 +1852,34 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE } @Override + @Deprecated public void setCoverDataAtSide(byte aSide, int aData) { - if (aSide >= 0 && aSide < 6) mCoverData[aSide] = aData; + if (aSide >= 0 && aSide < 6) mCoverData[aSide] = new ISerializableObject.LegacyCoverData(aData); } @Override + @Deprecated public int getCoverDataAtSide(byte aSide) { - if (aSide >= 0 && aSide < 6) return mCoverData[aSide]; + if (aSide >= 0 && aSide < 6 && mCoverData[aSide] instanceof ISerializableObject.LegacyCoverData) + return ((ISerializableObject.LegacyCoverData) mCoverData[aSide]).get(); return 0; } + @Override + public void setCoverDataAtSide(byte aSide, ISerializableObject aData) { + mCoverData[aSide] = aData; + } + + @Override + public ISerializableObject getComplexCoverDataAtSide(byte aSide) { + return mCoverData[aSide]; + } + + @Override + public GT_CoverBehaviorBase<?> getCoverBehaviorAtSideNew(byte aSide) { + return mCoverBehaviors[aSide]; + } + public byte getLightValue() { return mLightValue; } @@ -1860,8 +1909,8 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE @Override public boolean dropCover(byte aSide, byte aDroppedSide, boolean aForced) { - if (getCoverBehaviorAtSide(aSide).onCoverRemoval(aSide, getCoverIDAtSide(aSide), mCoverData[aSide], this, aForced) || aForced) { - ItemStack tStack = getCoverBehaviorAtSide(aSide).getDrop(aSide, getCoverIDAtSide(aSide), getCoverDataAtSide(aSide), this); + if (getCoverBehaviorAtSideNew(aSide).onCoverRemoval(aSide, getCoverIDAtSide(aSide), mCoverData[aSide], this, aForced) || aForced) { + ItemStack tStack = getCoverBehaviorAtSideNew(aSide).getDrop(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this); if (tStack != null) { tStack.setTagCompound(null); EntityItem tEntity = new EntityItem(worldObj, getOffsetX(aDroppedSide, 1) + 0.5, getOffsetY(aDroppedSide, 1) + 0.5, getOffsetZ(aDroppedSide, 1) + 0.5, tStack); @@ -1976,7 +2025,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE aSide == ForgeDirection.UNKNOWN || ( mMetaTileEntity.isLiquidInput((byte) aSide.ordinal()) && - getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidIn((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getCoverDataAtSide((byte) aSide.ordinal()), aFluid == null ? null : aFluid.getFluid(), this) + getCoverBehaviorAtSideNew((byte) aSide.ordinal()).letsFluidIn((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), aFluid == null ? null : aFluid.getFluid(), this) ) ) ) @@ -1992,7 +2041,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE aSide == ForgeDirection.UNKNOWN || ( mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) && - getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getCoverDataAtSide((byte) aSide.ordinal()), mMetaTileEntity.getFluid() == null ? null : mMetaTileEntity.getFluid().getFluid(), this) + getCoverBehaviorAtSideNew((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), mMetaTileEntity.getFluid() == null ? null : mMetaTileEntity.getFluid().getFluid(), this) ) ) ) @@ -2008,7 +2057,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE aSide == ForgeDirection.UNKNOWN || ( mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) && - getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getCoverDataAtSide((byte) aSide.ordinal()), aFluid == null ? null : aFluid.getFluid(), this) + getCoverBehaviorAtSideNew((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), aFluid == null ? null : aFluid.getFluid(), this) ) ) ) @@ -2024,7 +2073,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE aSide == ForgeDirection.UNKNOWN || ( mMetaTileEntity.isLiquidInput((byte) aSide.ordinal()) && - getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidIn((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getCoverDataAtSide((byte) aSide.ordinal()), aFluid, this) + getCoverBehaviorAtSideNew((byte) aSide.ordinal()).letsFluidIn((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), aFluid, this) ) ) ) @@ -2040,7 +2089,7 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE aSide == ForgeDirection.UNKNOWN || ( mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) && - getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getCoverDataAtSide((byte) aSide.ordinal()), aFluid, this) + getCoverBehaviorAtSideNew((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), aFluid, this) ) ) ) @@ -2055,8 +2104,8 @@ public class BaseMetaTileEntity extends BaseTileEntity implements IGregTechTileE aSide == ForgeDirection.UNKNOWN || ( mMetaTileEntity.isLiquidInput((byte) aSide.ordinal()) && - getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidIn((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getCoverDataAtSide((byte) aSide.ordinal()), null, this)) || (mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) && - getCoverBehaviorAtSide((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getCoverDataAtSide((byte) aSide.ordinal()), null, this) + getCoverBehaviorAtSideNew((byte) aSide.ordinal()).letsFluidIn((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), null, this)) || (mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) && + getCoverBehaviorAtSideNew((byte) aSide.ordinal()).letsFluidOut((byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), null, this) ) ) ) diff --git a/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java b/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java index 99e018ecdf..73a33fb9eb 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaPipeEntity.java @@ -178,7 +178,10 @@ public abstract class MetaPipeEntity implements IMetaTileEntity, IConnectable { if (difference > 1.05 && difference < 1.4) { aSide = 5; } - boolean tCovered = aSide < 6 && mBaseMetaTileEntity.getCoverIDAtSide(aSide) > 0; + boolean tCovered = false; + if (aSide < 6 && mBaseMetaTileEntity.getCoverIDAtSide(aSide) > 0) { + tCovered = true; + } if(isConnectedAtSide(aSide)){ tCovered = true; } @@ -518,9 +521,9 @@ public abstract class MetaPipeEntity implements IMetaTileEntity, IConnectable { public int[] getAccessibleSlotsFromSide(int aSide) { ArrayList<Integer> tList = new ArrayList<Integer>(); IGregTechTileEntity tTileEntity = getBaseMetaTileEntity(); - boolean tSkip = tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), -2, tTileEntity) || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), -2, tTileEntity); + boolean tSkip = tTileEntity.getCoverBehaviorAtSideNew((byte) aSide).letsItemsIn((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getComplexCoverDataAtSide((byte) aSide), -2, tTileEntity) || tTileEntity.getCoverBehaviorAtSideNew((byte) aSide).letsItemsOut((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getComplexCoverDataAtSide((byte) aSide), -2, tTileEntity); for (int i = 0; i < getSizeInventory(); i++) - if (isValidSlot(i) && (tSkip || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), i, tTileEntity) || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), i, tTileEntity))) + if (isValidSlot(i) && (tSkip || tTileEntity.getCoverBehaviorAtSideNew((byte) aSide).letsItemsOut((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getComplexCoverDataAtSide((byte) aSide), i, tTileEntity) || tTileEntity.getCoverBehaviorAtSideNew((byte) aSide).letsItemsIn((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getComplexCoverDataAtSide((byte) aSide), i, tTileEntity))) tList.add(i); int[] rArray = new int[tList.size()]; for (int i = 0; i < rArray.length; i++) rArray[i] = tList.get(i); @@ -766,7 +769,7 @@ public abstract class MetaPipeEntity implements IMetaTileEntity, IConnectable { if (tTileEntity instanceof IColoredTileEntity) { if (getBaseMetaTileEntity().getColorization() >= 0) { byte tColor = ((IColoredTileEntity) tTileEntity).getColorization(); - return tColor < 0 || tColor == getBaseMetaTileEntity().getColorization(); + if (tColor >= 0 && tColor != getBaseMetaTileEntity().getColorization()) return false; } } @@ -781,9 +784,9 @@ public abstract class MetaPipeEntity implements IMetaTileEntity, IConnectable { final IGregTechTileEntity baseMetaTile = getBaseMetaTileEntity(); if (baseMetaTile == null || !baseMetaTile.isServerSide()) return 0; - final GT_CoverBehavior coverBehavior = baseMetaTile.getCoverBehaviorAtSide(aSide); - final int coverId = baseMetaTile.getCoverIDAtSide(aSide), - coverData = baseMetaTile.getCoverDataAtSide(aSide); + final GT_CoverBehaviorBase<?> coverBehavior = baseMetaTile.getCoverBehaviorAtSideNew(aSide); + final int coverId = baseMetaTile.getCoverIDAtSide(aSide); + ISerializableObject coverData = baseMetaTile.getComplexCoverDataAtSide(aSide); boolean alwaysLookConnected = coverBehavior.alwaysLookConnected(aSide, coverId, coverData, baseMetaTile); boolean letsIn = letsIn(coverBehavior, aSide, coverId, coverData, baseMetaTile); @@ -853,6 +856,9 @@ public abstract class MetaPipeEntity implements IMetaTileEntity, IConnectable { public boolean letsIn(GT_CoverBehavior coverBehavior, byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { return false; } public boolean letsOut(GT_CoverBehavior coverBehavior, byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { return false; } + public boolean letsIn(GT_CoverBehaviorBase<?> coverBehavior, byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { return false; } + public boolean letsOut(GT_CoverBehaviorBase<?> coverBehavior, byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { return false; } + public boolean canConnect(byte aSide, TileEntity tTileEntity) { return false; } public boolean getGT6StyleConnection() { return false; } diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index e1a8d65149..b3c25ff345 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -714,9 +714,9 @@ public abstract class MetaTileEntity implements IMetaTileEntity { public int[] getAccessibleSlotsFromSide(int aSide) { ArrayList<Integer> tList = new ArrayList<Integer>(); IGregTechTileEntity tTileEntity = getBaseMetaTileEntity(); - boolean tSkip = tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), -2, tTileEntity) || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), -2, tTileEntity); + boolean tSkip = tTileEntity.getCoverBehaviorAtSideNew((byte) aSide).letsItemsIn((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getComplexCoverDataAtSide((byte) aSide), -2, tTileEntity) || tTileEntity.getCoverBehaviorAtSideNew((byte) aSide).letsItemsOut((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getComplexCoverDataAtSide((byte) aSide), -2, tTileEntity); for (int i = 0; i < getSizeInventory(); i++) - if (isValidSlot(i) && (tSkip || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), i, tTileEntity) || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), i, tTileEntity))) + if (isValidSlot(i) && (tSkip || tTileEntity.getCoverBehaviorAtSideNew((byte) aSide).letsItemsOut((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getComplexCoverDataAtSide((byte) aSide), i, tTileEntity) || tTileEntity.getCoverBehaviorAtSideNew((byte) aSide).letsItemsIn((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getComplexCoverDataAtSide((byte) aSide), i, tTileEntity))) tList.add(i); int[] rArray = new int[tList.size()]; for (int i = 0; i < rArray.length; i++) rArray[i] = tList.get(i); diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java index 439cacff91..2764eeb07e 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Cable.java @@ -1,7 +1,6 @@ package gregtech.api.metatileentity.implementations; import cofh.api.energy.IEnergyReceiver; -import com.google.common.collect.Sets; import cpw.mods.fml.common.Loader; import gregtech.GT_Mod; import gregtech.api.GregTech_API; @@ -159,7 +158,7 @@ public class GT_MetaPipeEntity_Cable extends MetaPipeEntity implements IMetaTile public long injectEnergyUnits(byte aSide, long aVoltage, long aAmperage) { if (!isConnectedAtSide(aSide) && aSide != 6) return 0; - if (!getBaseMetaTileEntity().getCoverBehaviorAtSide(aSide).letsEnergyIn(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getCoverDataAtSide(aSide), getBaseMetaTileEntity())) + if (!getBaseMetaTileEntity().getCoverBehaviorAtSideNew(aSide).letsEnergyIn(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getComplexCoverDataAtSide(aSide), getBaseMetaTileEntity())) return 0; HashSet<TileEntity> nul = null; return transferElectricity(aSide, aVoltage, aAmperage,nul); @@ -254,11 +253,21 @@ public class GT_MetaPipeEntity_Cable extends MetaPipeEntity implements IMetaTile return coverBehavior.letsEnergyOut(aSide, aCoverID, aCoverVariable, aTileEntity); } + @Override + public boolean letsIn(GT_CoverBehaviorBase<?> coverBehavior, byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return coverBehavior.letsEnergyIn(aSide, aCoverID, aCoverVariable, aTileEntity); + } + + @Override + public boolean letsOut(GT_CoverBehaviorBase<?> coverBehavior, byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return coverBehavior.letsEnergyOut(aSide, aCoverID, aCoverVariable, aTileEntity); + } + @Override public boolean canConnect(byte aSide, TileEntity tTileEntity) { final IGregTechTileEntity baseMetaTile = getBaseMetaTileEntity(); - final GT_CoverBehavior coverBehavior = baseMetaTile.getCoverBehaviorAtSide(aSide); + final GT_CoverBehaviorBase<?> coverBehavior = baseMetaTile.getCoverBehaviorAtSideNew(aSide); final byte tSide = GT_Utility.getOppositeSide(aSide); final ForgeDirection tDir = ForgeDirection.getOrientation(tSide); diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java index 128f6fa916..8479477d12 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Fluid.java @@ -15,8 +15,10 @@ import gregtech.api.metatileentity.BaseMetaPipeEntity; import gregtech.api.metatileentity.MetaPipeEntity; import gregtech.api.render.TextureFactory; import gregtech.api.util.GT_CoverBehavior; +import gregtech.api.util.GT_CoverBehaviorBase; import gregtech.api.util.GT_Log; import gregtech.api.util.GT_Utility; +import gregtech.api.util.ISerializableObject; import gregtech.api.util.WorldSpawnedEventBuilder; import gregtech.common.GT_Client; import gregtech.common.covers.GT_Cover_Drain; @@ -345,8 +347,8 @@ public class GT_MetaPipeEntity_Fluid extends MetaPipeEntity { final IGregTechTileEntity gTank = tTank instanceof IGregTechTileEntity ? (IGregTechTileEntity) tTank : null; if (isConnectedAtSide(aSide) && tTank != null && (mLastReceivedFrom & (1 << aSide)) == 0 && - getBaseMetaTileEntity().getCoverBehaviorAtSide(aSide).letsFluidOut(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getCoverDataAtSide(aSide), tFluid.getFluid(), getBaseMetaTileEntity()) && - (gTank == null || gTank.getCoverBehaviorAtSide(tSide).letsFluidIn(tSide, gTank.getCoverIDAtSide(tSide), gTank.getCoverDataAtSide(tSide), tFluid.getFluid(), gTank))) { + getBaseMetaTileEntity().getCoverBehaviorAtSideNew(aSide).letsFluidOut(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getComplexCoverDataAtSide(aSide), tFluid.getFluid(), getBaseMetaTileEntity()) && + (gTank == null || gTank.getCoverBehaviorAtSideNew(tSide).letsFluidIn(tSide, gTank.getCoverIDAtSide(tSide), gTank.getComplexCoverDataAtSide(tSide), tFluid.getFluid(), gTank))) { if (tTank.fill(ForgeDirection.getOrientation(tSide), tFluid, false) > 0) { tTanks.add(new MutableTriple<>(tTank, ForgeDirection.getOrientation(tSide), 0)); } @@ -420,6 +422,16 @@ public class GT_MetaPipeEntity_Fluid extends MetaPipeEntity { } @Override + public boolean letsIn(GT_CoverBehaviorBase<?> coverBehavior, byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return coverBehavior.letsFluidIn(aSide, aCoverID, aCoverVariable, null, aTileEntity); + } + + @Override + public boolean letsOut(GT_CoverBehaviorBase<?> coverBehavior, byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return coverBehavior.letsFluidOut(aSide, aCoverID, aCoverVariable, null, aTileEntity); + } + + @Override public boolean canConnect(byte aSide, TileEntity tTileEntity) { if (tTileEntity == null) return false; @@ -429,7 +441,7 @@ public class GT_MetaPipeEntity_Fluid extends MetaPipeEntity { if (baseMetaTile == null) return false; - final GT_CoverBehavior coverBehavior = baseMetaTile.getCoverBehaviorAtSide(aSide); + final GT_CoverBehaviorBase<?> coverBehavior = baseMetaTile.getCoverBehaviorAtSideNew(aSide); final IGregTechTileEntity gTileEntity = (tTileEntity instanceof IGregTechTileEntity) ? (IGregTechTileEntity) tTileEntity : null; if (coverBehavior instanceof GT_Cover_Drain || (GregTech_API.mTConstruct && isTConstructFaucet(tTileEntity))) @@ -442,7 +454,7 @@ public class GT_MetaPipeEntity_Fluid extends MetaPipeEntity { if (tInfo != null) { return tInfo.length > 0 || (GregTech_API.mTranslocator && isTranslocator(tTileEntity)) - || gTileEntity != null && gTileEntity.getCoverBehaviorAtSide(tSide) instanceof GT_Cover_FluidRegulator; + || gTileEntity != null && gTileEntity.getCoverBehaviorAtSideNew(tSide) instanceof GT_Cover_FluidRegulator; } } diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Item.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Item.java index edec79fe65..e316a44c80 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Item.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaPipeEntity_Item.java @@ -13,7 +13,9 @@ import gregtech.api.metatileentity.BaseMetaPipeEntity; import gregtech.api.metatileentity.MetaPipeEntity; import gregtech.api.render.TextureFactory; import gregtech.api.util.GT_CoverBehavior; +import gregtech.api.util.GT_CoverBehaviorBase; import gregtech.api.util.GT_Utility; +import gregtech.api.util.ISerializableObject; import gregtech.common.GT_Client; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; @@ -216,6 +218,16 @@ public class GT_MetaPipeEntity_Item extends MetaPipeEntity implements IMetaTileE } @Override + public boolean letsIn(GT_CoverBehaviorBase<?> coverBehavior, byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return coverBehavior.letsItemsIn(aSide, aCoverID, aCoverVariable, -1, aTileEntity); + } + + @Override + public boolean letsOut(GT_CoverBehaviorBase<?> coverBehavior, byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return coverBehavior.letsItemsOut(aSide, aCoverID, aCoverVariable, -1, aTileEntity); + } + + @Override public boolean canConnect(byte aSide, TileEntity tTileEntity) { if (tTileEntity == null) return false; @@ -271,7 +283,7 @@ public class GT_MetaPipeEntity_Item extends MetaPipeEntity implements IMetaTileE @Override public boolean insertItemStackIntoTileEntity(Object aSender, byte aSide) { - if (getBaseMetaTileEntity().getCoverBehaviorAtSide(aSide).letsItemsOut(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getCoverDataAtSide(aSide), -1, getBaseMetaTileEntity())) { + if (getBaseMetaTileEntity().getCoverBehaviorAtSideNew(aSide).letsItemsOut(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getComplexCoverDataAtSide(aSide), -1, getBaseMetaTileEntity())) { TileEntity tInventory = getBaseMetaTileEntity().getTileEntityAtSide(aSide); if (tInventory != null && !(tInventory instanceof BaseMetaPipeEntity)) { if ((!(tInventory instanceof TileEntityHopper) && !(tInventory instanceof TileEntityDispenser)) || getBaseMetaTileEntity().getMetaIDAtSide(aSide) != GT_Utility.getOppositeSide(aSide)) { @@ -320,7 +332,7 @@ public class GT_MetaPipeEntity_Item extends MetaPipeEntity implements IMetaTileE @Override public int[] getAccessibleSlotsFromSide(int aSide) { IGregTechTileEntity tTileEntity = getBaseMetaTileEntity(); - boolean tAllow = tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), -2, tTileEntity) || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), -2, tTileEntity); + boolean tAllow = tTileEntity.getCoverBehaviorAtSideNew((byte) aSide).letsItemsIn((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getComplexCoverDataAtSide((byte) aSide), -2, tTileEntity) || tTileEntity.getCoverBehaviorAtSideNew((byte) aSide).letsItemsOut((byte) aSide, tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getComplexCoverDataAtSide((byte) aSide), -2, tTileEntity); if (tAllow) { if (cacheSides == null) cacheSides = super.getAccessibleSlotsFromSide(aSide); diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine.java index 7c15137691..e8cac808dd 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine.java @@ -10,6 +10,7 @@ import gregtech.api.interfaces.metatileentity.IMachineCallback; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.objects.GT_ItemStack; import gregtech.api.render.TextureFactory; +import gregtech.api.util.GT_CoverBehaviorBase; import gregtech.api.util.GT_Log; import gregtech.api.util.GT_OreDictUnificator; import gregtech.api.util.GT_Recipe; @@ -823,8 +824,9 @@ public abstract class GT_MetaTileEntity_BasicMachine extends GT_MetaTileEntity_B @Override public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCoverID) { - return (aSide != mMainFacing || GregTech_API.getCoverBehavior(aCoverID.toStack()).isGUIClickable(aSide, GT_Utility.stackToInt(aCoverID.toStack()), 0, getBaseMetaTileEntity())); - } + if (aSide != mMainFacing) return true; + GT_CoverBehaviorBase<?> tBehavior = GregTech_API.getCoverBehaviorNew(aCoverID.toStack()); + return tBehavior.isGUIClickable(aSide, GT_Utility.stackToInt(aCoverID.toStack()), tBehavior.createDataObject(), getBaseMetaTileEntity());} @Override public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, byte aSide, ItemStack aStack) { diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine_Bronze.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine_Bronze.java index 3cdb26c9e1..d573c6bfd1 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine_Bronze.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine_Bronze.java @@ -186,7 +186,7 @@ public abstract class GT_MetaTileEntity_BasicMachine_Bronze extends GT_MetaTileE @Override public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCoverID) { - return GregTech_API.getCoverBehavior(aCoverID.toStack()).isSimpleCover() && super.allowCoverOnSide(aSide, aCoverID); + return GregTech_API.getCoverBehaviorNew(aCoverID.toStack()).isSimpleCover() && super.allowCoverOnSide(aSide, aCoverID); } public float getSteamDamage() { diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBus.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBus.java index 37a98162b8..2b7e50519d 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBus.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBus.java @@ -185,7 +185,7 @@ public class GT_MetaTileEntity_Hatch_InputBus extends GT_MetaTileEntity_Hatch { @Override public void onScrewdriverRightClick(byte aSide, EntityPlayer aPlayer, float aX, float aY, float aZ) { - if (!getBaseMetaTileEntity().getCoverBehaviorAtSide(aSide).isGUIClickable(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getCoverDataAtSide(aSide), getBaseMetaTileEntity())) + if (!getBaseMetaTileEntity().getCoverBehaviorAtSideNew(aSide).isGUIClickable(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getComplexCoverDataAtSide(aSide), getBaseMetaTileEntity())) return; if (aPlayer.isSneaking()) { if(disableSort) { diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Output.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Output.java index 7c518dbd2d..d848b06b07 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Output.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Output.java @@ -202,7 +202,7 @@ public class GT_MetaTileEntity_Hatch_Output extends GT_MetaTileEntity_Hatch { @Override public void onScrewdriverRightClick(byte aSide, EntityPlayer aPlayer, float aX, float aY, float aZ) { - if (!getBaseMetaTileEntity().getCoverBehaviorAtSide(aSide).isGUIClickable(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getCoverDataAtSide(aSide), getBaseMetaTileEntity())) + if (!getBaseMetaTileEntity().getCoverBehaviorAtSideNew(aSide).isGUIClickable(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getComplexCoverDataAtSide(aSide), getBaseMetaTileEntity())) return; if (aPlayer.isSneaking()) { mMode = (byte) ((mMode + 9) % 10); @@ -269,7 +269,7 @@ public class GT_MetaTileEntity_Hatch_Output extends GT_MetaTileEntity_Hatch { } private boolean tryToLockHatch(EntityPlayer aPlayer, byte aSide) { - if (!getBaseMetaTileEntity().getCoverBehaviorAtSide(aSide).isGUIClickable(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getCoverDataAtSide(aSide), getBaseMetaTileEntity())) + if (!getBaseMetaTileEntity().getCoverBehaviorAtSideNew(aSide).isGUIClickable(aSide, getBaseMetaTileEntity().getCoverIDAtSide(aSide), getBaseMetaTileEntity().getComplexCoverDataAtSide(aSide), getBaseMetaTileEntity())) return false; if (!isFluidLocked()) return false; diff --git a/src/main/java/gregtech/api/net/GT_Packet_TileEntityCover.java b/src/main/java/gregtech/api/net/GT_Packet_TileEntityCover.java index 29220e05ab..8035030f19 100644 --- a/src/main/java/gregtech/api/net/GT_Packet_TileEntityCover.java +++ b/src/main/java/gregtech/api/net/GT_Packet_TileEntityCover.java @@ -10,9 +10,8 @@ import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; /** - * Client -> Server: Update cover data + * Client -> Server: Update cover data. use this only if you are using the legacy data storage */ - public class GT_Packet_TileEntityCover extends GT_Packet_New { protected int mX; protected short mY; diff --git a/src/main/java/gregtech/api/net/GT_Packet_TileEntityCoverGUI.java b/src/main/java/gregtech/api/net/GT_Packet_TileEntityCoverGUI.java index 2a8091144d..e5cb184339 100644 --- a/src/main/java/gregtech/api/net/GT_Packet_TileEntityCoverGUI.java +++ b/src/main/java/gregtech/api/net/GT_Packet_TileEntityCoverGUI.java @@ -1,9 +1,11 @@ package gregtech.api.net; import com.google.common.io.ByteArrayDataInput; +import gregtech.api.GregTech_API; import gregtech.api.enums.GT_Values; import gregtech.api.interfaces.tileentity.ICoverable; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.util.ISerializableObject; import gregtech.common.GT_Proxy; import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; @@ -16,14 +18,14 @@ import net.minecraft.world.World; /** * Server -> Client: Show GUI */ - public class GT_Packet_TileEntityCoverGUI extends GT_Packet_New { protected int mX; protected short mY; protected int mZ; protected byte side; - protected int coverID, coverData, dimID, playerID; + protected int coverID, dimID, playerID; + protected ISerializableObject coverData; public GT_Packet_TileEntityCoverGUI() { super(true); @@ -37,12 +39,25 @@ public class GT_Packet_TileEntityCoverGUI extends GT_Packet_New { this.side = coverSide; this.coverID = coverID; - this.coverData = coverData; + this.coverData = new ISerializableObject.LegacyCoverData(coverData); this.dimID = dimID; this.playerID = playerID; } + public GT_Packet_TileEntityCoverGUI(int mX, short mY, int mZ, byte coverSide, int coverID, ISerializableObject coverData, int dimID, int playerID) { + super(false); + this.mX = mX; + this.mY = mY; + this.mZ = mZ; + + this.side = coverSide; + this.coverID = coverID; + this.coverData = coverData; + this.dimID = dimID; + this.playerID = playerID; + } + public GT_Packet_TileEntityCoverGUI(byte side, int coverID, int coverData, ICoverable tile, EntityPlayerMP aPlayer) { super(false); @@ -53,7 +68,7 @@ public class GT_Packet_TileEntityCoverGUI extends GT_Packet_New { this.side = side; this.coverID = coverID; - this.coverData = coverData; + this.coverData = new ISerializableObject.LegacyCoverData(coverData); this.dimID = tile.getWorld().provider.dimensionId; this.playerID = aPlayer.getEntityId(); @@ -67,11 +82,25 @@ public class GT_Packet_TileEntityCoverGUI extends GT_Packet_New { this.side = coverSide; this.coverID = coverID; - this.coverData = coverData; + this.coverData = new ISerializableObject.LegacyCoverData(coverData); this.dimID = tile.getWorld().provider.dimensionId; } + public GT_Packet_TileEntityCoverGUI(byte side, int coverID, ISerializableObject coverData, ICoverable tile, EntityPlayerMP aPlayer) { + super(false); + this.mX = tile.getXCoord(); + this.mY = tile.getYCoord(); + this.mZ = tile.getZCoord(); + + this.side = side; + this.coverID = coverID; + this.coverData = coverData.copy(); // make a copy so we don't get a race condition + + this.dimID = tile.getWorld().provider.dimensionId; + this.playerID = aPlayer.getEntityId(); + } + @Override public byte getPacketID() { return 7; @@ -85,7 +114,7 @@ public class GT_Packet_TileEntityCoverGUI extends GT_Packet_New { aOut.writeByte(side); aOut.writeInt(coverID); - aOut.writeInt(coverData); + coverData.writeToByteBuf(aOut); aOut.writeInt(dimID); aOut.writeInt(playerID); @@ -93,14 +122,15 @@ public class GT_Packet_TileEntityCoverGUI extends GT_Packet_New { @Override public GT_Packet_New decode(ByteArrayDataInput aData) { + int coverID; return new GT_Packet_TileEntityCoverGUI( aData.readInt(), aData.readShort(), aData.readInt(), aData.readByte(), - aData.readInt(), - aData.readInt(), + coverID = aData.readInt(), + GregTech_API.getCoverBehaviorNew(coverID).createDataObject().readFromPacket(aData, null), aData.readInt(), aData.readInt()); diff --git a/src/main/java/gregtech/api/net/GT_Packet_TileEntityCoverNew.java b/src/main/java/gregtech/api/net/GT_Packet_TileEntityCoverNew.java new file mode 100644 index 0000000000..f600fb1d82 --- /dev/null +++ b/src/main/java/gregtech/api/net/GT_Packet_TileEntityCoverNew.java @@ -0,0 +1,113 @@ +package gregtech.api.net; + +import com.google.common.io.ByteArrayDataInput; +import gregtech.api.GregTech_API; +import gregtech.api.interfaces.tileentity.ICoverable; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.util.ISerializableObject; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.INetHandler; +import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; + +/** + * Client -> Server: Update cover data + */ + +public class GT_Packet_TileEntityCoverNew extends GT_Packet_New { + protected int mX; + protected short mY; + protected int mZ; + + protected byte side; + protected int coverID, dimID; + protected ISerializableObject coverData; + + protected EntityPlayerMP mPlayer; + + public GT_Packet_TileEntityCoverNew() { + super(true); + } + + public GT_Packet_TileEntityCoverNew(int mX, short mY, int mZ, byte coverSide, int coverID, ISerializableObject coverData, int dimID) { + super(false); + this.mX = mX; + this.mY = mY; + this.mZ = mZ; + + this.side = coverSide; + this.coverID = coverID; + this.coverData = coverData; + + this.dimID = dimID; + } + public GT_Packet_TileEntityCoverNew(byte coverSide, int coverID, ISerializableObject coverData, ICoverable tile) { + super(false); + this.mX = tile.getXCoord(); + this.mY = tile.getYCoord(); + this.mZ = tile.getZCoord(); + + this.side = coverSide; + this.coverID = coverID; + this.coverData = coverData; + + this.dimID = tile.getWorld().provider.dimensionId; + } + + @Override + public byte getPacketID() { + return 11; + } + + @Override + public void setINetHandler(INetHandler aHandler) { + if (aHandler instanceof NetHandlerPlayServer) { + mPlayer = ((NetHandlerPlayServer) aHandler).playerEntity; + } + } + + @Override + public void encode(ByteBuf aOut) { + aOut.writeInt(mX); + aOut.writeShort(mY); + aOut.writeInt(mZ); + + aOut.writeByte(side); + aOut.writeInt(coverID); + coverData.writeToByteBuf(aOut); + + aOut.writeInt(dimID); + } + + @Override + public GT_Packet_New decode(ByteArrayDataInput aData) { + int coverId; + return new GT_Packet_TileEntityCoverNew( + aData.readInt(), + aData.readShort(), + aData.readInt(), + + aData.readByte(), + coverId = aData.readInt(), + GregTech_API.getCoverBehaviorNew(coverId).createDataObject().readFromPacket(aData, mPlayer), + + aData.readInt()); + } + + @Override + public void process(IBlockAccess aWorld) { + if (mPlayer == null) // impossible, but who knows + return; + World world = DimensionManager.getWorld(dimID); + if (world != null) { + TileEntity tile = world.getTileEntity(mX, mY, mZ); + if (tile instanceof IGregTechTileEntity && !((IGregTechTileEntity) tile).isDead()) { + ((IGregTechTileEntity) tile).receiveCoverData(side, coverID, coverData, mPlayer); + } + } + } +} diff --git a/src/main/java/gregtech/api/objects/GT_UO_Dimension.java b/src/main/java/gregtech/api/objects/GT_UO_Dimension.java index 1c090eb9b5..0d05e6d229 100644 --- a/src/main/java/gregtech/api/objects/GT_UO_Dimension.java +++ b/src/main/java/gregtech/api/objects/GT_UO_Dimension.java @@ -39,4 +39,11 @@ public class GT_UO_Dimension { return null; } + public String getUOFluidKey(GT_UO_Fluid uoFluid) { + return fFluids.inverse().get(uoFluid); + } + + public GT_UO_Fluid getUOFluid(String key) { + return fFluids.get(key); + } } diff --git a/src/main/java/gregtech/api/util/GT_ChunkAssociatedData.java b/src/main/java/gregtech/api/util/GT_ChunkAssociatedData.java new file mode 100644 index 0000000000..bd9148b516 --- /dev/null +++ b/src/main/java/gregtech/api/util/GT_ChunkAssociatedData.java @@ -0,0 +1,437 @@ +package gregtech.api.util; + +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import gregtech.api.enums.GT_Values; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.WorldEvent; +import org.apache.commons.io.FileUtils; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.lang.reflect.Array; +import java.nio.file.AtomicMoveNotSupportedException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.Arrays; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * A utility to save all kinds of data that is a function of any chunk. + * <p> + * GregTech takes care of saving and loading the data from disk, and an efficient mechanism to locate it. + * Subclass only need to define the exact scheme of each element data (by overriding the three protected abstract method) + * <p> + * Oh, there is no limit on how large your data is, though you'd not have the familiar NBT interface, but DataOutput + * should be reasonably common anyway. + * <p> + * It should be noted this class is NOT thread safe. + * <p> + * Element cannot be null. + * <p> + * TODO: Implement automatic region unloading. + * + * @param <T> data element type + * @author glease + */ +@ParametersAreNonnullByDefault +public abstract class GT_ChunkAssociatedData<T extends GT_ChunkAssociatedData.IData> { + private static final Map<String, GT_ChunkAssociatedData<?>> instances = new ConcurrentHashMap<>(); + private static final int IO_PARALLELISM = Math.min(8, Math.max(1, Runtime.getRuntime().availableProcessors()) * 2 / 3); + private static final ExecutorService IO_WORKERS = Executors.newWorkStealingPool(IO_PARALLELISM); + private static final Pattern FILE_PATTERN = Pattern.compile("(.+)\\.(-?\\d+)\\.(-?\\d+)\\.dat"); + + static { + // register event handler + new EventHandler(); + } + + protected final String mId; + protected final Class<T> elementtype; + private final int regionLength; + private final int version; + private final boolean saveDefaults; + /** + * Data is stored as a `(world id -> (super region id -> super region data))` hash map. + * where super region's size is determined by regionSize. + * Here it is called super region, to not confuse with vanilla's regions. + */ + private final Map<Integer, Map<ChunkCoordIntPair, SuperRegion>> masterMap = new ConcurrentHashMap<>(); + + /** + * Initialize this instance. + * + * @param aId An arbitrary, but globally unique identifier for what this data is + * @param elementType The class of this element type. Used to create arrays. + * @param regionLength The length of one super region. Each super region will contain {@code regionLength * regionLength} chunks + * @param version An integer marking the version of this data. Useful later when the data's serialized form changed. + */ + protected GT_ChunkAssociatedData(String aId, Class<T> elementType, int regionLength, byte version, boolean saveDefaults) { + if (regionLength * regionLength > Short.MAX_VALUE || regionLength <= 0) + throw new IllegalArgumentException("Region invalid: " + regionLength); + if (!IData.class.isAssignableFrom(elementType)) + throw new IllegalArgumentException("Data type invalid"); + if (aId.contains(".")) + throw new IllegalArgumentException("ID cannot contains dot"); + this.mId = aId; + this.elementtype = elementType; + this.regionLength = regionLength; + this.version = version; + this.saveDefaults = saveDefaults; + if (instances.putIfAbsent(aId, this) != null) + throw new IllegalArgumentException("Duplicate GT_ChunkAssociatedData: " + aId); + } + + private ChunkCoordIntPair getRegionID(int aChunkX, int aChunkZ) { + return new ChunkCoordIntPair(aChunkX / regionLength, aChunkZ / regionLength); + } + + /** + * Get a reference to data of the chunk that tile entity is in. + * The returned reference should be mutable. + */ + public final T get(IGregTechTileEntity tileEntity) { + return get(tileEntity.getWorld(), tileEntity.getXCoord() >> 4, tileEntity.getZCoord() >> 4); + } + + public final T get(Chunk chunk) { + return get(chunk.worldObj, chunk.xPosition, chunk.zPosition); + } + + public final T get(World world, ChunkCoordIntPair coord) { + return get(world, coord.chunkXPos, coord.chunkZPos); + } + + public final T get(World world, int chunkX, int chunkZ) { + SuperRegion region = masterMap.computeIfAbsent(world.provider.dimensionId, ignored -> new ConcurrentHashMap<>()) + .computeIfAbsent(getRegionID(chunkX, chunkZ), c -> new SuperRegion(world, c)); + return region.get(Math.floorMod(chunkX, regionLength), Math.floorMod(chunkZ, regionLength)); + } + + protected final void set(World world, int chunkX, int chunkZ, T data) { + SuperRegion region = masterMap.computeIfAbsent(world.provider.dimensionId, ignored -> new ConcurrentHashMap<>()) + .computeIfAbsent(getRegionID(chunkX, chunkZ), c -> new SuperRegion(world, c)); + region.set(Math.floorMod(chunkX, regionLength), Math.floorMod(chunkZ, regionLength), data); + } + + protected final boolean isCreated(int dimId, int chunkX, int chunkZ) { + Map<ChunkCoordIntPair, SuperRegion> dimData = masterMap.getOrDefault(dimId, null); + if (dimData == null) return false; + + SuperRegion region = dimData.getOrDefault(getRegionID(chunkX, chunkZ), null); + if (region == null) return false; + + return region.isCreated(Math.floorMod(chunkX, regionLength), Math.floorMod(chunkZ, regionLength)); + } + + public void clear() { + if (GT_Values.debugWorldData) { + long dirtyRegionCount = masterMap.values().stream() + .flatMap(m -> m.values().stream()) + .filter(SuperRegion::isDirty) + .count(); + if (dirtyRegionCount > 0) + GT_Log.out.println("Clearing ChunkAssociatedData with " + dirtyRegionCount + " regions dirty. Data might have been lost!"); + } + masterMap.clear(); + } + + public void save() { + saveRegions(masterMap.values().stream().flatMap(m -> m.values().stream())); + } + + public void save(World world) { + Map<ChunkCoordIntPair, SuperRegion> map = masterMap.get(world.provider.dimensionId); + if (map != null) + saveRegions(map.values().stream()); + } + + private void saveRegions(Stream<SuperRegion> stream) { + stream.filter(r -> !r.isDirty()) + .map(c -> (Runnable) c::save) + .map(r -> CompletableFuture.runAsync(r, IO_WORKERS)) + .reduce(CompletableFuture::allOf) + .ifPresent(f -> { + try { + f.get(); + } catch (Exception e) { + GT_Log.err.println("Data save error: " + mId); + e.printStackTrace(GT_Log.err); + } + }); + } + + protected abstract void writeElement(DataOutput output, T element, World world, int chunkX, int chunkZ) throws IOException; + + protected abstract T readElement(DataInput input, int version, World world, int chunkX, int chunkZ) throws IOException; + + protected abstract T createElement(World world, int chunkX, int chunkZ); + + /** + * Clear all mappings, regardless of whether they are dirty + */ + public static void clearAll() { + for (GT_ChunkAssociatedData<?> d : instances.values()) d.clear(); + } + + /** + * Save all mappings + */ + public static void saveAll() { + for (GT_ChunkAssociatedData<?> d : instances.values()) d.save(); + } + + /** + * Load data for all chunks for a given world. + * Current data for that world will be discarded. If this is what you intended, call {@link #save(World)} beforehand. + * <p> + * Be aware of the memory consumption though. + */ + protected void loadAll(World w) { + if (GT_Values.debugWorldData && masterMap.containsKey(w.provider.dimensionId)) + GT_Log.err.println("Reloading ChunkAssociatedData " + mId + " for world " + w.provider.dimensionId + " discards old data!"); + if (!getSaveDirectory(w).isDirectory()) + // nothing to load... + return; + try { + Map<ChunkCoordIntPair, SuperRegion> worldData = Files.list(getSaveDirectory(w).toPath()) + .map(f -> { + Matcher matcher = FILE_PATTERN.matcher(f.getFileName().toString()); + return matcher.matches() ? matcher : null; + }) + .filter(Objects::nonNull) + .filter(m -> mId.equals(m.group(1))) + .map(m -> CompletableFuture.supplyAsync(() -> new SuperRegion(w, Integer.parseInt(m.group(2)), Integer.parseInt(m.group(3))), IO_WORKERS)) + .map(f -> { + try { + return f.get(); + } catch (Exception e) { + GT_Log.err.println("Error loading region"); + e.printStackTrace(GT_Log.err); + return null; + } + }) + .filter(Objects::nonNull) + .collect(Collectors.toMap(SuperRegion::getCoord, Function.identity())); + masterMap.put(w.provider.dimensionId, worldData); + } catch (IOException e) { + GT_Log.err.println("Error loading all region"); + e.printStackTrace(GT_Log.err); + } + } + + protected File getSaveDirectory(World w) { + return new File(w.getSaveHandler().getWorldDirectory(), "gregtech"); + } + + public interface IData { + /** + * @return Whether the data is different from chunk default + */ + boolean isSameAsDefault(); + } + + protected final class SuperRegion { + private final T[] data = createData(); + private final File backingStorage; + private final WeakReference<World> world; + private final ChunkCoordIntPair coord; + + private SuperRegion(World world, int chunkX, int chunkZ) { + this.world = new WeakReference<>(world); + this.coord = new ChunkCoordIntPair(chunkX, chunkZ); + backingStorage = new File(getSaveDirectory(world), String.format("%s.%d.%d.dat", mId, chunkX, chunkZ)); + if (backingStorage.isFile()) + load(); + } + + private SuperRegion(World world, ChunkCoordIntPair coord) { + this.world = new WeakReference<>(world); + this.coord = coord; + backingStorage = new File(getSaveDirectory(world), String.format("%s.%d.%d.dat", mId, coord.chunkXPos, coord.chunkZPos)); + if (backingStorage.isFile()) + load(); + } + + @SuppressWarnings("unchecked") + private T[] createData() { + return (T[]) Array.newInstance(elementtype, regionLength * regionLength); + } + + public T get(int subRegionX, int subRegionZ) { + int index = getIndex(subRegionX, subRegionZ); + T datum = data[index]; + if (datum == null) { + World world = Objects.requireNonNull(this.world.get()); + T newElem = createElement(world, coord.chunkXPos * regionLength + subRegionX, coord.chunkZPos * regionLength + subRegionZ); + data[index] = newElem; + return newElem; + } + return datum; + } + + public void set(int subRegionX, int subRegionZ, T data) { + this.data[getIndex(subRegionX, subRegionZ)] = data; + } + + public boolean isCreated(int subRegionX, int subRegionZ) { + return this.data[getIndex(subRegionX, subRegionZ)] == null; + } + + public ChunkCoordIntPair getCoord() { + return coord; + } + + private int getIndex(int subRegionX, int subRegionY) { + return subRegionX * regionLength + subRegionY; + } + + private int getChunkX(int index) { + return index / regionLength + coord.chunkXPos; + } + + private int getChunkZ(int index) { + return index % regionLength + coord.chunkZPos; + } + + public boolean isDirty() { + for (T datum : data) { + if (datum != null && datum.isSameAsDefault()) + return true; + } + return false; + } + + public void save() { + try { + save0(); + } catch (IOException e) { + GT_Log.err.println("Error saving data " + backingStorage.getPath()); + e.printStackTrace(GT_Log.err); + } + } + + private void save0() throws IOException { + if (!isDirty()) + return; + //noinspection ResultOfMethodCallIgnored + backingStorage.getParentFile().mkdirs(); + File tmpFile = getTmpFile(); + World world = Objects.requireNonNull(this.world.get(), "Attempting to save region of another world!"); + try (DataOutputStream output = new DataOutputStream(new FileOutputStream(tmpFile))) { + int ptr = 0; + boolean nullRange = data[0] == null; + // write a magic byte as storage format version + output.writeByte(0); + // write a magic byte as data format version + output.writeByte(version); + output.writeBoolean(nullRange); + while (ptr < data.length) { + // work out how long is this range + int rangeStart = ptr; + while (ptr < data.length && (data[ptr] == null || (!saveDefaults && data[ptr].isSameAsDefault())) == nullRange) + ptr++; + // write range length + output.writeShort(ptr - rangeStart); + if (!nullRange) + // write element data + for (int i = rangeStart; i < ptr; i++) + writeElement(output, data[i], world, getChunkX(ptr), getChunkZ(ptr)); + // or not + nullRange = !nullRange; + } + } + // first try to replace the destination file + // since atomic operation, no need to keep the backup in place + try { + Files.move(tmpFile.toPath(), backingStorage.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); + } catch (AtomicMoveNotSupportedException ignored) { + // in case some dumb system/jre combination would cause this + // or if **somehow** two file inside the same directory belongs two separate filesystem + FileUtils.copyFile(tmpFile, backingStorage); + } + } + + public void load() { + try { + loadFromFile(backingStorage); + } catch (IOException | RuntimeException e) { + GT_Log.err.println("Primary storage file broken in " + backingStorage.getPath()); + e.printStackTrace(GT_Log.err); + // in case the primary storage is broken + try { + loadFromFile(getTmpFile()); + } catch (IOException | RuntimeException e2) { + GT_Log.err.println("Backup storage file broken in " + backingStorage.getPath()); + e2.printStackTrace(GT_Log.err); + } + } + } + + private void loadFromFile(File file) throws IOException { + World world = Objects.requireNonNull(this.world.get(), "Attempting to load region of another world!"); + try (DataInputStream input = new DataInputStream(new FileInputStream(file))) { + boolean nullRange = input.readBoolean(); + int ptr = 0; + while (ptr != data.length) { + int rangeEnd = ptr + input.readUnsignedShort(); + if (!nullRange) { + for (; ptr < rangeEnd; ptr++) { + data[ptr] = readElement(input, version, world, getChunkX(ptr), getChunkZ(ptr)); + } + } else { + Arrays.fill(data, ptr, rangeEnd, null); + ptr = rangeEnd; + } + } + } + } + + private File getTmpFile() { + return new File(backingStorage.getParentFile(), backingStorage.getName() + ".tmp"); + } + } + + public static class EventHandler { + private EventHandler() { + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void onWorldSave(WorldEvent.Save e) { + for (GT_ChunkAssociatedData<?> d : instances.values()) { + d.save(e.world); + } + } + + @SubscribeEvent + public void onWorldUnload(WorldEvent.Unload e) { + for (GT_ChunkAssociatedData<?> d : instances.values()) { + // there is no need to explicitly do a save here + // forge will send a WorldEvent.Save on server thread before this event is distributed + d.masterMap.remove(e.world.provider.dimensionId); + } + } + } +} diff --git a/src/main/java/gregtech/api/util/GT_CoverBehavior.java b/src/main/java/gregtech/api/util/GT_CoverBehavior.java index 14c8cc1308..9972331eb3 100644 --- a/src/main/java/gregtech/api/util/GT_CoverBehavior.java +++ b/src/main/java/gregtech/api/util/GT_CoverBehavior.java @@ -3,21 +3,179 @@ package gregtech.api.util; import gregtech.api.enums.GT_Values; import gregtech.api.interfaces.tileentity.ICoverable; import gregtech.api.net.GT_Packet_TileEntityCoverGUI; -import gregtech.api.objects.GT_ItemStack; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; +import net.minecraft.world.World; import net.minecraftforge.fluids.Fluid; import static gregtech.api.enums.GT_Values.E; /** - * For Covers with a special behavior. + * For Covers with a special behavior. Has fixed storage format of 4 byte. Not very convenient... */ -public abstract class GT_CoverBehavior { +public abstract class GT_CoverBehavior extends GT_CoverBehaviorBase<ISerializableObject.LegacyCoverData> { public EntityPlayer lastPlayer = null; + public GT_CoverBehavior() { + super(ISerializableObject.LegacyCoverData.class); + } + + private static int convert(ISerializableObject.LegacyCoverData data) { + return data == null ? 0 : data.get(); + } + + // region bridge the parent call to legacy calls + + @Override + public final ISerializableObject.LegacyCoverData createDataObject() { + return new ISerializableObject.LegacyCoverData(); + } + + @Override + public ISerializableObject.LegacyCoverData createDataObject(int aLegacyData) { + return new ISerializableObject.LegacyCoverData(aLegacyData); + } + + @Override + protected boolean isRedstoneSensitiveImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, long aTimer) { + return isRedstoneSensitive(aSide, aCoverID, aCoverVariable.get(), aTileEntity, aTimer); + } + + @Override + protected ISerializableObject.LegacyCoverData doCoverThingsImpl(byte aSide, byte aInputRedstone, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, long aTimer) { + if (aCoverVariable == null) + aCoverVariable = new ISerializableObject.LegacyCoverData(); + aCoverVariable.set(doCoverThings(aSide, aInputRedstone, aCoverID, aCoverVariable.get(), aTileEntity, aTimer)); + return aCoverVariable; + } + + @Override + protected boolean onCoverRightClickImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + return onCoverRightclick(aSide, aCoverID, convert(aCoverVariable), aTileEntity, aPlayer, aX, aY, aZ); + } + + @Override + protected ISerializableObject.LegacyCoverData onCoverScrewdriverClickImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + if (aCoverVariable == null) + aCoverVariable = new ISerializableObject.LegacyCoverData(); + aCoverVariable.set(onCoverScrewdriverclick(aSide, aCoverID, convert(aCoverVariable), aTileEntity, aPlayer, aX, aY, aZ)); + return aCoverVariable; + } + + @Override + protected boolean onCoverShiftRightClickImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer) { + return onCoverShiftRightclick(aSide, aCoverID, convert(aCoverVariable), aTileEntity, aPlayer); + } + + @Override + protected Object getClientGUIImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, World aWorld) { + return getClientGUI(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected boolean onCoverRemovalImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, boolean aForced) { + return onCoverRemoval(aSide, aCoverID, convert(aCoverVariable), aTileEntity, aForced); + } + + @Override + protected String getDescriptionImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return getDescription(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected float getBlastProofLevelImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return getBlastProofLevel(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected boolean letsRedstoneGoInImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return letsRedstoneGoIn(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected boolean letsRedstoneGoOutImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return letsRedstoneGoOut(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected boolean letsFibreGoInImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return letsFibreGoIn(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected boolean letsFibreGoOutImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return letsFibreGoOut(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected boolean letsEnergyInImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return letsEnergyIn(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected boolean letsEnergyOutImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return letsEnergyOut(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected boolean letsFluidInImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + return letsFluidIn(aSide, aCoverID, convert(aCoverVariable), aFluid, aTileEntity); + } + + @Override + protected boolean letsFluidOutImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + return letsFluidOut(aSide, aCoverID, convert(aCoverVariable), aFluid, aTileEntity); + } + + @Override + protected boolean letsItemsInImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, int aSlot, ICoverable aTileEntity) { + return letsItemsIn(aSide, aCoverID, convert(aCoverVariable), aSlot, aTileEntity); + } + + @Override + protected boolean letsItemsOutImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, int aSlot, ICoverable aTileEntity) { + return letsItemsOut(aSide, aCoverID, convert(aCoverVariable), aSlot, aTileEntity); + } + + @Override + protected boolean isGUIClickableImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return isGUIClickable(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected boolean manipulatesSidedRedstoneOutputImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return manipulatesSidedRedstoneOutput(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected boolean alwaysLookConnectedImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return alwaysLookConnected(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected byte getRedstoneInputImpl(byte aSide, byte aInputRedstone, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return getRedstoneInput(aSide, aInputRedstone, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected int getTickRateImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return getTickRate(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected byte getLensColorImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return getLensColor(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + @Override + protected ItemStack getDropImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity) { + return getDrop(aSide, aCoverID, convert(aCoverVariable), aTileEntity); + } + + // endregion + public boolean isRedstoneSensitive(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, long aTimer) { return true; } @@ -39,15 +197,6 @@ public abstract class GT_CoverBehavior { } /** - * Called when someone rightclicks this Cover Client Side - * <p/> - * return true, if something actually happens. - */ - public boolean onCoverRightclickClient(byte aSide, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { - return false; - } - - /** * Called when someone rightclicks this Cover with a Screwdriver. Doesn't call @onCoverRightclick in this Case. * <p/> * return the new Value of the Cover Variable @@ -68,22 +217,11 @@ public abstract class GT_CoverBehavior { return false; } - public boolean hasCoverGUI() { - return false; - } - public Object getClientGUI(byte aSide, int aCoverID, int coverData, ICoverable aTileEntity) { return null; } /** - * Checks if the Cover can be placed on this. - */ - public boolean isCoverPlaceable(byte aSide, GT_ItemStack aStack, ICoverable aTileEntity) { - return true; - } - - /** * Removes the Cover if this returns true, or if aForced is true. * Doesn't get called when the Machine Block is getting broken, only if you break the Cover away from the Machine. */ @@ -219,13 +357,6 @@ public abstract class GT_CoverBehavior { } /** - * If this is a simple Cover, which can also be used on Bronze Machines and similar. - */ - public boolean isSimpleCover() { - return false; - } - - /** * The MC Color of this Lens. -1 for no Color (meaning this isn't a Lens then). */ public byte getLensColor(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { @@ -238,15 +369,4 @@ public abstract class GT_CoverBehavior { public ItemStack getDrop(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { return GT_OreDictUnificator.get(true, aTileEntity.getCoverItemAtSide(aSide)); } - - /** - * @return sets the Cover upon placement. - */ - public void placeCover(byte aSide, ItemStack aCover, ICoverable aTileEntity) { - aTileEntity.setCoverIDAtSide(aSide, GT_Utility.stackToInt(aCover)); - } - - public String trans(String aNr, String aEnglish){ - return GT_LanguageManager.addStringLocalization("Interaction_DESCRIPTION_Index_"+aNr, aEnglish, false); - } } diff --git a/src/main/java/gregtech/api/util/GT_CoverBehaviorBase.java b/src/main/java/gregtech/api/util/GT_CoverBehaviorBase.java new file mode 100644 index 0000000000..50ef2632d9 --- /dev/null +++ b/src/main/java/gregtech/api/util/GT_CoverBehaviorBase.java @@ -0,0 +1,482 @@ +package gregtech.api.util; + +import gregtech.api.enums.GT_Values; +import gregtech.api.interfaces.tileentity.ICoverable; +import gregtech.api.net.GT_Packet_TileEntityCoverGUI; +import gregtech.api.objects.GT_ItemStack; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.world.World; +import net.minecraftforge.fluids.Fluid; + +import static gregtech.api.enums.GT_Values.E; + +/** + * For Covers with a special behavior. + * + * @author glease + */ +public abstract class GT_CoverBehaviorBase<T extends ISerializableObject> { + + public EntityPlayer lastPlayer = null; + private final Class<T> typeToken; + + protected GT_CoverBehaviorBase(Class<T> typeToken) { + this.typeToken = typeToken; + } + + public abstract T createDataObject(int aLegacyData); + + public abstract T createDataObject(); + + public T createDataObject(NBTBase aNBT) { + T ret = createDataObject(); + ret.loadDataFromNBT(aNBT); + return ret; + } + + public final T cast(ISerializableObject aData) { + if (typeToken.isInstance(aData)) + return forceCast(aData); + return null; + } + + private T forceCast(ISerializableObject aData) { + return typeToken.cast(aData); + } + + // region facade + + public final boolean isRedstoneSensitive(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity, long aTimer) { + return isRedstoneSensitiveImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity, aTimer); + } + + /** + * Called by updateEntity inside the covered TileEntity. aCoverVariable is the Value you returned last time. + */ + public final T doCoverThings(byte aSide, byte aInputRedstone, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity, long aTimer) { + return doCoverThingsImpl(aSide, aInputRedstone, aCoverID, forceCast(aCoverVariable), aTileEntity, aTimer); + } + + /** + * Called when someone rightclicks this Cover. + * <p/> + * return true, if something actually happens. + */ + public final boolean onCoverRightClick(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + return onCoverRightClickImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity, aPlayer, aX, aY, aZ); + } + + /** + * Called when someone rightclicks this Cover with a Screwdriver. Doesn't call @onCoverRightclick in this Case. + * <p/> + * return the new Value of the Cover Variable + */ + public final T onCoverScrewdriverClick(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + return onCoverScrewdriverClickImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity, aPlayer, aX, aY, aZ); + } + + /** + * Called when someone shift-rightclicks this Cover with no tool. Doesn't call @onCoverRightclick in this Case. + */ + public final boolean onCoverShiftRightClick(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer) { + return onCoverShiftRightClickImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity, aPlayer); + } + + public final Object getClientGUI(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, World aWorld) { + return getClientGUIImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity, aPlayer, aWorld); + } + + /** + * Removes the Cover if this returns true, or if aForced is true. + * Doesn't get called when the Machine Block is getting broken, only if you break the Cover away from the Machine. + */ + public final boolean onCoverRemoval(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity, boolean aForced) { + return onCoverRemovalImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity, aForced); + } + + /** + * Gives a small Text for the status of the Cover. + */ + public final String getDescription(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return getDescriptionImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * How Blast Proof the Cover is. 30 is normal. + */ + public final float getBlastProofLevel(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return getBlastProofLevelImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * If it lets RS-Signals into the Block + * <p/> + * This is just Informative so that Machines know if their Redstone Input is blocked or not + */ + public final boolean letsRedstoneGoIn(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return letsRedstoneGoInImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * If it lets RS-Signals out of the Block + */ + public final boolean letsRedstoneGoOut(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return letsRedstoneGoOutImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * If it lets Fibre-Signals into the Block + * <p/> + * This is just Informative so that Machines know if their Redstone Input is blocked or not + */ + public final boolean letsFibreGoIn(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return letsFibreGoInImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * If it lets Fibre-Signals out of the Block + */ + public final boolean letsFibreGoOut(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return letsFibreGoOutImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * If it lets Energy into the Block + */ + public final boolean letsEnergyIn(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return letsEnergyInImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * If it lets Energy out of the Block + */ + public final boolean letsEnergyOut(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return letsEnergyOutImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * If it lets Liquids into the Block, aFluid can be null meaning if this is generally allowing Fluids or not. + */ + public final boolean letsFluidIn(byte aSide, int aCoverID, ISerializableObject aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + return letsFluidInImpl(aSide, aCoverID, forceCast(aCoverVariable), aFluid, aTileEntity); + } + + /** + * If it lets Liquids out of the Block, aFluid can be null meaning if this is generally allowing Fluids or not. + */ + public final boolean letsFluidOut(byte aSide, int aCoverID, ISerializableObject aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + return letsFluidOutImpl(aSide, aCoverID, forceCast(aCoverVariable), aFluid, aTileEntity); + } + + /** + * If it lets Items into the Block, aSlot = -1 means if it is generally accepting Items (return false for no eraction at all), aSlot = -2 means if it would accept for all Slots Impl(return true to skip the Checks for each Slot). + */ + public final boolean letsItemsIn(byte aSide, int aCoverID, ISerializableObject aCoverVariable, int aSlot, ICoverable aTileEntity) { + return letsItemsInImpl(aSide, aCoverID, forceCast(aCoverVariable), aSlot, aTileEntity); + } + + /** + * If it lets Items out of the Block, aSlot = -1 means if it is generally accepting Items (return false for no eraction at all), aSlot = -2 means if it would accept for all Slots Impl(return true to skip the Checks for each Slot). + */ + public final boolean letsItemsOut(byte aSide, int aCoverID, ISerializableObject aCoverVariable, int aSlot, ICoverable aTileEntity) { + return letsItemsOutImpl(aSide, aCoverID, forceCast(aCoverVariable), aSlot, aTileEntity); + } + + /** + * If it lets you rightclick the Machine normally + */ + public final boolean isGUIClickable(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return isGUIClickableImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * Needs to return true for Covers, which have a Redstone Output on their Facing. + */ + public final boolean manipulatesSidedRedstoneOutput(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return manipulatesSidedRedstoneOutputImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * if this Cover should let Pipe Connections look connected even if it is not the case. + */ + public final boolean alwaysLookConnected(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return alwaysLookConnectedImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * Called to determine the incoming Redstone Signal of a Machine. + * Returns the original Redstone per default. + * The Cover should @letsRedstoneGoIn or the aInputRedstone Parameter is always 0. + */ + public final byte getRedstoneInput(byte aSide, byte aInputRedstone, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return getRedstoneInputImpl(aSide, aInputRedstone, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * Gets the Tick Rate for doCoverThings of the Cover + * <p/> + * 0 = No Ticks! Yes, 0 is Default, you have to override this + */ + public final int getTickRate(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return getTickRateImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + + /** + * The MC Color of this Lens. -1 for no Color (meaning this isn't a Lens then). + */ + public final byte getLensColor(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return getLensColorImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * @return the ItemStack dropped by this Cover + */ + public final ItemStack getDrop(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return getDropImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + // endregion + + // region impl + + protected boolean isRedstoneSensitiveImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity, long aTimer) { + return true; + } + + /** + * Called by updateEntity inside the covered TileEntity. aCoverVariable is the Value you returned last time. + */ + protected T doCoverThingsImpl(byte aSide, byte aInputRedstone, int aCoverID, T aCoverVariable, ICoverable aTileEntity, long aTimer) { + return aCoverVariable; + } + + /** + * Called when someone rightclicks this Cover. + * <p/> + * return true, if something actually happens. + */ + protected boolean onCoverRightClickImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + return false; + } + + /** + * Called when someone rightclicks this Cover with a Screwdriver. Doesn't call @onCoverRightclick in this Case. + * <p/> + * return the new Value of the Cover Variable + */ + protected T onCoverScrewdriverClickImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + return aCoverVariable; + } + + /** + * Called when someone shift-rightclicks this Cover with no tool. Doesn't call @onCoverRightclick in this Case. + */ + protected boolean onCoverShiftRightClickImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer) { + if (hasCoverGUI() && aPlayer instanceof EntityPlayerMP) { + lastPlayer = aPlayer; + GT_Values.NW.sendToPlayer(new GT_Packet_TileEntityCoverGUI(aSide, aCoverID, aCoverVariable, aTileEntity, (EntityPlayerMP) aPlayer), (EntityPlayerMP) aPlayer); + return true; + } + return false; + } + + protected Object getClientGUIImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, World aWorld) { + return null; + } + + /** + * Removes the Cover if this returns true, or if aForced is true. + * Doesn't get called when the Machine Block is getting broken, only if you break the Cover away from the Machine. + */ + protected boolean onCoverRemovalImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity, boolean aForced) { + return true; + } + + /** + * Gives a small Text for the status of the Cover. + */ + protected String getDescriptionImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return E; + } + + /** + * How Blast Proof the Cover is. 30 is normal. + */ + protected float getBlastProofLevelImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return 10.0F; + } + + /** + * If it lets RS-Signals into the Block + * <p/> + * This is just Informative so that Machines know if their Redstone Input is blocked or not + */ + protected boolean letsRedstoneGoInImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return false; + } + + /** + * If it lets RS-Signals out of the Block + */ + protected boolean letsRedstoneGoOutImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return false; + } + + /** + * If it lets Fibre-Signals into the Block + * <p/> + * This is just Informative so that Machines know if their Redstone Input is blocked or not + */ + protected boolean letsFibreGoInImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return false; + } + + /** + * If it lets Fibre-Signals out of the Block + */ + protected boolean letsFibreGoOutImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return false; + } + + /** + * If it lets Energy into the Block + */ + protected boolean letsEnergyInImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return false; + } + + /** + * If it lets Energy out of the Block + */ + protected boolean letsEnergyOutImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return false; + } + + /** + * If it lets Liquids into the Block, aFluid can be null meaning if this is generally allowing Fluids or not. + */ + protected boolean letsFluidInImpl(byte aSide, int aCoverID, T aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + return false; + } + + /** + * If it lets Liquids out of the Block, aFluid can be null meaning if this is generally allowing Fluids or not. + */ + protected boolean letsFluidOutImpl(byte aSide, int aCoverID, T aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + return false; + } + + /** + * If it lets Items into the Block, aSlot = -1 means if it is generally accepting Items (return false for no Interaction at all), aSlot = -2 means if it would accept for all Slots (return true to skip the Checks for each Slot). + */ + protected boolean letsItemsInImpl(byte aSide, int aCoverID, T aCoverVariable, int aSlot, ICoverable aTileEntity) { + return false; + } + + /** + * If it lets Items out of the Block, aSlot = -1 means if it is generally accepting Items (return false for no Interaction at all), aSlot = -2 means if it would accept for all Slots (return true to skip the Checks for each Slot). + */ + protected boolean letsItemsOutImpl(byte aSide, int aCoverID, T aCoverVariable, int aSlot, ICoverable aTileEntity) { + return false; + } + + /** + * If it lets you rightclick the Machine normally + */ + protected boolean isGUIClickableImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return false; + } + + /** + * Needs to return true for Covers, which have a Redstone Output on their Facing. + */ + protected boolean manipulatesSidedRedstoneOutputImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return false; + } + + /** + * if this Cover should let Pipe Connections look connected even if it is not the case. + */ + protected boolean alwaysLookConnectedImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return false; + } + + /** + * Called to determine the incoming Redstone Signal of a Machine. + * Returns the original Redstone per default. + * The Cover should @letsRedstoneGoIn or the aInputRedstone Parameter is always 0. + */ + protected byte getRedstoneInputImpl(byte aSide, byte aInputRedstone, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return letsRedstoneGoIn(aSide, aCoverID, aCoverVariable, aTileEntity) ? aInputRedstone : 0; + } + + /** + * Gets the Tick Rate for doCoverThings of the Cover + * <p/> + * 0 = No Ticks! Yes, 0 is Default, you have to override this + */ + protected int getTickRateImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return 0; + } + + + /** + * The MC Color of this Lens. -1 for no Color (meaning this isn't a Lens then). + */ + protected byte getLensColorImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return -1; + } + + /** + * @return the ItemStack dropped by this Cover + */ + protected ItemStack getDropImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return GT_OreDictUnificator.get(true, aTileEntity.getCoverItemAtSide(aSide)); + } + + //endregion + + // region no data + + /** + * Checks if the Cover can be placed on this. + */ + public boolean isCoverPlaceable(byte aSide, GT_ItemStack aStack, ICoverable aTileEntity) { + return true; + } + + public boolean hasCoverGUI() { + return false; + } + + /** + * Called when someone rightclicks this Cover Client Side + * <p/> + * return true, if something actually happens. + */ + public boolean onCoverRightclickClient(byte aSide, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + return false; + } + + /** + * If this is a simple Cover, which can also be used on Bronze Machines and similar. + */ + public boolean isSimpleCover() { + return false; + } + + /** + * sets the Cover upon placement. + */ + public void placeCover(byte aSide, ItemStack aCover, ICoverable aTileEntity) { + aTileEntity.setCoverIDAtSide(aSide, GT_Utility.stackToInt(aCover)); + } + + public String trans(String aNr, String aEnglish) { + return GT_LanguageManager.addStringLocalization("Interaction_DESCRIPTION_Index_" + aNr, aEnglish, false); + } + // endregion +} diff --git a/src/main/java/gregtech/api/util/GT_Utility.java b/src/main/java/gregtech/api/util/GT_Utility.java index 16d22be9ef..a07868ec68 100644 --- a/src/main/java/gregtech/api/util/GT_Utility.java +++ b/src/main/java/gregtech/api/util/GT_Utility.java @@ -12,13 +12,24 @@ import gregtech.api.GregTech_API; import gregtech.api.damagesources.GT_DamageSources; import gregtech.api.damagesources.GT_DamageSources.DamageSourceHotItem; import gregtech.api.enchants.Enchantment_Radioactivity; -import gregtech.api.enums.*; +import gregtech.api.enums.GT_Values; +import gregtech.api.enums.ItemList; +import gregtech.api.enums.Materials; +import gregtech.api.enums.OrePrefixes; +import gregtech.api.enums.SubTag; +import gregtech.api.enums.Textures; +import gregtech.api.enums.ToolDictNames; import gregtech.api.events.BlockScanningEvent; import gregtech.api.interfaces.IBlockContainer; import gregtech.api.interfaces.IDebugableBlock; import gregtech.api.interfaces.IProjectileItem; import gregtech.api.interfaces.ITexture; -import gregtech.api.interfaces.tileentity.*; +import gregtech.api.interfaces.tileentity.IBasicEnergyContainer; +import gregtech.api.interfaces.tileentity.ICoverable; +import gregtech.api.interfaces.tileentity.IGregTechDeviceInformation; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.interfaces.tileentity.IMachineProgress; +import gregtech.api.interfaces.tileentity.IUpgradableMachine; import gregtech.api.items.GT_EnergyArmor_Item; import gregtech.api.items.GT_Generic_Item; import gregtech.api.items.GT_MetaGenerated_Tool; @@ -28,7 +39,7 @@ import gregtech.api.objects.GT_ItemStack; import gregtech.api.objects.ItemData; import gregtech.api.threads.GT_Runnable_Sound; import gregtech.api.util.extensions.ArrayExt; -import gregtech.common.GT_Proxy; +import gregtech.common.GT_Pollution; import gregtech.common.blocks.GT_Block_Ores_Abstract; import ic2.api.recipe.IRecipeInput; import ic2.api.recipe.RecipeInputItemStack; @@ -37,7 +48,11 @@ import ic2.api.recipe.RecipeOutput; import net.minecraft.block.Block; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; -import net.minecraft.entity.*; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.EnumCreatureAttribute; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -59,9 +74,14 @@ import net.minecraft.potion.Potion; import net.minecraft.potion.PotionEffect; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityChest; -import net.minecraft.util.*; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MathHelper; import net.minecraft.world.World; import net.minecraft.world.WorldServer; +import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.BlockSnapshot; @@ -70,8 +90,13 @@ import net.minecraftforge.common.util.FakePlayerFactory; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.world.BlockEvent; -import net.minecraftforge.fluids.*; +import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidContainerRegistry.FluidContainerData; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTankInfo; +import net.minecraftforge.fluids.IFluidContainerItem; +import net.minecraftforge.fluids.IFluidHandler; import net.minecraftforge.oredict.OreDictionary; import javax.annotation.Nullable; @@ -79,16 +104,25 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.text.NumberFormat; -import java.text.DecimalFormatSymbols; import java.util.*; import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; import java.util.function.Function; import java.util.function.IntFunction; import java.util.function.Supplier; import static gregtech.GT_Mod.GT_FML_LOGGER; -import static gregtech.api.enums.GT_Values.*; -import static gregtech.common.GT_Proxy.GTPOLLUTION; +import static gregtech.api.enums.GT_Values.D1; +import static gregtech.api.enums.GT_Values.DW; +import static gregtech.api.enums.GT_Values.E; +import static gregtech.api.enums.GT_Values.GT; +import static gregtech.api.enums.GT_Values.L; +import static gregtech.api.enums.GT_Values.M; +import static gregtech.api.enums.GT_Values.NW; +import static gregtech.api.enums.GT_Values.V; +import static gregtech.api.enums.GT_Values.W; import static gregtech.common.GT_UndergroundOil.undergroundOilReadInformation; /** @@ -2114,7 +2148,7 @@ public class GT_Utility { try { if (tTileEntity instanceof ICoverable) { rEUAmount += 300; - String tString = ((ICoverable) tTileEntity).getCoverBehaviorAtSide((byte) aSide).getDescription((byte) aSide, ((ICoverable) tTileEntity).getCoverIDAtSide((byte) aSide), ((ICoverable) tTileEntity).getCoverDataAtSide((byte) aSide), (ICoverable) tTileEntity); + String tString = ((ICoverable) tTileEntity).getCoverBehaviorAtSideNew((byte) aSide).getDescription((byte) aSide, ((ICoverable) tTileEntity).getCoverIDAtSide((byte) aSide), ((ICoverable) tTileEntity).getComplexCoverDataAtSide((byte) aSide), (ICoverable) tTileEntity); if (tString != null && !tString.equals(E)) tList.add(tString); } } catch (Throwable e) { @@ -2186,23 +2220,19 @@ public class GT_Utility { } } + Chunk currentChunk = aWorld.getChunkFromBlockCoords(aX, aZ); if (aPlayer.capabilities.isCreativeMode) { - FluidStack tFluid = undergroundOilReadInformation(aWorld.getChunkFromBlockCoords(aX,aZ));//-# to only read + FluidStack tFluid = undergroundOilReadInformation(currentChunk);//-# to only read if (tFluid!=null) tList.add(EnumChatFormatting.GOLD + tFluid.getLocalizedName() + EnumChatFormatting.RESET + ": " + EnumChatFormatting.YELLOW + formatNumbers(tFluid.amount) + EnumChatFormatting.RESET + " L"); else tList.add(EnumChatFormatting.GOLD + trans("201","Nothing") + EnumChatFormatting.RESET + ": " + EnumChatFormatting.YELLOW + '0' + EnumChatFormatting.RESET + " L"); } // if(aPlayer.capabilities.isCreativeMode){ - int[] chunkData = GT_Proxy.dimensionWiseChunkData.get(aWorld.provider.dimensionId).get(aWorld.getChunkFromBlockCoords(aX,aZ).getChunkCoordIntPair()); - if(chunkData != null){ - if(chunkData[GTPOLLUTION]>0){ - tList.add(trans("202","Pollution in Chunk: ") + EnumChatFormatting.RED + formatNumbers(chunkData[GTPOLLUTION]) + EnumChatFormatting.RESET + trans("203"," gibbl")); - }else{ - tList.add(EnumChatFormatting.GREEN+trans("204","No Pollution in Chunk! HAYO!")+EnumChatFormatting.RESET); - } - }else{ - tList.add(EnumChatFormatting.GREEN+trans("204","No Pollution in Chunk! HAYO!")+EnumChatFormatting.RESET); + if (GT_Pollution.hasPollution(currentChunk)) { + tList.add(trans("202", "Pollution in Chunk: ") + EnumChatFormatting.RED + formatNumbers(GT_Pollution.getPollution(currentChunk)) + EnumChatFormatting.RESET + trans("203", " gibbl")); + } else { + tList.add(EnumChatFormatting.GREEN + trans("204", "No Pollution in Chunk! HAYO!") + EnumChatFormatting.RESET); } try { diff --git a/src/main/java/gregtech/api/util/ISerializableObject.java b/src/main/java/gregtech/api/util/ISerializableObject.java new file mode 100644 index 0000000000..51fa40e55a --- /dev/null +++ b/src/main/java/gregtech/api/util/ISerializableObject.java @@ -0,0 +1,150 @@ +package gregtech.api.util; + +import com.google.common.io.ByteArrayDataInput; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTSizeTracker; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagInt; + +import javax.annotation.Nonnull; +import java.io.IOException; + +/** + * We could well have used {@link java.io.Serializable}, but that's too slow and should generally be avoided + * + * @author glease + */ +public interface ISerializableObject { + + @Nonnull + ISerializableObject copy(); + + @Nonnull + NBTBase saveDataToNBT(); + + /** + * Write data to given ByteBuf + * The data saved this way is intended to be stored for short amount of time over network. + * DO NOT store it to disks. + */ + // the NBT is an unfortunate piece of tech. everything uses it but its API is not as efficient as could be + void writeToByteBuf(ByteBuf aBuf); + + void loadDataFromNBT(NBTBase aNBT); + + /** + * Read data from given parameter and return this. + * The data read this way is intended to be stored for short amount of time over network. + */ + // the NBT is an unfortunate piece of tech. everything uses it but its API is not as efficient as could be + @Nonnull + ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer); + + /** + * Reverse engineered and adapted {@link cpw.mods.fml.common.network.ByteBufUtils#readTag(ByteBuf)} + * Given buffer must contain a serialized NBTTagCompound in minecraft encoding + */ + static NBTTagCompound readCompoundTagFromGreggyByteBuf(ByteArrayDataInput aBuf) { + short size = aBuf.readShort(); + if (size < 0) + return null; + else { + byte[] buf = new byte[size]; // this is shit, how many copies have we been doing? + aBuf.readFully(buf); + try { + return CompressedStreamTools.func_152457_a(buf, new NBTSizeTracker(2097152L)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + /** + * Reverse engineered and adapted {@link cpw.mods.fml.common.network.ByteBufUtils#readItemStack(ByteBuf)} + * Given buffer must contain a serialized ItemStack in minecraft encoding + */ + static ItemStack readItemStackFromGreggyByteBuf(ByteArrayDataInput aBuf) { + ItemStack stack = null; + short id = aBuf.readShort(); + if (id >= 0) { + byte size = aBuf.readByte(); + short meta = aBuf.readShort(); + stack = new ItemStack(Item.getItemById(id), size, meta); + stack.stackTagCompound = readCompoundTagFromGreggyByteBuf(aBuf); + } + return stack; + } + + final class LegacyCoverData implements ISerializableObject { + private int mData; + + public LegacyCoverData() { + } + + public LegacyCoverData(int mData) { + this.mData = mData; + } + + @Override + @Nonnull + public ISerializableObject copy() { + return new LegacyCoverData(mData); + } + + @Override + @Nonnull + public NBTBase saveDataToNBT() { + return new NBTTagInt(mData); + } + + @Override + public void writeToByteBuf(ByteBuf aBuf) { + aBuf.writeInt(mData); + } + + @Override + public void loadDataFromNBT(NBTBase aNBT) { + mData = aNBT instanceof NBTBase.NBTPrimitive ? ((NBTBase.NBTPrimitive) aNBT).func_150287_d() : 0; + } + + @Override + @Nonnull + public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) { + mData = aBuf.readInt(); + return this; + } + + public int get() { + return mData; + } + + public void set(int mData) { + this.mData = mData; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LegacyCoverData that = (LegacyCoverData) o; + + return mData == that.mData; + } + + @Override + public int hashCode() { + return mData; + } + + @Override + public String toString() { + return String.valueOf(mData); + } + } +} diff --git a/src/main/java/gregtech/common/GT_Network.java b/src/main/java/gregtech/common/GT_Network.java index c9c57676ad..97e511aba4 100644 --- a/src/main/java/gregtech/common/GT_Network.java +++ b/src/main/java/gregtech/common/GT_Network.java @@ -36,7 +36,7 @@ public class GT_Network extends MessageToMessageCodec<FMLProxyPacket, GT_Packet> public GT_Network() { this.mChannel = NetworkRegistry.INSTANCE.newChannel("GregTech", this, new HandlerShared()); - this.mSubChannels = new GT_Packet[]{new GT_Packet_TileEntity(), new GT_Packet_Sound(), new GT_Packet_Block_Event(), new GT_Packet_Ores(), new GT_Packet_Pollution(), new MessageSetFlaskCapacity(), new GT_Packet_TileEntityCover(), new GT_Packet_TileEntityCoverGUI(), new MessageUpdateFluidDisplayItem(), new GT_Packet_ClientPreference(), new GT_Packet_WirelessRedstoneCover()}; + this.mSubChannels = new GT_Packet[]{new GT_Packet_TileEntity(), new GT_Packet_Sound(), new GT_Packet_Block_Event(), new GT_Packet_Ores(), new GT_Packet_Pollution(), new MessageSetFlaskCapacity(), new GT_Packet_TileEntityCover(), new GT_Packet_TileEntityCoverGUI(), new MessageUpdateFluidDisplayItem(), new GT_Packet_ClientPreference(), new GT_Packet_WirelessRedstoneCover(), new GT_Packet_TileEntityCoverNew()}; } @Override diff --git a/src/main/java/gregtech/common/GT_Pollution.java b/src/main/java/gregtech/common/GT_Pollution.java index 7b1ad90d52..865fa83f7e 100644 --- a/src/main/java/gregtech/common/GT_Pollution.java +++ b/src/main/java/gregtech/common/GT_Pollution.java @@ -7,6 +7,7 @@ import gregtech.GT_Mod; import gregtech.api.enums.GT_Values; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.net.GT_Packet_Pollution; +import gregtech.api.util.GT_ChunkAssociatedData; import gregtech.api.util.GT_Utility; import net.minecraft.block.Block; import net.minecraft.block.material.Material; @@ -20,30 +21,34 @@ import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.ChunkPosition; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.ChunkDataEvent; import net.minecraftforge.event.world.ChunkWatchEvent; +import net.minecraftforge.event.world.WorldEvent; +import javax.annotation.ParametersAreNonnullByDefault; +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import static gregtech.api.objects.XSTR.XSTR_INSTANCE; -import static gregtech.common.GT_Proxy.GTPOLLUTION; -import static gregtech.common.GT_Proxy.dimensionWiseChunkData; import static gregtech.common.GT_Proxy.dimensionWisePollution; -import static gregtech.common.GT_Proxy.getDefaultChunkDataOnCreation; public class GT_Pollution { + private static final Storage STORAGE = new Storage(); /** * Pollution dispersion until effects start: * Calculation: ((Limit * 0.01) + 2000) * (4 <- spreading rate) - * + * <p> * SMOG(500k) 466.7 pollution/sec * Poison(750k) 633,3 pollution/sec * Dying Plants(1mio) 800 pollution/sec * Sour Rain(1.5mio) 1133.3 pollution/sec - * + * <p> * Pollution producers (pollution/sec) * Bronze Boiler(20) * Lava Boiler(20) @@ -52,7 +57,7 @@ public class GT_Pollution { * Diesel Generator(40/80/160) * Gas Turbine(20/40/80) * Charcoal Pile(100) - * + * <p> * Large Diesel Engine(320) * Electric Blast Furnace(100) * Implosion Compressor(2000) @@ -60,33 +65,27 @@ public class GT_Pollution { * Large Gas Turbine(160) * Multi Smelter(100) * Pyrolyse Oven(400) - * + * <p> * Machine Explosion(100,000) - * + * <p> * Other Random Shit: lots and lots - * + * <p> * Muffler Hatch Pollution reduction: ** inaccurate ** * LV (0%), MV (30%), HV (52%), EV (66%), IV (76%), LuV (84%), ZPM (89%), UV (92%), MAX (95%) */ private List<ChunkCoordIntPair> pollutionList = new ArrayList<>();//chunks left to process - private HashMap<ChunkCoordIntPair,int[]> chunkData;//link to chunk data that is saved/loaded - private int operationsPerTick=0;//how much chunks should be processed in each cycle - private static final short cycleLen=1200; - private final World aWorld; + private final List<ChunkCoordIntPair> chunkData = new ArrayList<>();//link to chunk data that is saved/loaded + private int operationsPerTick = 0;//how much chunks should be processed in each cycle + private static final short cycleLen = 1200; + private final World world; public static int mPlayerPollution; private static int POLLUTIONPACKET_MINVALUE = 1000; private static GT_PollutionEventHandler EVENT_HANDLER; - public GT_Pollution(World world){ - aWorld=world; - chunkData=dimensionWiseChunkData.get(aWorld.provider.dimensionId); - if(chunkData==null){ - chunkData=new HashMap<>(1024); - dimensionWiseChunkData.put(world.provider.dimensionId,chunkData); - } - dimensionWisePollution.put(aWorld.provider.dimensionId,this); + public GT_Pollution(World world) { + this.world = world; if (EVENT_HANDLER == null) { EVENT_HANDLER = new GT_PollutionEventHandler(); @@ -94,61 +93,61 @@ public class GT_Pollution { } } - public static void onWorldTick(TickEvent.WorldTickEvent aEvent){//called from proxy + public static void onWorldTick(TickEvent.WorldTickEvent aEvent) {//called from proxy //return if pollution disabled - if(!GT_Mod.gregtechproxy.mPollution) return; + if (!GT_Mod.gregtechproxy.mPollution) return; final GT_Pollution pollutionInstance = dimensionWisePollution.get(aEvent.world.provider.dimensionId); - if(pollutionInstance==null)return; - pollutionInstance.tickPollutionInWorld((int)(aEvent.world.getTotalWorldTime()%cycleLen)); + if (pollutionInstance == null) return; + pollutionInstance.tickPollutionInWorld((int) (aEvent.world.getTotalWorldTime() % cycleLen)); } - private void tickPollutionInWorld(int aTickID){//called from method above + private void tickPollutionInWorld(int aTickID) {//called from method above //gen data set - if(aTickID==0){ - pollutionList = new ArrayList<>(chunkData.keySet()); + if (aTickID == 0) { + // make a snapshot of what to work on + // counterintuitive as it seems, but this is the fastest way java collections framework offers us. + pollutionList = new ArrayList<>(chunkData); //set operations per tick - if(pollutionList.size()>0) operationsPerTick =(pollutionList.size()/cycleLen); - else operationsPerTick=0;//SANity + if (pollutionList.size() > 0) operationsPerTick = (pollutionList.size() / cycleLen); + else operationsPerTick = 0;//SANity } - for(int chunksProcessed=0;chunksProcessed<=operationsPerTick;chunksProcessed++){ - if(pollutionList.size()==0)break;//no more stuff to do - ChunkCoordIntPair actualPos=pollutionList.remove(pollutionList.size()-1);//faster - //add default data if missing - if(!chunkData.containsKey(actualPos)) chunkData.put(actualPos,getDefaultChunkDataOnCreation()); + for (int chunksProcessed = 0; chunksProcessed <= operationsPerTick; chunksProcessed++) { + if (pollutionList.size() == 0) break;//no more stuff to do + ChunkCoordIntPair actualPos = pollutionList.remove(pollutionList.size() - 1);//faster //get pollution - int tPollution = chunkData.get(actualPos)[GTPOLLUTION]; + ChunkData currentData = STORAGE.get(world, actualPos); + int tPollution = currentData.getAmount(); //remove some - tPollution = (int)(0.9945f*tPollution); + tPollution = (int) (0.9945f * tPollution); //tPollution -= 2000;//This does not really matter... - if(tPollution<=0) tPollution = 0;//SANity check - else if(tPollution>400000){//Spread Pollution + if (tPollution <= 0) tPollution = 0;//SANity check + else if (tPollution > 400000) {//Spread Pollution ChunkCoordIntPair[] tNeighbors = new ChunkCoordIntPair[4];//array is faster - tNeighbors[0]=(new ChunkCoordIntPair(actualPos.chunkXPos+1,actualPos.chunkZPos)); - tNeighbors[1]=(new ChunkCoordIntPair(actualPos.chunkXPos-1,actualPos.chunkZPos)); - tNeighbors[2]=(new ChunkCoordIntPair(actualPos.chunkXPos,actualPos.chunkZPos+1)); - tNeighbors[3]=(new ChunkCoordIntPair(actualPos.chunkXPos,actualPos.chunkZPos-1)); - for(ChunkCoordIntPair neighborPosition : tNeighbors){ - if(!chunkData.containsKey(neighborPosition)) chunkData.put(neighborPosition,getDefaultChunkDataOnCreation()); - - int neighborPollution = chunkData.get(neighborPosition)[GTPOLLUTION]; - if(neighborPollution*6 < tPollution*5){//METHEMATICS... + tNeighbors[0] = (new ChunkCoordIntPair(actualPos.chunkXPos + 1, actualPos.chunkZPos)); + tNeighbors[1] = (new ChunkCoordIntPair(actualPos.chunkXPos - 1, actualPos.chunkZPos)); + tNeighbors[2] = (new ChunkCoordIntPair(actualPos.chunkXPos, actualPos.chunkZPos + 1)); + tNeighbors[3] = (new ChunkCoordIntPair(actualPos.chunkXPos, actualPos.chunkZPos - 1)); + for (ChunkCoordIntPair neighborPosition : tNeighbors) { + ChunkData neighbor = STORAGE.get(world, neighborPosition); + int neighborPollution = neighbor.getAmount(); + if (neighborPollution * 6 < tPollution * 5) {//MATHEMATICS... int tDiff = tPollution - neighborPollution; - tDiff = tDiff/20; - neighborPollution = GT_Utility.safeInt((long)neighborPollution+tDiff);//tNPol += tDiff; + tDiff = tDiff / 20; + neighborPollution = GT_Utility.safeInt((long) neighborPollution + tDiff);//tNPol += tDiff; tPollution -= tDiff; - chunkData.get(neighborPosition)[GTPOLLUTION] = neighborPollution; + neighbor.setAmount(neighborPollution); } } //Create Pollution effects //Smog filter TODO - if(tPollution > GT_Mod.gregtechproxy.mPollutionSmogLimit) { + if (tPollution > GT_Mod.gregtechproxy.mPollutionSmogLimit) { AxisAlignedBB chunk = AxisAlignedBB.getBoundingBox(actualPos.chunkXPos << 4, 0, actualPos.chunkZPos << 4, (actualPos.chunkXPos << 4) + 16, 256, (actualPos.chunkZPos << 4) + 16); - List<EntityLivingBase> tEntitys = aWorld.getEntitiesWithinAABB(EntityLivingBase.class, chunk); + List<EntityLivingBase> tEntitys = world.getEntitiesWithinAABB(EntityLivingBase.class, chunk); for (EntityLivingBase tEnt : tEntitys) { if (tEnt instanceof EntityPlayerMP && ((EntityPlayerMP) tEnt).capabilities.isCreativeMode) continue; @@ -194,131 +193,211 @@ public class GT_Pollution { int x = (actualPos.chunkXPos << 4) + XSTR_INSTANCE.nextInt(16); int y = 60 + (-f + XSTR_INSTANCE.nextInt(f * 2 + 1)); int z = (actualPos.chunkZPos << 4) + XSTR_INSTANCE.nextInt(16); - damageBlock(aWorld, x, y, z, tPollution > GT_Mod.gregtechproxy.mPollutionSourRainLimit); + damageBlock(world, x, y, z, tPollution > GT_Mod.gregtechproxy.mPollutionSourRainLimit); } } } } } //Write new pollution to Hashmap !!! - chunkData.get(actualPos)[GTPOLLUTION] = tPollution; + currentData.setAmount(tPollution); //Send new value to players nearby if (tPollution > POLLUTIONPACKET_MINVALUE) { - NetworkRegistry.TargetPoint point = new NetworkRegistry.TargetPoint(aWorld.provider.dimensionId, (actualPos.chunkXPos << 4), 64, (actualPos.chunkZPos << 4), 256); + NetworkRegistry.TargetPoint point = new NetworkRegistry.TargetPoint(world.provider.dimensionId, (actualPos.chunkXPos << 4), 64, (actualPos.chunkZPos << 4), 256); GT_Values.NW.sendToAllAround(new GT_Packet_Pollution(actualPos, tPollution), point); } } } - private static void damageBlock(World world, int x, int y, int z, boolean sourRain){ - if (world.isRemote) return; + private static void damageBlock(World world, int x, int y, int z, boolean sourRain) { + if (world.isRemote) return; Block tBlock = world.getBlock(x, y, z); int tMeta = world.getBlockMetadata(x, y, z); - if (tBlock == Blocks.air || tBlock == Blocks.stone || tBlock == Blocks.sand|| tBlock == Blocks.deadbush)return; - - if (tBlock == Blocks.leaves || tBlock == Blocks.leaves2 || tBlock.getMaterial() == Material.leaves) - world.setBlockToAir(x, y, z); - if (tBlock == Blocks.reeds) { - tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); - world.setBlockToAir(x, y, z); - } - if (tBlock == Blocks.tallgrass) - world.setBlock(x, y, z, Blocks.deadbush); - if (tBlock == Blocks.vine) { - tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); - world.setBlockToAir(x, y, z); - } - if (tBlock == Blocks.waterlily || tBlock == Blocks.wheat || tBlock == Blocks.cactus || + if (tBlock == Blocks.air || tBlock == Blocks.stone || tBlock == Blocks.sand || tBlock == Blocks.deadbush) + return; + + if (tBlock == Blocks.leaves || tBlock == Blocks.leaves2 || tBlock.getMaterial() == Material.leaves) + world.setBlockToAir(x, y, z); + if (tBlock == Blocks.reeds) { + tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); + world.setBlockToAir(x, y, z); + } + if (tBlock == Blocks.tallgrass) + world.setBlock(x, y, z, Blocks.deadbush); + if (tBlock == Blocks.vine) { + tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); + world.setBlockToAir(x, y, z); + } + if (tBlock == Blocks.waterlily || tBlock == Blocks.wheat || tBlock == Blocks.cactus || tBlock.getMaterial() == Material.cactus || tBlock == Blocks.melon_block || tBlock == Blocks.melon_stem) { - tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); - world.setBlockToAir(x, y, z); - } - if (tBlock == Blocks.red_flower || tBlock == Blocks.yellow_flower || tBlock == Blocks.carrots || + tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); + world.setBlockToAir(x, y, z); + } + if (tBlock == Blocks.red_flower || tBlock == Blocks.yellow_flower || tBlock == Blocks.carrots || tBlock == Blocks.potatoes || tBlock == Blocks.pumpkin || tBlock == Blocks.pumpkin_stem) { - tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); - world.setBlockToAir(x, y, z); - } - if (tBlock == Blocks.sapling || tBlock.getMaterial() == Material.plants) - world.setBlock(x, y, z, Blocks.deadbush); - if (tBlock == Blocks.cocoa) { - tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); - world.setBlockToAir(x, y, z); - } - if (tBlock == Blocks.mossy_cobblestone) + tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); + world.setBlockToAir(x, y, z); + } + if (tBlock == Blocks.sapling || tBlock.getMaterial() == Material.plants) + world.setBlock(x, y, z, Blocks.deadbush); + if (tBlock == Blocks.cocoa) { + tBlock.dropBlockAsItem(world, x, y, z, tMeta, 0); + world.setBlockToAir(x, y, z); + } + if (tBlock == Blocks.mossy_cobblestone) + world.setBlock(x, y, z, Blocks.cobblestone); + if (tBlock == Blocks.grass || tBlock.getMaterial() == Material.grass) + world.setBlock(x, y, z, Blocks.dirt); + if (tBlock == Blocks.farmland || tBlock == Blocks.dirt) { + world.setBlock(x, y, z, Blocks.sand); + } + + if (sourRain && world.isRaining() && (tBlock == Blocks.stone || tBlock == Blocks.gravel || tBlock == Blocks.cobblestone) && + world.getBlock(x, y + 1, z) == Blocks.air && world.canBlockSeeTheSky(x, y, z)) { + if (tBlock == Blocks.stone) { world.setBlock(x, y, z, Blocks.cobblestone); - if (tBlock == Blocks.grass || tBlock.getMaterial() == Material.grass ) - world.setBlock(x, y, z, Blocks.dirt); - if(tBlock == Blocks.farmland || tBlock == Blocks.dirt){ + } else if (tBlock == Blocks.cobblestone) { + world.setBlock(x, y, z, Blocks.gravel); + } else if (tBlock == Blocks.gravel) { world.setBlock(x, y, z, Blocks.sand); } - - if(sourRain && world.isRaining() && (tBlock == Blocks.stone || tBlock == Blocks.gravel || tBlock == Blocks.cobblestone) && - world.getBlock(x, y+1, z) == Blocks.air && world.canBlockSeeTheSky(x, y, z)){ - if(tBlock == Blocks.stone){world.setBlock(x, y, z, Blocks.cobblestone); } - else if(tBlock == Blocks.cobblestone){world.setBlock(x, y, z, Blocks.gravel); } - else if(tBlock == Blocks.gravel){world.setBlock(x, y, z, Blocks.sand); } - } + } } - public static void addPollution(IGregTechTileEntity te, int aPollution){ - addPollution(te.getWorld().getChunkFromBlockCoords(te.getXCoord(),te.getZCoord()), aPollution); + public static void addPollution(IGregTechTileEntity te, int aPollution) { + addPollution(te.getWorld().getChunkFromBlockCoords(te.getXCoord(), te.getZCoord()), aPollution); } - public static void addPollution(Chunk ch, int aPollution){ - if(!GT_Mod.gregtechproxy.mPollution)return; - HashMap<ChunkCoordIntPair,int[]> dataMap=dimensionWiseChunkData.get(ch.worldObj.provider.dimensionId); - if(dataMap==null){ - dataMap=new HashMap<>(1024); - dimensionWiseChunkData.put(ch.worldObj.provider.dimensionId,dataMap); - } - int[] dataArr=dataMap.get(ch.getChunkCoordIntPair()); - if(dataArr==null){ - dataArr=getDefaultChunkDataOnCreation(); - dataMap.put(ch.getChunkCoordIntPair(),dataArr); - } - dataArr[GTPOLLUTION]+=aPollution; - if(dataArr[GTPOLLUTION]<0)dataArr[GTPOLLUTION]=0; + public static void addPollution(Chunk ch, int aPollution) { + if (!GT_Mod.gregtechproxy.mPollution || aPollution == 0) return; + STORAGE.get(ch).changeAmount(aPollution); } - public static int getPollution(IGregTechTileEntity te){ - return getPollution(te.getWorld().getChunkFromBlockCoords(te.getXCoord(),te.getZCoord())); + public static int getPollution(IGregTechTileEntity te) { + return getPollution(te.getWorld().getChunkFromBlockCoords(te.getXCoord(), te.getZCoord())); } - public static int getPollution(Chunk ch){ - if(!GT_Mod.gregtechproxy.mPollution) + public static int getPollution(Chunk ch) { + if (!GT_Mod.gregtechproxy.mPollution) return 0; - HashMap<ChunkCoordIntPair,int[]> dataMap=dimensionWiseChunkData.get(ch.worldObj.provider.dimensionId); - if(dataMap==null || dataMap.get(ch.getChunkCoordIntPair())==null) return 0; - return dataMap.get(ch.getChunkCoordIntPair())[GTPOLLUTION]; + return STORAGE.get(ch).getAmount(); + } + + public static boolean hasPollution(Chunk ch) { + if (!GT_Mod.gregtechproxy.mPollution) + return false; + return STORAGE.isCreated(ch.worldObj, ch.getChunkCoordIntPair()) && STORAGE.get(ch).getAmount() > 0; } public static int getPollution(ChunkCoordIntPair aCh, int aDim) { if (!GT_Mod.gregtechproxy.mPollution) return 0; - HashMap<ChunkCoordIntPair, int[]> dataMap = dimensionWiseChunkData.get(aDim); - if (dataMap == null || dataMap.get(aCh) == null) - return 0; - return dataMap.get(aCh)[GTPOLLUTION]; + return STORAGE.get(DimensionManager.getWorld(aDim), aCh.chunkXPos, aCh.chunkZPos).getAmount(); } //Add compatibility with old code @Deprecated /*Don't use it... too weird way of passing position*/ - public static void addPollution(World aWorld, ChunkPosition aPos, int aPollution){ + public static void addPollution(World aWorld, ChunkPosition aPos, int aPollution) { //The abuse of ChunkPosition to store block position and dim... //is just bad especially when that is both used to store ChunkPos and BlockPos depending on context - addPollution(aWorld.getChunkFromBlockCoords(aPos.chunkPosX,aPos.chunkPosZ),aPollution); + addPollution(aWorld.getChunkFromBlockCoords(aPos.chunkPosX, aPos.chunkPosZ), aPollution); + } + + static void migrate(ChunkDataEvent.Load e) { + addPollution(e.getChunk(), e.getData().getInteger("GTPOLLUTION")); } - public class GT_PollutionEventHandler { + public static class GT_PollutionEventHandler { @SubscribeEvent public void chunkWatch(ChunkWatchEvent.Watch event) { - if(!GT_Mod.gregtechproxy.mPollution) return; - if (chunkData.containsKey(event.chunk)) { - int pollution = chunkData.get(event.chunk)[GTPOLLUTION]; + if (!GT_Mod.gregtechproxy.mPollution) return; + World world = event.player.worldObj; + if (STORAGE.isCreated(world, event.chunk)) { + int pollution = STORAGE.get(world, event.chunk).getAmount(); if (pollution > POLLUTIONPACKET_MINVALUE) GT_Values.NW.sendToPlayer(new GT_Packet_Pollution(event.chunk, pollution), event.player); } } + + @SubscribeEvent + public void onWorldLoad(WorldEvent.Load e) { + // super class loads everything lazily. We force it to load them all. + STORAGE.loadAll(e.world); + } + } + + @ParametersAreNonnullByDefault + private static final class Storage extends GT_ChunkAssociatedData<ChunkData> { + private Storage() { + super("Pollution", ChunkData.class, 64, (byte) 0, false); + } + + @Override + protected void writeElement(DataOutput output, ChunkData element, World world, int chunkX, int chunkZ) throws IOException { + output.writeInt(element.getAmount()); + } + + @Override + protected ChunkData readElement(DataInput input, int version, World world, int chunkX, int chunkZ) throws IOException { + ChunkData data = new ChunkData(input.readInt()); + getChunkData(world).add(new ChunkCoordIntPair(chunkX, chunkZ)); + return data; + } + + private List<ChunkCoordIntPair> getChunkData(World world) { + return dimensionWisePollution.computeIfAbsent(world.provider.dimensionId, i -> new GT_Pollution(world)).chunkData; + } + + @Override + protected ChunkData createElement(World world, int chunkX, int chunkZ) { + return new ChunkData(); + } + + @Override + public void loadAll(World w) { + super.loadAll(w); + } + + public void set(World world, ChunkCoordIntPair coord, ChunkData data) { + set(world, coord.chunkXPos, coord.chunkZPos, data); + getChunkData(world).add(coord); + } + + public boolean isCreated(World world, ChunkCoordIntPair coord) { + return isCreated(world.provider.dimensionId, coord.chunkXPos, coord.chunkZPos); + } + } + + private static final class ChunkData implements GT_ChunkAssociatedData.IData { + public int amount; + + private ChunkData() { + this(0); + } + + private ChunkData(int amount) { + this.amount = amount; + } + + /** + * Current pollution amount. + */ + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = Math.max(amount, 0); + } + + public void changeAmount(int delta) { + this.amount = Math.max(amount + delta, 0); + } + + @Override + public boolean isSameAsDefault() { + return amount == 0; + } } } diff --git a/src/main/java/gregtech/common/GT_Proxy.java b/src/main/java/gregtech/common/GT_Proxy.java index ed99c1e3c0..a1706ee6e9 100644 --- a/src/main/java/gregtech/common/GT_Proxy.java +++ b/src/main/java/gregtech/common/GT_Proxy.java @@ -709,8 +709,8 @@ public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler { } public void onServerAboutToStart(){ - dimensionWiseChunkData.clear();//!!! IMPORTANT for map switching... dimensionWisePollution.clear();//!!! IMPORTANT for map switching... + GT_ChunkAssociatedData.clearAll(); } public void onServerStarting() { @@ -776,6 +776,7 @@ public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler { } catch (Throwable e) {e.printStackTrace(GT_Log.err);} } this.mUniverse = null; + //GT_ChunkAssociatedData.saveAll(); todo: figure out if this is needed } @SubscribeEvent @@ -1981,87 +1982,25 @@ public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler { } + @Deprecated public static final HashMap<Integer,HashMap<ChunkCoordIntPair,int []>> dimensionWiseChunkData = new HashMap<>(16);//stores chunk data that is loaded/saved public static final HashMap<Integer,GT_Pollution> dimensionWisePollution = new HashMap<>(16);//stores GT_Polluttors objects public static final byte GTOIL=3,GTOILFLUID=2,GTPOLLUTION=1,GTMETADATA=0,NOT_LOADED=0,LOADED=1;//consts - //@Deprecated - //public static final HashMap<ChunkPosition, int[]> chunkData = new HashMap<>(0); - - private static final byte oilVer=(byte)20;//non zero plz //TO get default's fast + @Deprecated public static int[] getDefaultChunkDataOnCreation(){ return new int[]{NOT_LOADED,0,-1,-1}; } + @Deprecated public static int[] getDefaultChunkDataOnLoad(){ return new int[]{LOADED,0,-1,-1}; } @SubscribeEvent - public void handleChunkSaveEvent(ChunkDataEvent.Save event) {//ALWAYS SAVE FROM THE HASH MAP DATA - HashMap<ChunkCoordIntPair,int []> chunkData=dimensionWiseChunkData.get(event.world.provider.dimensionId); - if(chunkData==null) return;//no dim info stored - - int[] tInts = chunkData.get(event.getChunk().getChunkCoordIntPair()); - if(tInts==null) return;//no chunk data stored - //assuming len of this array 4 - if(tInts[3]>=0)event.getData().setInteger("GTOIL", tInts[GTOIL]); - else event.getData().removeTag("GTOIL"); - if(tInts[2]>=0)event.getData().setInteger("GTOILFLUID", tInts[GTOILFLUID]); - else event.getData().removeTag("GTOILFLUID"); - if(tInts[1]>0)event.getData().setInteger("GTPOLLUTION", tInts[GTPOLLUTION]); - else event.getData().removeTag("GTPOLLUTION"); - event.getData().setByte("GTOILVER", oilVer);//version mark - } - - @SubscribeEvent public void handleChunkLoadEvent(ChunkDataEvent.Load event) { - final int worldID=event.world.provider.dimensionId; - HashMap<ChunkCoordIntPair, int[]> chunkData = dimensionWiseChunkData.computeIfAbsent(worldID, k -> new HashMap<>(1024)); - if (dimensionWisePollution.get(worldID) == null) - dimensionWisePollution.put(worldID, new GT_Pollution(event.world)); - - int[] tInts = chunkData.get(event.getChunk().getChunkCoordIntPair()); - if (tInts == null) { - //NOT LOADED and NOT PROCESSED by pollution algorithms - //regular load - tInts = getDefaultChunkDataOnLoad(); - - if (event.getData().getByte("GTOILVER") == oilVer) { - if (event.getData().hasKey("GTOIL")) - tInts[GTOIL] = event.getData().getInteger("GTOIL"); - if (event.getData().hasKey("GTOILFLUID")) - tInts[GTOILFLUID] = event.getData().getInteger("GTOILFLUID"); - } - - tInts[GTPOLLUTION] = event.getData().getInteger("GTPOLLUTION");//Defaults to 0 - - //store in HASH MAP if has useful data - if (tInts[GTPOLLUTION] > 0 || tInts[GTOIL] >= 0 || tInts[GTOILFLUID] >= 0) - chunkData.put(event.getChunk().getChunkCoordIntPair(), tInts); - } else if (tInts[GTMETADATA] == NOT_LOADED) {//was NOT loaded from chunk save game data - //NOT LOADED but generated - //append load - if (event.getData().getByte("GTOILVER") == oilVer) { - if (tInts[GTOIL] < 0 && event.getData().hasKey("GTOIL"))//if was not yet initialized - tInts[GTOIL] = event.getData().getInteger("GTOIL"); - - if (tInts[GTOILFLUID] < 0 && event.getData().hasKey("GTOILFLUID"))//if was not yet initialized - tInts[GTOILFLUID] = event.getData().getInteger("GTOILFLUID"); - } else { - tInts[GTOIL] = -1; - tInts[GTOILFLUID] = -1; - } - - tInts[GTPOLLUTION] += event.getData().getInteger("GTPOLLUTION");//Defaults to 0, add stored pollution to data - tInts[GTMETADATA] = LOADED;//mark as = loaded - //store in HASHMAP - - chunkData.put(event.getChunk().getChunkCoordIntPair(), tInts); - }//else if(tInts[0]==1){ - ////Already loaded chunk data - ////DO NOTHING - this chunk data was already loaded and stored in hash map - //} + GT_UndergroundOil.migrate(event); + GT_Pollution.migrate(event); } @SubscribeEvent diff --git a/src/main/java/gregtech/common/GT_UndergroundOil.java b/src/main/java/gregtech/common/GT_UndergroundOil.java index 1f45b5fca9..cc6771dc90 100644 --- a/src/main/java/gregtech/common/GT_UndergroundOil.java +++ b/src/main/java/gregtech/common/GT_UndergroundOil.java @@ -5,22 +5,29 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.objects.GT_UO_Dimension; import gregtech.api.objects.GT_UO_Fluid; import gregtech.api.objects.XSTR; -import net.minecraft.world.ChunkCoordIntPair; +import gregtech.api.util.GT_ChunkAssociatedData; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; -import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.event.world.ChunkDataEvent; +import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; -import java.util.HashMap; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.Objects; +import java.util.WeakHashMap; import static gregtech.api.objects.XSTR.XSTR_INSTANCE; -import static gregtech.common.GT_Proxy.*; /** * Created by Tec on 29.04.2017. */ public class GT_UndergroundOil { public static final short DIVIDER=5000; + private static final GT_UndergroundOilStore STORAGE = new GT_UndergroundOilStore(); public static FluidStack undergroundOilReadInformation(IGregTechTileEntity te){ return undergroundOil(te.getWorld().getChunkFromBlockCoords(te.getXCoord(),te.getZCoord()),-1); @@ -37,81 +44,221 @@ public class GT_UndergroundOil { //Returns whole content for information purposes -> when drainSpeedCoefficient < 0 //Else returns extracted fluidStack if amount > 0, or null otherwise public static FluidStack undergroundOil(Chunk chunk, float readOrDrainCoefficient) { - World aWorld = chunk.worldObj; - int dimensionId=aWorld.provider.dimensionId; - GT_UO_Dimension dimension=GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(dimensionId); - if(dimension==null) return null; - - //Read hash map - HashMap<ChunkCoordIntPair, int[]> chunkData = dimensionWiseChunkData.get(dimensionId); - if(chunkData==null){ - chunkData=new HashMap<>(1024); - dimensionWiseChunkData.put(dimensionId,chunkData); - } - - int[] tInts = chunkData.get(chunk.getChunkCoordIntPair()); - - if(tInts==null) tInts=getDefaultChunkDataOnCreation();//init if null - else if(tInts[GTOIL]==0){//FAST stop - //can return 0 amount stack for info :D - return readOrDrainCoefficient>=0 ? null : new FluidStack(FluidRegistry.getFluid(tInts[GTOILFLUID]),0); - } - - //GEN IT TO GET OBJECT... - final XSTR tRandom = new XSTR(aWorld.getSeed() + dimensionId * 2 + - (chunk.getChunkCoordIntPair().chunkXPos>>3) + - 8267 * (chunk.getChunkCoordIntPair().chunkZPos>>3)); - - GT_UO_Fluid uoFluid = dimension.getRandomFluid(tRandom); - - //Fluid stack holder - FluidStack fluidInChunk; - - //Set fluid stack from uoFluid - if (uoFluid == null || uoFluid.getFluid()==null){ - tInts[GTOILFLUID]=Integer.MAX_VALUE;//null fluid pointer... kind of - tInts[GTOIL]=0; - chunkData.put(chunk.getChunkCoordIntPair(),tInts);//update hash map + ChunkData chunkData = STORAGE.get(chunk); + if (chunkData.getVein() == null || chunkData.getFluid() == null) // nothing here... return null; - } else { - if(tInts[GTOILFLUID]== uoFluid.getFluid().getID()){//if stored fluid matches uoFluid - fluidInChunk = new FluidStack(uoFluid.getFluid(),tInts[GTOIL]); - }else{ - fluidInChunk = new FluidStack(uoFluid.getFluid(), uoFluid.getRandomAmount(tRandom)); - fluidInChunk.amount=(int)((float)fluidInChunk.amount*(0.75f+(XSTR_INSTANCE.nextFloat()/2f)));//Randomly change amounts by +/- 25% - } - tInts[GTOIL]=fluidInChunk.amount; - tInts[GTOILFLUID]=fluidInChunk.getFluidID(); - } - //do stuff on it if needed + FluidStack fluidInChunk = new FluidStack(chunkData.getFluid(), 0); if(readOrDrainCoefficient>=0){ - int fluidExtracted=(int)Math.floor(fluidInChunk.amount * (double) readOrDrainCoefficient / DIVIDER); - double averageDecrease=uoFluid.DecreasePerOperationAmount * (double)readOrDrainCoefficient; + int fluidExtracted = (int) Math.floor(chunkData.getAmount() * (double) readOrDrainCoefficient / DIVIDER); + double averageDecrease = chunkData.getVein().DecreasePerOperationAmount * (double) readOrDrainCoefficient; int decrease=(int)Math.ceil(averageDecrease); - if(fluidExtracted<=0 || fluidInChunk.amount<=decrease){//decrease - here it is max value of extraction for easy check - fluidInChunk=null; - tInts[GTOIL]=0;//so in next access it will stop way above + if (fluidExtracted <= 0 || chunkData.amount <= decrease) {//decrease - here it is max value of extraction for easy check + chunkData.setAmount(0); }else{ fluidInChunk.amount = fluidExtracted;//give appropriate amount - if(XSTR_INSTANCE.nextFloat()<(decrease-averageDecrease)) decrease--;//use XSTR_INSTANCE to "subtract double from int" + if (XSTR_INSTANCE.nextFloat() < (decrease - averageDecrease)) + decrease--;//use XSTR_INSTANCE to "subtract double from int" //ex. // averageDecrease=3.9 // decrease= ceil from 3.9 = 4 // decrease-averageDecrease=0.1 -> chance to subtract 1 // if XSTR_INSTANCE is < chance then subtract 1 - tInts[GTOIL]-=decrease;//diminish amount, "randomly" adjusted to double value (averageDecrease) + chunkData.changeAmount(-decrease);//diminish amount, "randomly" adjusted to double value (averageDecrease) } }else{//just get info if(fluidInChunk.amount<=DIVIDER){ fluidInChunk.amount=0;//return informative stack - tInts[GTOIL]=0;//so in next access it will stop way above + chunkData.setAmount(0); }else{ fluidInChunk.amount=fluidInChunk.amount/DIVIDER;//give moderate extraction speed } } - - chunkData.put(chunk.getChunkCoordIntPair(),tInts);//update hash map return fluidInChunk; } + + static void migrate(ChunkDataEvent.Load e) { + if (e.getData().hasKey("GTOIL") && e.getData().hasKey("GTOILFLUID")) { + ChunkData chunkData = STORAGE.get(e.getChunk()); + Fluid fluid = chunkData.getFluid(); + if (fluid != null && fluid.getID() == e.getData().getInteger("GTOIL")) + chunkData.setAmount(Math.min(chunkData.getAmount(), e.getData().getInteger("GTOILFLUID"))); + } + } + + /** + * Revamped UO store. + * <p> + * Primary functionality: + * + * <ul> + * <li>Decouple data storage with chunk, making it possible to pump oil from unloaded chunks</li> + * <li>Regen detection. If fluid generation config is changed, chunk fluid will be regenerated.</li> + * </ul> + * + * <h2>Serialized form</h2> + * <p> + * Since the exact file layout is controlled by the super class, here we only concern how each chunk's data is written. + * <h3>Form A: Empty Chunk</h3> + * <ol> + * <li>4 bytes of 0 </li> + * </ol> + * + * <h3>Form B: Normal Chunk</h3> + * <ol> + * <li>4 bytes unsigned integer. Vein Hash.</li> + * <li>UTF string. Vein Key.</li> + * <li>4 bytes signed integer. Fluid amount.</li> + * </ol> + * + * @author glease + */ + @ParametersAreNonnullByDefault + private static class GT_UndergroundOilStore extends GT_ChunkAssociatedData<ChunkData> { + private static final GT_UndergroundOil.ChunkData NIL_FLUID_STACK = new GT_UndergroundOil.ChunkData(-1, null, null, false); + private static final WeakHashMap<GT_UO_Fluid, Integer> hashes = new WeakHashMap<>(); + + private GT_UndergroundOilStore() { + super("UO", GT_UndergroundOil.ChunkData.class, 64, (byte) 0, false); + } + + @Override + protected void writeElement(DataOutput output, ChunkData element, World world, int chunkX, int chunkZ) throws IOException { + /* see class javadoc for explanation */ + output.writeInt(element.getVeinHash()); + if (element.getVeinKey() == null) return; + output.writeUTF(element.getVeinKey()); + if (element.getAmount() > 0 && element.getFluid() != null) { + output.writeInt(element.getAmount()); + } else { + output.writeInt(-1); + } + } + + @Override + protected GT_UndergroundOil.ChunkData readElement(DataInput input, int version, World world, int chunkX, int chunkZ) throws IOException { + /* see class javadoc for explanation */ + if (version != 0) + throw new IOException("Region file corrupted"); + GT_UndergroundOil.ChunkData pristine = createElement(world, chunkX, chunkZ); + int hash = input.readInt(); + String veinKey = hash != 0 ? input.readUTF() : null; + int amount = hash != 0 ? input.readInt() : -1; + if (hash != pristine.veinHash || !Objects.equals(veinKey, pristine.getVeinKey())) { + // vein config changed. use regen-ed data. + return pristine; + } + if (hash == 0) + return NIL_FLUID_STACK; + return new GT_UndergroundOil.ChunkData(amount, GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(world.provider.dimensionId).getUOFluid(veinKey), veinKey); + } + + @Override + protected GT_UndergroundOil.ChunkData createElement(World world, int chunkX, int chunkZ) { + int dimensionId = world.provider.dimensionId; + GT_UO_Dimension dimension = GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(dimensionId); + if (dimension == null) return NIL_FLUID_STACK; + // prepare RNG 🙏 🙏 🙏 + final XSTR tRandom = new XSTR(world.getSeed() + dimensionId * 2L + (chunkX >> 3) + 8267L * (chunkZ >> 3)); + GT_UO_Fluid uoFluid = dimension.getRandomFluid(tRandom); + // nothing here :( + if (uoFluid == null || uoFluid.getFluid() == null) return NIL_FLUID_STACK; + // offset each chunk's fluid amount by +-25% + int amount = (int) ((float) uoFluid.getRandomAmount(tRandom) * (0.75f + (XSTR_INSTANCE.nextFloat() / 2f))); + return new GT_UndergroundOil.ChunkData(amount, uoFluid, dimension.getUOFluidKey(uoFluid), false); + } + + private static int hash(@Nullable GT_UO_Fluid fluid) { + if (fluid == null) + return 0; + int result = fluid.Registry.hashCode(); + result = 31 * result + fluid.MaxAmount; + result = 31 * result + fluid.MinAmount; + result = 31 * result + fluid.Chance; + result = 31 * result + fluid.DecreasePerOperationAmount; + return result == 0 ? 1 : result; + } + + } + + /** + * Represent the amount of fluid in a given chunk. + */ + private static final class ChunkData implements GT_ChunkAssociatedData.IData { + private final Fluid fluid; + @Nullable + private final GT_UO_Fluid vein; + private final String veinKey; + private final int veinHash; + private int amount; + private boolean dirty; + + private ChunkData(int amount, GT_UO_Fluid veinKey, String veinID) { + this(amount, veinKey, veinID, true); + } + + private ChunkData(int amount, @Nullable GT_UO_Fluid vein, @Nullable String veinKey, boolean dirty) { + this.amount = amount; + this.vein = vein; + this.dirty = dirty; + if (vein == null) { + fluid = null; + this.veinKey = null; + veinHash = 0; + } else { + fluid = vein.getFluid(); + this.veinKey = veinKey; + veinHash = GT_UndergroundOilStore.hashes.computeIfAbsent(vein, GT_UndergroundOilStore::hash); + } + } + + /** + * The current fluid type. {@code null} if vein is generated to be empty. + */ + @Nullable + public Fluid getFluid() { + return fluid; + } + + /** + * Current fluid amount. Might be 0 if empty. Cannot be negative + */ + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + if (this.amount != amount) + dirty = true; + this.amount = Math.max(0, amount); + } + + public void changeAmount(int delta) { + if (delta != 0) + dirty = true; + this.amount = Math.max(0, amount - delta); + } + + @Nullable + public GT_UO_Fluid getVein() { + return vein; + } + + /** + * The vein ID. Might be null if generated to be empty. + */ + @Nullable + public String getVeinKey() { + return veinKey; + } + + public int getVeinHash() { + return veinHash; + } + + @Override + public boolean isSameAsDefault() { + return dirty; + } + } } diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Arm.java b/src/main/java/gregtech/common/covers/GT_Cover_Arm.java index ed60929719..c64aaa16a1 100644 --- a/src/main/java/gregtech/common/covers/GT_Cover_Arm.java +++ b/src/main/java/gregtech/common/covers/GT_Cover_Arm.java @@ -11,6 +11,7 @@ import gregtech.api.interfaces.tileentity.IMachineProgress; import gregtech.api.net.GT_Packet_TileEntityCover; import gregtech.api.util.GT_CoverBehavior; import gregtech.api.util.GT_Utility; +import gregtech.api.util.ISerializableObject; import net.minecraft.client.gui.GuiButton; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; @@ -111,6 +112,16 @@ public class GT_Cover_Arm extends GT_CoverBehavior { } @Override + protected boolean onCoverRightClickImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + int step = (GT_Utility.getClickedFacingCoords(aSide, aX, aY, aZ)[0] >= 0.5F) ? 1 : -1; + int tCoverVariable = getNewVar(aCoverVariable.get(), step); + sendMessageToPlayer(aPlayer, tCoverVariable); + aCoverVariable.set(tCoverVariable); + return true; + } + + @Override + @SuppressWarnings("deprecation") public boolean onCoverRightclick(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { int step = (GT_Utility.getClickedFacingCoords(aSide, aX, aY, aZ)[0] >= 0.5F) ? 1 : -1; aCoverVariable = getNewVar(aCoverVariable, step); diff --git a/src/main/java/gregtech/common/covers/GT_Cover_FluidRegulator.java b/src/main/java/gregtech/common/covers/GT_Cover_FluidRegulator.java index a53545802a..83a8f20ea9 100644 --- a/src/main/java/gregtech/common/covers/GT_Cover_FluidRegulator.java +++ b/src/main/java/gregtech/common/covers/GT_Cover_FluidRegulator.java @@ -9,6 +9,7 @@ import gregtech.api.interfaces.tileentity.ICoverable; import gregtech.api.net.GT_Packet_TileEntityCover; import gregtech.api.util.GT_CoverBehavior; import gregtech.api.util.GT_Utility; +import gregtech.api.util.ISerializableObject; import net.minecraft.client.gui.GuiButton; import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.common.util.ForgeDirection; @@ -136,6 +137,18 @@ public class GT_Cover_FluidRegulator extends GT_CoverBehavior { } @Override + protected boolean onCoverRightClickImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + if (GT_Utility.getClickedFacingCoords(aSide, aX, aY, aZ)[0] >= 0.5F) { + aCoverVariable.set(adjustSpeed(aPlayer, aCoverVariable.get(), 1)); + } else { + aCoverVariable.set(adjustSpeed(aPlayer, aCoverVariable.get(), -1)); + } + aTileEntity.setCoverDataAtSide(aSide, aCoverVariable); + return true; + } + + @Override + @SuppressWarnings("deprecation") public boolean onCoverRightclick(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { if (GT_Utility.getClickedFacingCoords(aSide, aX, aY, aZ)[0] >= 0.5F) { diff --git a/src/main/java/gregtech/common/covers/GT_Cover_Fluidfilter.java b/src/main/java/gregtech/common/covers/GT_Cover_Fluidfilter.java index 7aab35ddaa..99836c1d99 100644 --- a/src/main/java/gregtech/common/covers/GT_Cover_Fluidfilter.java +++ b/src/main/java/gregtech/common/covers/GT_Cover_Fluidfilter.java @@ -1,22 +1,33 @@ package gregtech.common.covers; +import com.google.common.io.ByteArrayDataInput; import gregtech.api.enums.GT_Values; import gregtech.api.gui.GT_GUICover; import gregtech.api.gui.widgets.GT_GuiFakeItemButton; import gregtech.api.gui.widgets.GT_GuiIcon; import gregtech.api.gui.widgets.GT_GuiIconButton; import gregtech.api.interfaces.tileentity.ICoverable; -import gregtech.api.net.GT_Packet_TileEntityCover; -import gregtech.api.util.GT_CoverBehavior; +import gregtech.api.net.GT_Packet_TileEntityCoverNew; +import gregtech.api.util.GT_CoverBehaviorBase; import gregtech.api.util.GT_Utility; +import gregtech.api.util.ISerializableObject; +import io.netty.buffer.ByteBuf; import net.minecraft.client.gui.GuiButton; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; -import net.minecraftforge.fluids.*; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; + +import javax.annotation.Nonnull; import static gregtech.api.enums.GT_Values.E; -public class GT_Cover_Fluidfilter extends GT_CoverBehavior { +public class GT_Cover_Fluidfilter extends GT_CoverBehaviorBase<GT_Cover_Fluidfilter.FluidFilterData> { // Uses the lower 3 bits of the cover variable, so we have 8 options to work with (0-7) private final int FILTER_INPUT_DENY_OUTPUT = 0; // 000 @@ -28,99 +39,115 @@ public class GT_Cover_Fluidfilter extends GT_CoverBehavior { private final int ANY_INPUT_FILTER_OUTPUT = 6; // 110 private final int ANY_INPUT_INVERT_OUTPUT = 7; // 111 + public GT_Cover_Fluidfilter() { + super(FluidFilterData.class); + } + + @Override + public FluidFilterData createDataObject() { + return new FluidFilterData(-1, 0); + } + + @Override + public FluidFilterData createDataObject(int aLegacyData) { + return new FluidFilterData(aLegacyData >>> 3, aLegacyData & 0x7); + } + @Override - public String getDescription(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { - int aFilterMode = aCoverVariable & 7; - int aFilterFluid = aCoverVariable >>> 3; - final Fluid fluid = FluidRegistry.getFluid(aFilterFluid); - if(fluid == null) return E; - + protected String getDescriptionImpl(byte aSide, int aCoverID, FluidFilterData aCoverVariable, ICoverable aTileEntity) { + final Fluid fluid = FluidRegistry.getFluid(aCoverVariable.mFluidID); + if (fluid == null) return E; + final FluidStack sFluid = new FluidStack(fluid, 1000); - return(String.format("Filtering Fluid: %s Mode: %s", sFluid.getLocalizedName(), getFilterMode(aFilterMode))); + return (String.format("Filtering Fluid: %s Mode: %s", sFluid.getLocalizedName(), getFilterMode(aCoverVariable.mFilterMode))); } @Override - public boolean isRedstoneSensitive(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, long aTimer) { + protected boolean isRedstoneSensitiveImpl(byte aSide, int aCoverID, FluidFilterData aCoverVariable, ICoverable aTileEntity, long aTimer) { return false; } @Override - public int doCoverThings(byte aSide, byte aInputRedstone, int aCoverID, int aCoverVariable, ICoverable aTileEntity, long aTimer) { + protected FluidFilterData doCoverThingsImpl(byte aSide, byte aInputRedstone, int aCoverID, FluidFilterData aCoverVariable, ICoverable aTileEntity, long aTimer) { return aCoverVariable; } public String getFilterMode(int aFilterMode) { - switch(aFilterMode) { - case FILTER_INPUT_DENY_OUTPUT: return(trans("043", "Filter input, Deny output")); - case INVERT_INPUT_DENY_OUTPUT: return(trans("044", "Invert input, Deny output")); - case FILTER_INPUT_ANY_OUTPUT: return(trans("045", "Filter input, Permit any output")); - case INVERT_INPUT_ANY_OUTPUT: return(trans("046", "Invert input, Permit any output")); - case DENY_INPUT_FILTER_OUTPUT: return(trans("219", "Deny input, Filter output")); - case DENY_INPUT_INVERT_OUTPUT: return(trans("220", "Deny input, Invert output")); - case ANY_INPUT_FILTER_OUTPUT: return(trans("221", "Permit any input, Filter output")); - case ANY_INPUT_INVERT_OUTPUT: return(trans("222", "Permit any input, Invert output")); - default: return("UNKNOWN"); + switch (aFilterMode) { + case FILTER_INPUT_DENY_OUTPUT: + return (trans("043", "Filter input, Deny output")); + case INVERT_INPUT_DENY_OUTPUT: + return (trans("044", "Invert input, Deny output")); + case FILTER_INPUT_ANY_OUTPUT: + return (trans("045", "Filter input, Permit any output")); + case INVERT_INPUT_ANY_OUTPUT: + return (trans("046", "Invert input, Permit any output")); + case DENY_INPUT_FILTER_OUTPUT: + return (trans("219", "Deny input, Filter output")); + case DENY_INPUT_INVERT_OUTPUT: + return (trans("220", "Deny input, Invert output")); + case ANY_INPUT_FILTER_OUTPUT: + return (trans("221", "Permit any input, Filter output")); + case ANY_INPUT_INVERT_OUTPUT: + return (trans("222", "Permit any input, Invert output")); + default: + return ("UNKNOWN"); } } @Override - public int onCoverScrewdriverclick(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { - int aFilterMode = aCoverVariable & 7; - aCoverVariable ^= aFilterMode; - aFilterMode = (aFilterMode + (aPlayer.isSneaking()? -1 : 1)) % 8; - if (aFilterMode < 0) { - aFilterMode = 7; + protected FluidFilterData onCoverScrewdriverClickImpl(byte aSide, int aCoverID, FluidFilterData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + aCoverVariable.mFilterMode = (aCoverVariable.mFilterMode + (aPlayer.isSneaking() ? -1 : 1)) % 8; + if (aCoverVariable.mFilterMode < 0) { + aCoverVariable.mFilterMode = 7; } - GT_Utility.sendChatToPlayer(aPlayer, getFilterMode(aFilterMode)); - - aCoverVariable|=aFilterMode; + GT_Utility.sendChatToPlayer(aPlayer, getFilterMode(aCoverVariable.mFilterMode)); return aCoverVariable; } @Override - public boolean onCoverRightclick(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { - //GT_FML_LOGGER.info("rightclick"); + protected boolean onCoverRightClickImpl(byte aSide, int aCoverID, FluidFilterData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { if ( ((aX > 0.375D) && (aX < 0.625D)) || - ((aSide > 3) && ((aY > 0.375D) && (aY < 0.625D))) || - ((aSide < 2) && ((aZ > 0.375D) && (aZ < 0.625D))) || - (aSide == 2) || - (aSide == 3) + ((aSide > 3) && ((aY > 0.375D) && (aY < 0.625D))) || + ((aSide < 2) && ((aZ > 0.375D) && (aZ < 0.625D))) || + (aSide == 2) || + (aSide == 3) ) { ItemStack tStack = aPlayer.inventory.getCurrentItem(); if (tStack == null) return true; - FluidStack tFluid = FluidContainerRegistry.getFluidForFilledItem(tStack); + FluidStack tFluid = GT_Utility.getFluidForFilledItem(tStack, true); if (tFluid != null) { int aFluid = tFluid.getFluidID(); - aCoverVariable = (aCoverVariable & 7) | (aFluid << 3); + aCoverVariable.mFluidID = aFluid; aTileEntity.setCoverDataAtSide(aSide, aCoverVariable); FluidStack sFluid = new FluidStack(FluidRegistry.getFluid(aFluid), 1000); GT_Utility.sendChatToPlayer(aPlayer, trans("047", "Filter Fluid: ") + sFluid.getLocalizedName()); - } else if (tStack.getItem() instanceof IFluidContainerItem) { - IFluidContainerItem tContainer = (IFluidContainerItem) tStack.getItem(); - if (tContainer.getFluid(tStack) != null) { - int aFluid = tContainer.getFluid(tStack).getFluidID(); - aCoverVariable = (aCoverVariable & 7) | (aFluid << 3); - aTileEntity.setCoverDataAtSide(aSide, aCoverVariable); - FluidStack sFluid = new FluidStack(FluidRegistry.getFluid(aFluid), 1000); - GT_Utility.sendChatToPlayer(aPlayer, trans("047", "Filter Fluid: ") + sFluid.getLocalizedName()); - } } return true; } return false; } - + + @Override + protected boolean letsFluidInImpl(byte aSide, int aCoverID, FluidFilterData aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + return isFluidAllowed(aCoverVariable, aFluid); + } + @Override - public boolean letsFluidIn(byte aSide, int aCoverID, int aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + protected boolean letsFluidOutImpl(byte aSide, int aCoverID, FluidFilterData aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + return isFluidAllowed(aCoverVariable, aFluid); + } + + protected boolean isFluidAllowed(FluidFilterData aCoverVariable, Fluid aFluid) { if (aFluid == null) return true; - int aFilterMode = aCoverVariable & 7; - int aFilterFluid = aCoverVariable >>> 3; + int aFilterMode = aCoverVariable.mFilterMode; + int aFilterFluid = aCoverVariable.mFluidID; if (aFilterMode == DENY_INPUT_FILTER_OUTPUT || aFilterMode == DENY_INPUT_INVERT_OUTPUT) return false; @@ -130,36 +157,18 @@ public class GT_Cover_Fluidfilter extends GT_CoverBehavior { return aFilterMode == FILTER_INPUT_DENY_OUTPUT || aFilterMode == FILTER_INPUT_ANY_OUTPUT; else return aFilterMode == INVERT_INPUT_DENY_OUTPUT || aFilterMode == INVERT_INPUT_ANY_OUTPUT; - } - - @Override - public boolean letsFluidOut(byte aSide, int aCoverID, int aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { - if (aFluid == null) return true; - int aFilterMode = aCoverVariable & 7; - int aFilterFluid = aCoverVariable >>> 3; - - if (aFilterMode == FILTER_INPUT_DENY_OUTPUT || aFilterMode == INVERT_INPUT_DENY_OUTPUT) - return false; - else if (aFilterMode == FILTER_INPUT_ANY_OUTPUT || aFilterMode == INVERT_INPUT_ANY_OUTPUT) - return true; - else if (aFluid.getID() == aFilterFluid) - return aFilterMode == DENY_INPUT_FILTER_OUTPUT || aFilterMode == ANY_INPUT_FILTER_OUTPUT; - else - return aFilterMode == DENY_INPUT_INVERT_OUTPUT || aFilterMode == ANY_INPUT_INVERT_OUTPUT; - - } - @Override - public boolean alwaysLookConnected(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { + protected boolean alwaysLookConnectedImpl(byte aSide, int aCoverID, FluidFilterData aCoverVariable, ICoverable aTileEntity) { return true; } @Override - public int getTickRate(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { + protected int getTickRateImpl(byte aSide, int aCoverID, FluidFilterData aCoverVariable, ICoverable aTileEntity) { return 0; } + /** * GUI Stuff */ @@ -170,14 +179,14 @@ public class GT_Cover_Fluidfilter extends GT_CoverBehavior { } @Override - public Object getClientGUI(byte aSide, int aCoverID, int coverData, ICoverable aTileEntity) { + protected Object getClientGUIImpl(byte aSide, int aCoverID, FluidFilterData coverData, ICoverable aTileEntity, EntityPlayer aPlayer, World aWorld) { return new GT_FluidFilterGUICover(aSide, aCoverID, coverData, aTileEntity); } private class GT_FluidFilterGUICover extends GT_GUICover { private final byte side; private final int coverID; - private int coverVariable; + private final FluidFilterData coverVariable; private final GT_GuiFakeItemButton fluidFilterButton; protected String fluidFilterName; @@ -186,8 +195,7 @@ public class GT_Cover_Fluidfilter extends GT_CoverBehavior { private static final int spaceX = 18; private static final int spaceY = 18; - public GT_FluidFilterGUICover(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) - { + public GT_FluidFilterGUICover(byte aSide, int aCoverID, FluidFilterData aCoverVariable, ICoverable aTileEntity) { super(aTileEntity, 176, 107, GT_Utility.intToStack(aCoverID)); this.side = aSide; this.coverID = aCoverID; @@ -201,35 +209,38 @@ public class GT_Cover_Fluidfilter extends GT_CoverBehavior { b = new GT_GuiIconButton(this, 4, startX + spaceX*0, startY+spaceY*1, GT_GuiIcon.WHITELIST).setTooltipText(trans("236","Whitelist Fluid")); b = new GT_GuiIconButton(this, 5, startX + spaceX*1, startY+spaceY*1, GT_GuiIcon.BLACKLIST).setTooltipText(trans("237","Blacklist Fluid")); - fluidFilterButton = new GT_GuiFakeItemButton(this, startX, startY+spaceY*3+2, GT_GuiIcon.SLOT_DARKGRAY); + fluidFilterButton = new GT_GuiFakeItemButton(this, startX, startY + spaceY * 3 + 2, GT_GuiIcon.SLOT_DARKGRAY); } - private int getNewCoverVariable(int id) { + private int getNewFilterMode(int id) { switch (id) { case 0: - return (coverVariable & ~0x7) | (coverVariable & 0x3); + return (coverVariable.mFilterMode & 0x3); case 1: - return (coverVariable & ~0x7) | (coverVariable | 0x4); + return (coverVariable.mFilterMode | 0x4); case 2: - return (coverVariable & ~0x7) | (coverVariable & 0x5); + return (coverVariable.mFilterMode & 0x5); case 3: - return (coverVariable & ~0x7) | (coverVariable | 0x2); + return (coverVariable.mFilterMode | 0x2); case 4: - return (coverVariable & ~0x7) | (coverVariable & 0x6); + return (coverVariable.mFilterMode & 0x6); case 5: - return (coverVariable & ~0x7) | (coverVariable | 0x1); + return (coverVariable.mFilterMode | 0x1); } - return coverVariable; + return coverVariable.mFilterMode; } private boolean getClickable(int id) { switch (id) { - case 0: case 1: - return (coverVariable>>2 & 0x1) != (id & 0x1); - case 2: case 3: - return (coverVariable>>1 & 0x1) != (id & 0x1); - case 4: case 5: - return (coverVariable & 0x1) != (id & 0x1); + case 0: + case 1: + return (coverVariable.mFilterMode >> 2 & 0x1) != (id & 0x1); + case 2: + case 3: + return (coverVariable.mFilterMode >> 1 & 0x1) != (id & 0x1); + case 4: + case 5: + return (coverVariable.mFilterMode & 0x1) != (id & 0x1); } return false; } @@ -250,15 +261,15 @@ public class GT_Cover_Fluidfilter extends GT_CoverBehavior { } @Override - public void buttonClicked(GuiButton btn){ - if (getClickable(btn.id)){ - coverVariable = getNewCoverVariable(btn.id); - GT_Values.NW.sendToServer(new GT_Packet_TileEntityCover(side, coverID, coverVariable, tile)); + public void buttonClicked(GuiButton btn) { + if (getClickable(btn.id)) { + coverVariable.mFilterMode = (byte) getNewFilterMode(btn.id); + GT_Values.NW.sendToServer(new GT_Packet_TileEntityCoverNew(side, coverID, coverVariable, tile)); } updateButtons(); } - private void updateButtons(){ + private void updateButtons() { GT_GuiIconButton b; for (Object o : buttonList) { if (o instanceof GT_GuiIconButton) { @@ -277,7 +288,7 @@ public class GT_Cover_Fluidfilter extends GT_CoverBehavior { } } } - Fluid f = FluidRegistry.getFluid(coverVariable >>> 3); + Fluid f = FluidRegistry.getFluid(coverVariable.mFluidID); if (f != null) { ItemStack item = GT_Utility.getFluidDisplayStack(f); if (item != null) { @@ -290,4 +301,51 @@ public class GT_Cover_Fluidfilter extends GT_CoverBehavior { fluidFilterName = trans("224", "Filter Empty"); } } + + public static class FluidFilterData implements ISerializableObject { + private int mFluidID; + private int mFilterMode; + + public FluidFilterData(int mFluidID, int mFilterMode) { + this.mFluidID = mFluidID; + this.mFilterMode = mFilterMode; + } + + @Override + @Nonnull + public ISerializableObject copy() { + return new FluidFilterData(mFluidID, mFilterMode); + } + + @Override + @Nonnull + public NBTBase saveDataToNBT() { + NBTTagCompound tNBT = new NBTTagCompound(); + tNBT.setInteger("mFilterMode", mFilterMode); + tNBT.setString("mFluid", FluidRegistry.getFluid(mFluidID).getName()); + return tNBT; + } + + @Override + public void writeToByteBuf(ByteBuf aBuf) { + aBuf.writeByte(mFilterMode).writeInt(mFluidID); + } + + @Override + public void loadDataFromNBT(NBTBase aNBT) { + if (aNBT instanceof NBTTagCompound) { + NBTTagCompound tNBT = (NBTTagCompound) aNBT; + mFilterMode = tNBT.getByte("mFilterMod"); + mFluidID = FluidRegistry.getFluidID(tNBT.getString("mFluid")); + } + } + + @Override + @Nonnull + public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) { + mFilterMode = aBuf.readByte(); + mFluidID = aBuf.readInt(); + return this; + } + } } diff --git a/src/main/java/gregtech/common/covers/GT_Cover_ItemFilter.java b/src/main/java/gregtech/common/covers/GT_Cover_ItemFilter.java index 99003e18e0..88ef51dd01 100644 --- a/src/main/java/gregtech/common/covers/GT_Cover_ItemFilter.java +++ b/src/main/java/gregtech/common/covers/GT_Cover_ItemFilter.java @@ -1,134 +1,142 @@ package gregtech.common.covers; +import com.google.common.io.ByteArrayDataInput; +import cpw.mods.fml.common.network.ByteBufUtils; import gregtech.api.enums.GT_Values; import gregtech.api.gui.GT_GUICover; import gregtech.api.gui.widgets.GT_GuiFakeItemButton; import gregtech.api.gui.widgets.GT_GuiIcon; -import gregtech.api.gui.widgets.GT_GuiIconButton; +import gregtech.api.gui.widgets.GT_GuiIconCheckButton; import gregtech.api.interfaces.tileentity.ICoverable; -import gregtech.api.net.GT_Packet_TileEntityCover; -import gregtech.api.util.GT_CoverBehavior; +import gregtech.api.net.GT_Packet_TileEntityCoverNew; +import gregtech.api.util.GT_CoverBehaviorBase; import gregtech.api.util.GT_Utility; +import gregtech.api.util.ISerializableObject; +import io.netty.buffer.ByteBuf; import net.minecraft.client.gui.GuiButton; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.util.Constants; import net.minecraftforge.fluids.Fluid; +import javax.annotation.Nonnull; import java.util.Collections; import java.util.List; -import static gregtech.api.util.GT_Utility.*; +import static gregtech.api.util.GT_Utility.intToStack; +import static gregtech.api.util.GT_Utility.moveMultipleItemStacks; -public class GT_Cover_ItemFilter extends GT_CoverBehavior { +public class GT_Cover_ItemFilter extends GT_CoverBehaviorBase<GT_Cover_ItemFilter.ItemFilterData> { private final boolean mExport; - public GT_Cover_ItemFilter(boolean isExport){ + public GT_Cover_ItemFilter(boolean isExport) { + super(ItemFilterData.class); this.mExport = isExport; } @Override - public boolean isRedstoneSensitive(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, long aTimer) { + public ItemFilterData createDataObject(int aLegacyData) { + return new ItemFilterData((aLegacyData & 0x1) == 0, intToStack(aLegacyData >>> 1)); + } + + @Override + public ItemFilterData createDataObject() { + return new ItemFilterData(); + } + + @Override + protected boolean isRedstoneSensitiveImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity, long aTimer) { return false; } @Override - public int doCoverThings(byte aSide, byte aInputRedstone, int aCoverID, int aCoverVariable, ICoverable aTileEntity, long aTimer) { + protected ItemFilterData doCoverThingsImpl(byte aSide, byte aInputRedstone, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity, long aTimer) { TileEntity tTileEntity = aTileEntity.getTileEntityAtSide(aSide); Object fromEntity = mExport ? aTileEntity : tTileEntity, toEntity = !mExport ? aTileEntity : tTileEntity; byte fromSide = !mExport ? GT_Utility.getOppositeSide(aSide) : aSide, toSide = mExport ? GT_Utility.getOppositeSide(aSide) : aSide; - int FilterId = aCoverVariable >>> 1; - List<ItemStack> Filter = Collections.singletonList(intToStack(FilterId)); + List<ItemStack> Filter = Collections.singletonList(aCoverVariable.mFilter); - boolean isWhiteList = (aCoverVariable & 1) != 0; - - moveMultipleItemStacks(fromEntity, toEntity, fromSide , toSide, Filter, isWhiteList, (byte) 64, (byte) 1, (byte) 64, (byte) 1,64); + moveMultipleItemStacks(fromEntity, toEntity, fromSide, toSide, Filter, aCoverVariable.mWhitelist, (byte) 64, (byte) 1, (byte) 64, (byte) 1, 64); return aCoverVariable; } @Override - public boolean onCoverRightclick(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ){ - ItemStack tStack = aPlayer.inventory.getCurrentItem(); - if (tStack != null){ - aCoverVariable = (stackToInt(tStack) << 1) + (aCoverVariable & 1); - aTileEntity.setCoverDataAtSide(aSide, aCoverVariable); - GT_Utility.sendChatToPlayer(aPlayer, trans("301", "Item Filter: ") + tStack.getDisplayName()); - } - else{ - aCoverVariable = aCoverVariable & 1; - aTileEntity.setCoverDataAtSide(aSide, aCoverVariable); - GT_Utility.sendChatToPlayer(aPlayer, trans("300", "Filter Cleared!")); - } - return true; + protected boolean onCoverRightClickImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + ItemStack tStack = aPlayer.inventory.getCurrentItem(); + if (tStack != null) { + aCoverVariable.mFilter = tStack; + GT_Utility.sendChatToPlayer(aPlayer, trans("301", "Item Filter: ") + tStack.getDisplayName()); + } else { + aCoverVariable.mFilter = null; + GT_Utility.sendChatToPlayer(aPlayer, trans("300", "Filter Cleared!")); + } + return true; } @Override - public int onCoverScrewdriverclick(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { - int mode = aCoverVariable & 1; - if (mode == 1) mode = 0; - else mode = 1; - if (mode == 1){ - GT_Utility.sendChatToPlayer(aPlayer, trans("124", "Blacklist Mode")); - } - else{ - GT_Utility.sendChatToPlayer(aPlayer, trans("125", "Whitelist Mode")); - } - aCoverVariable = (aCoverVariable & ~0x1) + mode; + protected ItemFilterData onCoverScrewdriverClickImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + aCoverVariable.mWhitelist = !aCoverVariable.mWhitelist; + GT_Utility.sendChatToPlayer(aPlayer, aCoverVariable.mWhitelist ? trans("125", "Whitelist Mode") : trans("124", "Blacklist Mode")); return aCoverVariable; } @Override - public boolean letsRedstoneGoIn(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { + protected boolean letsRedstoneGoInImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity) { return true; } @Override - public boolean letsRedstoneGoOut(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { + protected boolean letsRedstoneGoOutImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity) { return true; } @Override - public boolean letsEnergyIn(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { + protected boolean letsEnergyInImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity) { return true; } @Override - public boolean letsEnergyOut(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { + protected boolean letsEnergyOutImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity) { return true; } @Override - public boolean letsFluidIn(byte aSide, int aCoverID, int aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + protected boolean letsFluidInImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { return false; } @Override - public boolean letsFluidOut(byte aSide, int aCoverID, int aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + protected boolean letsFluidOutImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { return false; } @Override - public boolean letsItemsIn(byte aSide, int aCoverID, int aCoverVariable, int aSlot, ICoverable aTileEntity) { + protected boolean letsItemsInImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, int aSlot, ICoverable aTileEntity) { return true; } @Override - public boolean letsItemsOut(byte aSide, int aCoverID, int aCoverVariable, int aSlot, ICoverable aTileEntity) { + protected boolean letsItemsOutImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, int aSlot, ICoverable aTileEntity) { return true; } @Override - public boolean alwaysLookConnected(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { + protected boolean alwaysLookConnectedImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity) { return true; } @Override - public int getTickRate(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { + protected int getTickRateImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity) { return 1; } @@ -142,14 +150,68 @@ public class GT_Cover_ItemFilter extends GT_CoverBehavior { } @Override - public Object getClientGUI(byte aSide, int aCoverID, int coverData, ICoverable aTileEntity) { - return new GT_Cover_ItemFilter.GUI(aSide, aCoverID, coverData, aTileEntity); + protected Object getClientGUIImpl(byte aSide, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, World aWorld) { + return new GT_Cover_ItemFilter.GUI(aSide, aCoverID, aCoverVariable, aTileEntity); + } + + public static class ItemFilterData implements ISerializableObject { + private boolean mWhitelist; + private ItemStack mFilter; + + public ItemFilterData() { + } + + public ItemFilterData(boolean mWhitelist, ItemStack mFilter) { + this.mWhitelist = mWhitelist; + this.mFilter = mFilter; + } + + @Nonnull + @Override + public ISerializableObject copy() { + return new ItemFilterData(mWhitelist, mFilter); + } + + @Nonnull + @Override + public NBTBase saveDataToNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setBoolean("mWhitelist", mWhitelist); + if (mFilter != null) + tag.setTag("mFilter", mFilter.writeToNBT(new NBTTagCompound())); + return tag; + } + + @Override + public void writeToByteBuf(ByteBuf aBuf) { + aBuf.writeBoolean(mWhitelist); + ByteBufUtils.writeItemStack(aBuf, mFilter); + } + + @Override + public void loadDataFromNBT(NBTBase aNBT) { + NBTTagCompound tag = (NBTTagCompound) aNBT; + mWhitelist = tag.getBoolean("mWhitelist"); + if (tag.hasKey("mFilter", Constants.NBT.TAG_COMPOUND)) + mFilter = ItemStack.loadItemStackFromNBT(tag.getCompoundTag("mFilter")); + else + mFilter = null; + } + + @Nonnull + @Override + public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) { + mWhitelist = aBuf.readBoolean(); + mFilter = ISerializableObject.readItemStackFromGreggyByteBuf(aBuf); + return this; + } } private class GUI extends GT_GUICover { private final byte side; private final int coverID; - private int coverVariable; + private final GT_GuiIconCheckButton btnMode; + private final ItemFilterData coverVariable; private final GT_GuiFakeItemButton itemFilterButtons; private static final int startX = 10; @@ -157,17 +219,15 @@ public class GT_Cover_ItemFilter extends GT_CoverBehavior { private static final int spaceX = 18; private static final int spaceY = 18; - public GUI(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity) { + public GUI(byte aSide, int aCoverID, ItemFilterData aCoverVariable, ICoverable aTileEntity) { super(aTileEntity, 176, 107, GT_Utility.intToStack(aCoverID)); this.side = aSide; this.coverID = aCoverID; this.coverVariable = aCoverVariable; - GT_GuiIconButton b; - b = new GT_GuiIconButton(this, 0, startX + spaceX*0, startY+spaceY*0, GT_GuiIcon.WHITELIST).setTooltipText(trans("125","Whitelist Mode")); - b = new GT_GuiIconButton(this, 1, startX + spaceX*1, startY+spaceY*0, GT_GuiIcon.BLACKLIST).setTooltipText(trans("124","Blacklist Mode")); + btnMode = new GT_GuiIconCheckButton(this, 0, startX + spaceX * 0, startY + spaceY * 0, GT_GuiIcon.WHITELIST, GT_GuiIcon.BLACKLIST, trans("125", "Whitelist Mode"), trans("124", "Blacklist Mode")); - itemFilterButtons = new GT_GuiFakeItemButton(this ,startX + spaceX*0, startY+spaceY*2, GT_GuiIcon.SLOT_GRAY); + itemFilterButtons = new GT_GuiFakeItemButton(this, startX + spaceX * 0, startY + spaceY * 2, GT_GuiIcon.SLOT_GRAY); } @Override @@ -183,46 +243,19 @@ public class GT_Cover_ItemFilter extends GT_CoverBehavior { } @Override - public void buttonClicked(GuiButton btn){ - if (getClickable(btn.id)){ - coverVariable = getNewCoverVariable(btn.id); - GT_Values.NW.sendToServer(new GT_Packet_TileEntityCover(side, coverID, coverVariable, tile)); + public void buttonClicked(GuiButton btn) { + if (btn == btnMode) { + if (coverVariable.mWhitelist != btnMode.isChecked()) { + coverVariable.mWhitelist = btnMode.isChecked(); + GT_Values.NW.sendToServer(new GT_Packet_TileEntityCoverNew(side, coverID, coverVariable, tile)); + } } updateButtons(); } - private void updateButtons(){ - GuiButton b; - for (Object o : buttonList) { - b = (GuiButton) o; - b.enabled = getClickable(b.id); - } - ItemStack tItemStack = intToStack(coverVariable >>> 1); - if (tItemStack != null){ - itemFilterButtons.setItem(tItemStack); - return; - } - itemFilterButtons.setItem(null); - } - - private int getNewCoverVariable(int id) { - switch (id) { - case 0: - return coverVariable & ~0x1; - case 1: - return coverVariable | 0x1; - } - return coverVariable; - } - - private boolean getClickable(int id) { - switch (id) { - case 0: - return (0x1 & coverVariable) != 0; - case 1: - return (0x1 & coverVariable) == 0; - } - return false; + private void updateButtons() { + btnMode.setChecked(coverVariable.mWhitelist); + itemFilterButtons.setItem(coverVariable.mFilter); } } } diff --git a/src/main/java/gregtech/common/covers/GT_Cover_ItemMeter.java b/src/main/java/gregtech/common/covers/GT_Cover_ItemMeter.java index f1c1bc7df7..74e5438bde 100644 --- a/src/main/java/gregtech/common/covers/GT_Cover_ItemMeter.java +++ b/src/main/java/gregtech/common/covers/GT_Cover_ItemMeter.java @@ -14,7 +14,6 @@ import gregtech.api.util.GT_CoverBehavior; import gregtech.api.util.GT_Utility; import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_OutputBus_ME; import gregtech.common.tileentities.storage.GT_MetaTileEntity_DigitalChestBase; - import net.minecraft.client.gui.GuiButton; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -46,25 +45,22 @@ public class GT_Cover_ItemMeter extends GT_CoverBehavior { long tMax = 0; long tUsed = 0; - IMetaTileEntity mte = ((IGregTechTileEntity)aTileEntity).getMetaTileEntity(); + IMetaTileEntity mte = ((IGregTechTileEntity) aTileEntity).getMetaTileEntity(); if (mte instanceof GT_MetaTileEntity_DigitalChestBase) { - GT_MetaTileEntity_DigitalChestBase dc = (GT_MetaTileEntity_DigitalChestBase)mte; + GT_MetaTileEntity_DigitalChestBase dc = (GT_MetaTileEntity_DigitalChestBase) mte; tMax = dc.getMaxItemCount(); // currently it is limited by int, but there is not much reason for that ItemStack[] inv = dc.getStoredItemData(); if (inv != null && inv.length > 1 && inv[1] != null) tUsed = inv[1].stackSize; - } - else if (mte instanceof GT_MetaTileEntity_Hatch_OutputBus_ME) { - if (((GT_MetaTileEntity_Hatch_OutputBus_ME)mte).isLastOutputFailed()) - { + } else if (mte instanceof GT_MetaTileEntity_Hatch_OutputBus_ME) { + if (((GT_MetaTileEntity_Hatch_OutputBus_ME) mte).isLastOutputFailed()) { tMax = 64; tUsed = 64; } - } - else { + } else { int[] tSlots = (aCoverVariable & SLOT_MASK) > 0 ? - new int[] {(aCoverVariable & SLOT_MASK) - 1} : - aTileEntity.getAccessibleSlotsFromSide(aSide); + new int[]{(aCoverVariable & SLOT_MASK) - 1} : + aTileEntity.getAccessibleSlotsFromSide(aSide); for (int i : tSlots) { if (i >= 0 && i < aTileEntity.getSizeInventory()) { diff --git a/src/main/java/gregtech/common/covers/GT_Cover_RedstoneWirelessBase.java b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneWirelessBase.java index 577cff3d7a..62f8d3550b 100644 --- a/src/main/java/gregtech/common/covers/GT_Cover_RedstoneWirelessBase.java +++ b/src/main/java/gregtech/common/covers/GT_Cover_RedstoneWirelessBase.java @@ -12,6 +12,7 @@ import gregtech.api.net.GT_Packet_TileEntityCover; import gregtech.api.net.GT_Packet_WirelessRedstoneCover; import gregtech.api.util.GT_CoverBehavior; import gregtech.api.util.GT_Utility; +import gregtech.api.util.ISerializableObject; import net.minecraft.client.gui.GuiButton; import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.fluids.Fluid; @@ -25,14 +26,26 @@ public abstract class GT_Cover_RedstoneWirelessBase extends GT_CoverBehavior { @Override public boolean onCoverRemoval(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, boolean aForced) { - GregTech_API.sWirelessRedstone.put(Integer.valueOf(aCoverVariable), Byte.valueOf((byte) 0)); + GregTech_API.sWirelessRedstone.put(aCoverVariable, (byte) 0); return true; } @Override + protected boolean onCoverRightClickImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + if (((aX > 0.375D) && (aX < 0.625D)) || ((aSide > 3) && ((aY > 0.375D) && (aY < 0.625D)))) { + GregTech_API.sWirelessRedstone.put(aCoverVariable.get(), (byte) 0); + aCoverVariable.set((aCoverVariable.get() & (PRIVATE_MASK | CHECKBOX_MASK)) | (((Integer)GT_Utility.stackToInt(aPlayer.inventory.getCurrentItem())).hashCode() & PUBLIC_MASK)); + GT_Utility.sendChatToPlayer(aPlayer, trans("081", "Frequency: ") + aCoverVariable); + return true; + } + return false; + } + + @Override + @SuppressWarnings("deprecation") public boolean onCoverRightclick(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { if (((aX > 0.375D) && (aX < 0.625D)) || ((aSide > 3) && ((aY > 0.375D) && (aY < 0.625D)))) { - GregTech_API.sWirelessRedstone.put(Integer.valueOf(aCoverVariable), Byte.valueOf((byte) 0)); + GregTech_API.sWirelessRedstone.put(aCoverVariable, (byte) 0); int val = GT_Utility.stackToInt(aPlayer.inventory.getCurrentItem()) * (1 + aPlayer.inventory.getCurrentItem().getItemDamage()); @@ -48,7 +61,7 @@ public abstract class GT_Cover_RedstoneWirelessBase extends GT_CoverBehavior { @Override public int onCoverScrewdriverclick(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { if (((aX > 0.375D) && (aX < 0.625D)) || ((aSide <= 3) || (((aY > 0.375D) && (aY < 0.625D)) || ((((aZ <= 0.375D) || (aZ >= 0.625D))))))) { - GregTech_API.sWirelessRedstone.put(Integer.valueOf(aCoverVariable), Byte.valueOf((byte) 0)); + GregTech_API.sWirelessRedstone.put(aCoverVariable, (byte) 0); float[] tCoords = GT_Utility.getClickedFacingCoords(aSide, aX, aY, aZ); short tAdjustVal = 0; diff --git a/src/main/java/gregtech/common/covers/GT_Cover_SolarPanel.java b/src/main/java/gregtech/common/covers/GT_Cover_SolarPanel.java index ae1b73b8cb..09a9d5ab69 100644 --- a/src/main/java/gregtech/common/covers/GT_Cover_SolarPanel.java +++ b/src/main/java/gregtech/common/covers/GT_Cover_SolarPanel.java @@ -3,6 +3,7 @@ package gregtech.common.covers; import gregtech.api.interfaces.tileentity.ICoverable; import gregtech.api.util.GT_CoverBehavior; import gregtech.api.util.GT_Utility; +import gregtech.api.util.ISerializableObject; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; @@ -58,6 +59,29 @@ public class GT_Cover_SolarPanel extends GT_CoverBehavior { } @Override + protected boolean onCoverRightClickImpl(byte aSide, int aCoverID, ISerializableObject.LegacyCoverData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + if(aPlayer.capabilities.isCreativeMode){ + GT_Utility.sendChatToPlayer(aPlayer,"Cleaned solar panel from "+(aCoverVariable.get()>>2)+"% dirt"); + aCoverVariable.set(aCoverVariable.get() & 0x3); + return true; + } + for(int i=0;i<aPlayer.inventory.mainInventory.length;i++){ + ItemStack is=aPlayer.inventory.mainInventory[i]; + if(is==null) continue; + if(is.getUnlocalizedName().equals(new ItemStack(Items.water_bucket).getUnlocalizedName())){ + aPlayer.inventory.mainInventory[i]=new ItemStack(Items.bucket); + if (aPlayer.inventoryContainer != null) aPlayer.inventoryContainer.detectAndSendChanges(); + GT_Utility.sendChatToPlayer(aPlayer,"Cleaned solar panel from "+(aCoverVariable.get()>>2)+"% dirt"); + aCoverVariable.set(aCoverVariable.get() & 0x3); + return true; + } + } + GT_Utility.sendChatToPlayer(aPlayer,"You need water bucket in inventory to clean the panel."); + return false; + } + + @Override + @SuppressWarnings("deprecation") public boolean onCoverRightclick(byte aSide, int aCoverID, int aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { if(aPlayer.capabilities.isCreativeMode){ GT_Utility.sendChatToPlayer(aPlayer,"Cleaned solar panel from "+(aCoverVariable>>2)+"% dirt"); diff --git a/src/main/java/gregtech/common/misc/GT_Command.java b/src/main/java/gregtech/common/misc/GT_Command.java index 13e26353d8..4f6f77ea70 100644 --- a/src/main/java/gregtech/common/misc/GT_Command.java +++ b/src/main/java/gregtech/common/misc/GT_Command.java @@ -61,7 +61,7 @@ public final class GT_Command extends CommandBase { } else if (test.equals("toggle")) { String test1 = ss[1].trim(); Stream.of("D1", "D2", "debugCleanroom", "debugDriller", "debugBlockPump", "debugBlockMiner", "debugWorldGen", "debugEntityCramming", - "debugOrevein", "debugSmallOres", "debugStones", "debugChunkloaders", "debugMulti") + "debugOrevein", "debugSmallOres", "debugStones", "debugChunkloaders", "debugMulti", "debugWorldData") .filter(s -> test1.isEmpty() || s.startsWith(test1)) .forEach(l::add); diff --git a/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler.java b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler.java index 4fb9deb5b4..96b991e767 100644 --- a/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler.java +++ b/src/main/java/gregtech/common/tileentities/boilers/GT_MetaTileEntity_Boiler.java @@ -175,7 +175,7 @@ public abstract class GT_MetaTileEntity_Boiler extends GT_MetaTileEntity_BasicTa @Override public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCover) { - return GregTech_API.getCoverBehavior(aCover.toStack()).isSimpleCover(); + return GregTech_API.getCoverBehaviorNew(aCover.toStack()).isSimpleCover(); } @Override diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java index eab4e9c896..61fb394841 100644 --- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java +++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PrimitiveBlastFurnace.java @@ -114,7 +114,7 @@ public abstract class GT_MetaTileEntity_PrimitiveBlastFurnace extends MetaTileEn @Override public boolean allowCoverOnSide(byte aSide, GT_ItemStack aCoverID) { - return (GregTech_API.getCoverBehavior(aCoverID.toStack()).isSimpleCover()) && (super.allowCoverOnSide(aSide, aCoverID)); + return (GregTech_API.getCoverBehaviorNew(aCoverID.toStack()).isSimpleCover()) && (super.allowCoverOnSide(aSide, aCoverID)); } @Override diff --git a/src/main/java/gregtech/loaders/postload/GT_MachineRecipeLoader.java b/src/main/java/gregtech/loaders/postload/GT_MachineRecipeLoader.java index 74fd68ff4b..77dc5a4cc7 100644 --- a/src/main/java/gregtech/loaders/postload/GT_MachineRecipeLoader.java +++ b/src/main/java/gregtech/loaders/postload/GT_MachineRecipeLoader.java @@ -1259,10 +1259,10 @@ public class GT_MachineRecipeLoader implements Runnable { GT_Values.RA.addChemicalRecipeForBasicMachineOnly(Materials.Carbon.getDust(1), Materials.Empty.getCells(1), Materials.Hydrogen.getGas(4000L), GT_Values.NF, Materials.Methane.getCells(1), GT_Values.NI, 200, 30); GT_Values.RA.addChemicalRecipeForBasicMachineOnly(GT_OreDictUnificator.get(OrePrefixes.cell, Materials.Oxygen, 1L), GT_Values.NI, Materials.Hydrogen.getGas(2000L), GT_ModHandler.getDistilledWater(1000L), ItemList.Cell_Empty.get(1L), GT_Values.NI, 10, 30); GT_Values.RA.addChemicalRecipeForBasicMachineOnly(GT_OreDictUnificator.get(OrePrefixes.cell, Materials.Hydrogen, 1L), GT_Values.NI, Materials.Oxygen.getGas(500L), GT_ModHandler.getDistilledWater(500L), ItemList.Cell_Empty.get(1L), GT_Values.NI, 5, 30); - GT_Values.RA.addMultiblockChemicalRecipe(new ItemStack[]{GT_Utility.getIntegratedCircuit(1)}, new FluidStack[]{Materials.Hydrogen.getGas(2000), Materials.Oxygen.getGas(1000)}, new FluidStack[]{GT_ModHandler.getDistilledWater(1000)}, new ItemStack[]{}, 10, 30); - GT_Values.RA.addChemicalRecipe(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Rutile, 1L), GT_OreDictUnificator.get(OrePrefixes.cell, Materials.Carbon, 2L), Materials.Chlorine.getGas(4000L), Materials.Titaniumtetrachloride.getFluid(1000L), GT_OreDictUnificator.get(OrePrefixes.cell, Materials.CarbonMonoxide, 2L), 500, 480); - GT_Values.RA.addChemicalRecipe(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Rutile, 1L), GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Carbon, 2L), Materials.Chlorine.getGas(4000L), Materials.Titaniumtetrachloride.getFluid(1000L), GT_Values.NI, 500, 480); - GT_Values.RA.addChemicalRecipe(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Sodium, 1L), GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Magnesiumchloride, 2L), GT_Values.NF, Materials.Chlorine.getGas(3000L), GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Magnesium, 2L), 300, 240); + GT_Values.RA.addMultiblockChemicalRecipe(new ItemStack[]{GT_Utility.getIntegratedCircuit(22)}, new FluidStack[]{Materials.Hydrogen.getGas(16000), Materials.Oxygen.getGas(8000)}, new FluidStack[]{GT_ModHandler.getDistilledWater(8000)}, new ItemStack[]{}, 80, 30); + GT_Values.RA.addChemicalRecipe(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Rutile, 1L), GT_OreDictUnificator.get(OrePrefixes.cell, Materials.Carbon, 2L), Materials.Chlorine.getGas(4000L), Materials.Titaniumtetrachloride.getFluid(1000L), GT_OreDictUnificator.get(OrePrefixes.cell, Materials.CarbonMonoxide, 2L), 400, 480); + GT_Values.RA.addChemicalRecipe(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Rutile, 1L), GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Carbon, 2L), Materials.Chlorine.getGas(4000L), Materials.Titaniumtetrachloride.getFluid(1000L), GT_Values.NI, 400, 480); + GT_Values.RA.addChemicalRecipe(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Sodium, 1L), GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Magnesiumchloride, 2L), GT_Values.NF, Materials.Chlorine.getGas(3000L), GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Magnesium, 2L), 400, 300); GT_Values.RA.addChemicalRecipe(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.RawRubber, 9L), GT_OreDictUnificator.get(OrePrefixes.dust, Materials.Sulfur, 1L), GT_Values.NF, Materials.Rubber.getMolten(1296L), GT_Values.NI, 600, 16); GT_Values.RA.addChemicalRecipe(GT_OreDictUnificator.get(OrePrefixes.dust, Materials.RawRubber, 1L), GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Sulfur, 1L), GT_Values.NF, Materials.Rubber.getMolten(144L), GT_Values.NI, 100, 16); |