diff options
Diffstat (limited to 'src/main')
27 files changed, 1292 insertions, 71 deletions
diff --git a/src/main/java/gregtech/GT_Mod.java b/src/main/java/gregtech/GT_Mod.java index 1309186528..f834af648d 100644 --- a/src/main/java/gregtech/GT_Mod.java +++ b/src/main/java/gregtech/GT_Mod.java @@ -1,5 +1,6 @@ package gregtech; +import appeng.api.AEApi; import com.google.common.base.Stopwatch; import cpw.mods.fml.common.*; import cpw.mods.fml.common.event.*; @@ -20,6 +21,7 @@ import gregtech.common.GT_DummyWorld; import gregtech.common.GT_Network; import gregtech.common.GT_Proxy; import gregtech.common.GT_RecipeAdder; +import gregtech.common.covers.GT_Cover_FacadeAE; import gregtech.common.entities.GT_Entity_Arrow; import gregtech.common.entities.GT_Entity_Arrow_Potion; import gregtech.common.misc.GT_Command; @@ -343,8 +345,15 @@ public class GT_Mod implements IGT_Mod { GT_Forestry_Compat.transferCentrifugeRecipes(); GT_Forestry_Compat.transferSqueezerRecipes(); } - if (GregTech_API.mAE2) + if (GregTech_API.mAE2) { GT_MetaTileEntity_DigitalChestBase.registerAEIntegration(); + ItemStack facade = AEApi.instance().definitions().items().facade().maybeItem() + .transform(i -> new ItemStack(i, 1, GT_Values.W)) + .orNull(); + if (facade != null) { + GregTech_API.registerCover(facade, null, new GT_Cover_FacadeAE()); + } + } Arrays.stream(new String[]{ diff --git a/src/main/java/gregtech/api/GregTech_API.java b/src/main/java/gregtech/api/GregTech_API.java index 23c4bdade0..011bd3d86e 100644 --- a/src/main/java/gregtech/api/GregTech_API.java +++ b/src/main/java/gregtech/api/GregTech_API.java @@ -767,9 +767,10 @@ public class GregTech_API { if (aStack == null || aStack.getItem() == null) return sNoBehavior; GT_CoverBehaviorBase<?> rCover = sCoverBehaviors.get(new GT_ItemStack(aStack)); - if (rCover == null) - return sDefaultBehavior; - return rCover; + if (rCover != null) return rCover; + rCover = sCoverBehaviors.get(new GT_ItemStack(aStack, true)); + if (rCover != null) return rCover; + return sDefaultBehavior; } /** diff --git a/src/main/java/gregtech/api/enums/GT_Values.java b/src/main/java/gregtech/api/enums/GT_Values.java index 6505c34423..d922c2787c 100644 --- a/src/main/java/gregtech/api/enums/GT_Values.java +++ b/src/main/java/gregtech/api/enums/GT_Values.java @@ -9,7 +9,9 @@ import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.oredict.OreDictionary; +import java.util.HashSet; import java.util.Locale; +import java.util.Set; /** * Made for static imports, this Class is just a Helper. @@ -303,6 +305,8 @@ public class GT_Values { public static boolean debugChunkloaders = false; public static boolean cls_enabled; + public static final Set<String> mCTMEnabledBlock = new HashSet<>(); + public static final Set<String> mCTMDisabledBlock = new HashSet<>(); public static boolean hideAssLineRecipes = false; public static boolean updateFluidDisplayItems = true; diff --git a/src/main/java/gregtech/api/interfaces/ITextureBuilder.java b/src/main/java/gregtech/api/interfaces/ITextureBuilder.java index d72b538243..d0d25328b9 100644 --- a/src/main/java/gregtech/api/interfaces/ITextureBuilder.java +++ b/src/main/java/gregtech/api/interfaces/ITextureBuilder.java @@ -65,6 +65,22 @@ public interface ITextureBuilder { ITextureBuilder stdOrient(); /** + * Force using world coord overload of getIcon. + * + * @return {@link ITextureBuilder} for chaining + * @throws IllegalStateException if setFromBlock has never been called. + */ + ITextureBuilder useWorldCoord(); + + /** + * Force using meta overload of getIcon. + * + * @return {@link ITextureBuilder} for chaining + * @throws IllegalStateException if setFromBlock has never been called. + */ + ITextureBuilder noWorldCoord(); + + /** * Texture will orientate from block's {@link ExtendedFacing} * * @return {@link ITextureBuilder} for chaining diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java index bd060d9ae8..e0125ae50a 100644 --- a/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java +++ b/src/main/java/gregtech/api/metatileentity/BaseMetaPipeEntity.java @@ -8,10 +8,8 @@ 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; -import gregtech.api.enums.Textures.BlockIcons; import gregtech.api.graphs.Node; import gregtech.api.graphs.paths.NodePath; import gregtech.api.interfaces.ITexture; @@ -25,12 +23,9 @@ 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 net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -147,6 +142,9 @@ public class BaseMetaPipeEntity extends CoverableGregTechTileEntity implements I oZ = zCoord; if (isServerSide()) checkDropCover(); + else { + requestCoverDataIfNeeded(); + } worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this); mMetaTileEntity.onFirstTick(this); if (!hasValidMetaTileEntity()) return; @@ -247,6 +245,7 @@ public class BaseMetaPipeEntity extends CoverableGregTechTileEntity implements I ); mSendClientData = false; } + sendCoverDataIfNeeded(); } @Override @@ -371,22 +370,11 @@ public class BaseMetaPipeEntity extends CoverableGregTechTileEntity implements I @Override public void issueCoverUpdate(byte aSide) { + super.issueCoverUpdate(aSide); issueClientUpdate(); } @Override - public void receiveCoverData(byte coverSide, int coverID, int coverData) { - if ((coverSide >= 0 && coverSide < 6) && (mCoverSides[coverSide] == coverID)) - setCoverDataAtSide(coverSide, coverData); - } - - @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)))))); } @@ -401,14 +389,6 @@ public class BaseMetaPipeEntity extends CoverableGregTechTileEntity implements I return getInternalInputRedstoneSignal(aSide) > 0; } - public ITexture getCoverTexture(byte aSide) { - if (getCoverIDAtSide(aSide) == 0) return null; - if (GT_Mod.instance.isClientSide() && (GT_Client.hideValue & 0x1) != 0) { - return BlockIcons.HIDDEN_TEXTURE[0]; // See through - } - return GregTech_API.sCovers.get(new GT_ItemStack(getCoverIDAtSide(aSide))); - } - @Override public boolean isGivingInformation() { if (canAccessData()) return mMetaTileEntity.isGivingInformation(); @@ -860,8 +840,8 @@ public class BaseMetaPipeEntity extends CoverableGregTechTileEntity implements I if (getCoverIDAtSide(aSide) == 0) coverSide = tSide; if (getCoverIDAtSide(coverSide) == 0) { - if (GregTech_API.sCovers.containsKey(new GT_ItemStack(tCurrentItem))) { - if (GregTech_API.getCoverBehaviorNew(tCurrentItem).isCoverPlaceable(coverSide, new GT_ItemStack(tCurrentItem), this) && + if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sCovers.keySet())) { + if (GregTech_API.getCoverBehaviorNew(tCurrentItem).isCoverPlaceable(coverSide, tCurrentItem, this) && mMetaTileEntity.allowCoverOnSide(coverSide, new GT_ItemStack(tCurrentItem))) { setCoverItemAtSide(coverSide, tCurrentItem); diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java index ddcb9b99cd..5786edc8ce 100644 --- a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java @@ -19,7 +19,6 @@ import gregtech.GT_Mod; import gregtech.api.GregTech_API; import gregtech.api.enums.ItemList; import gregtech.api.enums.Textures; -import gregtech.api.enums.Textures.BlockIcons; import gregtech.api.graphs.GenerateNodeMap; import gregtech.api.graphs.GenerateNodeMapPower; import gregtech.api.graphs.Node; @@ -32,7 +31,6 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch; import gregtech.api.net.GT_Packet_TileEntity; import gregtech.api.objects.GT_ItemStack; import gregtech.api.util.*; -import gregtech.common.GT_Client; import gregtech.common.GT_Pollution; import ic2.api.Direction; import net.minecraft.block.Block; @@ -40,7 +38,6 @@ 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; @@ -271,6 +268,8 @@ public class BaseMetaTileEntity extends CoverableGregTechTileEntity implements I oZ = zCoord; if (aSideServer) { checkDropCover(); + } else { + requestCoverDataIfNeeded(); } worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this); mMetaTileEntity.onFirstTick(this); @@ -552,6 +551,7 @@ public class BaseMetaTileEntity extends CoverableGregTechTileEntity implements I ); mSendClientData = false; } + sendCoverDataIfNeeded(); } @Override @@ -706,22 +706,11 @@ public class BaseMetaTileEntity extends CoverableGregTechTileEntity implements I @Override public void issueCoverUpdate(byte aSide) { + super.issueCoverUpdate(aSide); issueClientUpdate(); } @Override - public void receiveCoverData(byte coverSide, int coverID, int coverData) { - if ((coverSide >= 0 && coverSide < 6) && (mCoverSides[coverSide] == coverID)) - setCoverDataAtSide(coverSide, coverData); - } - - @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)))))); } @@ -736,14 +725,6 @@ public class BaseMetaTileEntity extends CoverableGregTechTileEntity implements I return getInternalInputRedstoneSignal(aSide) > 0; } - public ITexture getCoverTexture(byte aSide) { - if (getCoverIDAtSide(aSide) == 0) return null; - if (GT_Mod.instance.isClientSide() && (GT_Client.hideValue & 0x1) != 0) { - return BlockIcons.HIDDEN_TEXTURE[0]; // See through - } - return GregTech_API.sCovers.get(new GT_ItemStack(getCoverIDAtSide(aSide))); - } - @Override public boolean isGivingInformation() { if (canAccessData()) return mMetaTileEntity.isGivingInformation(); @@ -1403,8 +1384,8 @@ public class BaseMetaTileEntity extends CoverableGregTechTileEntity implements I if (getCoverIDAtSide(aSide) == 0) coverSide = GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ); if (getCoverIDAtSide(coverSide) == 0) { - if (GregTech_API.sCovers.containsKey(new GT_ItemStack(tCurrentItem))) { - if (GregTech_API.getCoverBehaviorNew(tCurrentItem).isCoverPlaceable(coverSide, new GT_ItemStack(tCurrentItem), this) && + if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sCovers.keySet())) { + if (GregTech_API.getCoverBehaviorNew(tCurrentItem).isCoverPlaceable(coverSide, tCurrentItem, this) && mMetaTileEntity.allowCoverOnSide(coverSide, new GT_ItemStack(tCurrentItem))) { setCoverItemAtSide(coverSide, tCurrentItem); diff --git a/src/main/java/gregtech/api/metatileentity/CoverableGregTechTileEntity.java b/src/main/java/gregtech/api/metatileentity/CoverableGregTechTileEntity.java index 0460f93f78..13bb70dbda 100644 --- a/src/main/java/gregtech/api/metatileentity/CoverableGregTechTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/CoverableGregTechTileEntity.java @@ -2,15 +2,21 @@ package gregtech.api.metatileentity; import gregtech.GT_Mod; import gregtech.api.GregTech_API; +import gregtech.api.enums.Textures; +import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.net.GT_Packet_RequestCoverData; +import gregtech.api.net.GT_Packet_SendCoverData; import gregtech.api.objects.GT_ItemStack; 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.common.GT_Client; import gregtech.common.covers.GT_Cover_Fluidfilter; import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -20,13 +26,15 @@ import net.minecraftforge.fluids.FluidRegistry; import java.util.Arrays; import static gregtech.GT_Mod.GT_FML_LOGGER; +import static gregtech.api.enums.GT_Values.NW; public abstract class CoverableGregTechTileEntity extends BaseTileEntity implements IGregTechTileEntity { - static final String[] COVER_DATA_NBT_KEYS = Arrays.stream(ForgeDirection.VALID_DIRECTIONS).mapToInt(Enum::ordinal).mapToObj(i -> "mCoverData" + i).toArray(String[]::new); + public static final String[] COVER_DATA_NBT_KEYS = Arrays.stream(ForgeDirection.VALID_DIRECTIONS).mapToInt(Enum::ordinal).mapToObj(i -> "mCoverData" + i).toArray(String[]::new); protected 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 int[] mCoverSides = new int[]{0, 0, 0, 0, 0, 0}; protected ISerializableObject[] mCoverData = new ISerializableObject[6]; + protected final boolean[] mCoverNeedUpdate = new boolean[]{false, false, false, false, false, false}; protected short mID = 0; public long mTickTimer = 0; @@ -115,6 +123,8 @@ public abstract class CoverableGregTechTileEntity extends BaseTileEntity impleme mCoverData[i] = mCoverBehaviors[i].createDataObject(aNBT.getTag(COVER_DATA_NBT_KEYS[i])); else mCoverData[i] = mCoverBehaviors[i].createDataObject(); + if (mCoverBehaviors[i].isDataNeededOnClient(i, mCoverSides[i], mCoverData[i], this)) + issueCoverUpdate(i); } } } @@ -145,7 +155,29 @@ public abstract class CoverableGregTechTileEntity extends BaseTileEntity impleme mCoverBehaviors[i] = GregTech_API.getCoverBehaviorNew(mCoverSides[i]); } - protected abstract boolean hasValidMetaTileEntity(); + @Override + public void issueCoverUpdate(byte aSide) { + if (isServerSide() && getCoverBehaviorAtSideNew(aSide).isDataNeededOnClient(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this)) + mCoverNeedUpdate[aSide] = true; + } + + public ITexture getCoverTexture(byte aSide) { + if (getCoverIDAtSide(aSide) == 0) return null; + if (GT_Mod.instance.isClientSide() && (GT_Client.hideValue & 0x1) != 0) { + return Textures.BlockIcons.HIDDEN_TEXTURE[0]; // See through + } + ITexture coverTexture = getCoverBehaviorAtSideNew(aSide).getSpecialCoverTexture(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this); + return coverTexture != null ? coverTexture : GregTech_API.sCovers.get(new GT_ItemStack(getCoverIDAtSide(aSide))); + } + + protected void requestCoverDataIfNeeded() { + for (byte i = 0; i < 6; i++) { + if (getCoverBehaviorAtSideNew(i).isDataNeededOnClient(i, getCoverIDAtSide(i), getComplexCoverDataAtSide(i), this)) + NW.sendToServer(new GT_Packet_RequestCoverData(i, getCoverIDAtSide(i), this)); + } + } + + protected abstract boolean hasValidMetaTileEntity(); protected boolean createNewMetatileEntity(short aID) { if (aID <= 0 || aID >= GregTech_API.METATILEENTITIES.length || GregTech_API.METATILEENTITIES[aID] == null) { @@ -162,7 +194,9 @@ public abstract class CoverableGregTechTileEntity extends BaseTileEntity impleme @Override public void setCoverIDAtSide(byte aSide, int aID) { - if (aSide >= 0 && aSide < 6) { + if (aSide >= 0 && aSide < 6 && mCoverSides[aSide] != aID) { + if (aID == 0 && isClientSide()) + mCoverBehaviors[aSide].onDropped(aSide, mCoverSides[aSide], mCoverData[aSide], this); mCoverSides[aSide] = aID; mCoverBehaviors[aSide] = GregTech_API.getCoverBehaviorNew(aID); mCoverData[aSide] = mCoverBehaviors[aSide].createDataObject(); @@ -192,7 +226,7 @@ public abstract class CoverableGregTechTileEntity extends BaseTileEntity impleme @Override public ItemStack getCoverItemAtSide(byte aSide) { - return GT_Utility.intToStack(getCoverIDAtSide(aSide)); + return getCoverBehaviorAtSideNew(aSide).getDisplayStack(getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide)); } @Override @@ -245,7 +279,7 @@ public abstract class CoverableGregTechTileEntity extends BaseTileEntity impleme 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); + getCoverBehaviorAtSideNew(aSide).onDropped(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this); EntityItem tEntity = new EntityItem(worldObj, getOffsetX(aDroppedSide, 1) + 0.5, getOffsetY(aDroppedSide, 1) + 0.5, getOffsetZ(aDroppedSide, 1) + 0.5, tStack); tEntity.motionX = 0; tEntity.motionY = 0; @@ -264,4 +298,33 @@ public abstract class CoverableGregTechTileEntity extends BaseTileEntity impleme setOutputRedstoneSignal(aSide, (byte) 0); } + @Override + public void receiveCoverData(byte coverSide, int coverID, int coverData) { + if ((coverSide >= 0 && coverSide < 6) && (mCoverSides[coverSide] == coverID)) + setCoverDataAtSide(coverSide, coverData); + } + + @Override + public void receiveCoverData(byte aCoverSide, int aCoverID, ISerializableObject aCoverData, EntityPlayerMP aPlayer) { + if ((aCoverSide >= 0 && aCoverSide < 6) && (mCoverSides[aCoverSide] == aCoverID)) { + setCoverDataAtSide(aCoverSide, aCoverData); + if (isClientSide()) + getCoverBehaviorAtSideNew(aCoverSide).onDataChanged(aCoverSide, aCoverID, aCoverData, this); + } + } + + protected void sendCoverDataIfNeeded() { + int mCoverNeedUpdateLength = mCoverNeedUpdate.length; + for (byte i = 0; i < mCoverNeedUpdateLength; i++) { + if (mCoverNeedUpdate[i]) { + NW.sendPacketToAllPlayersInRange( + worldObj, + new GT_Packet_SendCoverData( + i, getCoverIDAtSide(i), getComplexCoverDataAtSide(i), this), + xCoord, zCoord + ); + mCoverNeedUpdate[i] = false; + } + } + } } diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_EnhancedMultiBlockBase.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_EnhancedMultiBlockBase.java index 8f54112885..a2de864f41 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_EnhancedMultiBlockBase.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_EnhancedMultiBlockBase.java @@ -55,6 +55,7 @@ public abstract class GT_MetaTileEntity_EnhancedMultiBlockBase<T extends GT_Meta mExtendedFacing = newExtendedFacing; IGregTechTileEntity base = getBaseMetaTileEntity(); mMachine = false; + mUpdated = false; mUpdate = 100; if (getBaseMetaTileEntity().isServerSide()) { StructureLibAPI.sendAlignment((IAlignmentProvider) base, diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java index 8fa9819e6a..5564ff6b88 100644 --- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java +++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java @@ -39,7 +39,8 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity { public boolean mMachine = false, mWrench = false, mScrewdriver = false, mSoftHammer = false, mHardHammer = false, mSolderingTool = false, mCrowbar = false, mRunningOnLoad = false; public boolean mStructureChanged = false; public int mPollution = 0, mProgresstime = 0, mMaxProgresstime = 0, mEUt = 0, mEfficiencyIncrease = 0, mStartUpCheck = 100, mRuntime = 0, mEfficiency = 0; - public volatile int mUpdate = 0; //TODO: Replace with AtomicInteger + public volatile boolean mUpdated = false; + public int mUpdate = 0; public ItemStack[] mOutputItems = null; public FluidStack[] mOutputFluids = null; public String mNEI; @@ -243,7 +244,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity { @Override public void onMachineBlockUpdate() { - mUpdate = 50; + mUpdated = true; } /** @@ -280,6 +281,10 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity { public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { if (aBaseMetaTileEntity.isServerSide()) { if (mEfficiency < 0) mEfficiency = 0; + if (mUpdated) { + mUpdate = 50; + mUpdated = false; + } if (--mUpdate == 0 || --mStartUpCheck == 0) { checkStructure(true, aBaseMetaTileEntity); } diff --git a/src/main/java/gregtech/api/net/GT_Packet_RequestCoverData.java b/src/main/java/gregtech/api/net/GT_Packet_RequestCoverData.java new file mode 100644 index 0000000000..93bc5eba72 --- /dev/null +++ b/src/main/java/gregtech/api/net/GT_Packet_RequestCoverData.java @@ -0,0 +1,102 @@ +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 : ask for cover data + */ +public class GT_Packet_RequestCoverData extends GT_Packet_New { + protected int mX; + protected short mY; + protected int mZ; + + protected byte side; + protected int coverID; + + protected EntityPlayerMP mPlayer; + + public GT_Packet_RequestCoverData() { + super(true); + } + + public GT_Packet_RequestCoverData(int mX, short mY, int mZ, byte coverSide, int coverID) { + super(false); + this.mX = mX; + this.mY = mY; + this.mZ = mZ; + + this.side = coverSide; + this.coverID = coverID; + } + public GT_Packet_RequestCoverData(byte coverSide, int coverID, ICoverable tile) { + super(false); + this.mX = tile.getXCoord(); + this.mY = tile.getYCoord(); + this.mZ = tile.getZCoord(); + + this.side = coverSide; + this.coverID = coverID; + } + + @Override + public byte getPacketID() { + return 17; + } + + @Override + public void encode(ByteBuf aOut) { + aOut.writeInt(mX); + aOut.writeShort(mY); + aOut.writeInt(mZ); + + aOut.writeByte(side); + aOut.writeInt(coverID); + } + + @Override + public GT_Packet_New decode(ByteArrayDataInput aData) { + return new GT_Packet_RequestCoverData( + aData.readInt(), + aData.readShort(), + aData.readInt(), + + aData.readByte(), + aData.readInt() + ); + } + + @Override + public void setINetHandler(INetHandler aHandler) { + if (aHandler instanceof NetHandlerPlayServer) { + mPlayer = ((NetHandlerPlayServer) aHandler).playerEntity; + } + } + + @Override + public void process(IBlockAccess aWorld) { + if (mPlayer == null) // impossible, but who knows + return; + World world = DimensionManager.getWorld(mPlayer.dimension); + if (world != null) { + TileEntity tile = world.getTileEntity(mX, mY, mZ); + if (tile instanceof IGregTechTileEntity) { + IGregTechTileEntity te = (IGregTechTileEntity) tile; + if (!te.isDead() && te.getCoverIDAtSide(side) == coverID) { + te.issueCoverUpdate(side); + } + } + } + } +} diff --git a/src/main/java/gregtech/api/net/GT_Packet_SendCoverData.java b/src/main/java/gregtech/api/net/GT_Packet_SendCoverData.java new file mode 100644 index 0000000000..3e1abac4e7 --- /dev/null +++ b/src/main/java/gregtech/api/net/GT_Packet_SendCoverData.java @@ -0,0 +1,90 @@ +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.tileentity.TileEntity; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; + +/** + * Server -> Client : Update cover data + */ +public class GT_Packet_SendCoverData extends GT_Packet_New { + protected int mX; + protected short mY; + protected int mZ; + + protected byte side; + protected int coverID; + protected ISerializableObject coverData; + + public GT_Packet_SendCoverData() { + super(true); + } + + public GT_Packet_SendCoverData(int mX, short mY, int mZ, byte coverSide, int coverID, ISerializableObject coverData) { + super(false); + this.mX = mX; + this.mY = mY; + this.mZ = mZ; + + this.side = coverSide; + this.coverID = coverID; + this.coverData = coverData; + } + public GT_Packet_SendCoverData(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; + } + + @Override + public byte getPacketID() { + return 16; + } + + @Override + public void encode(ByteBuf aOut) { + aOut.writeInt(mX); + aOut.writeShort(mY); + aOut.writeInt(mZ); + + aOut.writeByte(side); + aOut.writeInt(coverID); + coverData.writeToByteBuf(aOut); + } + + @Override + public GT_Packet_New decode(ByteArrayDataInput aData) { + int coverId; + return new GT_Packet_SendCoverData( + aData.readInt(), + aData.readShort(), + aData.readInt(), + + aData.readByte(), + coverId = aData.readInt(), + GregTech_API.getCoverBehaviorNew(coverId).createDataObject().readFromPacket(aData, null) + ); + } + + @Override + public void process(IBlockAccess aWorld) { + if (aWorld != null) { + TileEntity tile = aWorld.getTileEntity(mX, mY, mZ); + if (tile instanceof IGregTechTileEntity && !((IGregTechTileEntity) tile).isDead()) { + ((IGregTechTileEntity) tile).receiveCoverData(side, coverID, coverData, null); + } + } + } +} diff --git a/src/main/java/gregtech/api/util/GT_BlockMap.java b/src/main/java/gregtech/api/util/GT_BlockMap.java new file mode 100644 index 0000000000..cd98aae2bd --- /dev/null +++ b/src/main/java/gregtech/api/util/GT_BlockMap.java @@ -0,0 +1,133 @@ +package gregtech.api.util; + +import gnu.trove.map.TByteObjectMap; +import gnu.trove.map.hash.TByteObjectHashMap; +import net.minecraft.block.Block; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiFunction; + +public class GT_BlockMap<V> { + public static final byte WILDCARD = -1; + private final Map<Block, TByteObjectMap<V>> backing = new HashMap<>(); + private int size = 0; + + private TByteObjectMap<V> getSubmap(Block block) { + return backing.computeIfAbsent(block, b -> new TByteObjectHashMap<>()); + } + + /** + * Associate a value with that union key + * + * @param block block + * @param meta meta + * @return old mapping, or null if that doesn't exist + */ + public V put(Block block, byte meta, V value) { + V v = getSubmap(block).put(meta, value); + if (v == null) size++; + return v; + } + + /** + * Associate a value with that union key ONLY IF there isn't a prior EXACT mapping + * + * @param block block + * @param meta meta + * @return old mapping, or null if that doesn't exist + */ + public V putIfAbsent(Block block, byte meta, V value) { + V v = getSubmap(block).putIfAbsent(meta, value); + if (v == null) size++; + return v; + } + + /** + * Associate a value with that union key ONLY IF there isn't a prior EXACT mapping + * + * @param block block + * @param meta meta + * @return old mapping, or null if that doesn't exist + */ + public V computeIfAbsent(Block block, byte meta, BiFunction<Block, Byte, V> function) { + TByteObjectMap<V> submap = getSubmap(block); + V v = submap.get(meta); + if (v == null) { + v = function.apply(block, meta); + submap.put(meta, v); + size++; + } + return v; + } + + /** + * Contains an associated value + * + * @param block block + * @param meta meta + * @return current mapping OR wildcard of that mapping exists + */ + public boolean containsKey(Block block, byte meta) { + TByteObjectMap<V> submap = backing.get(block); + if (submap == null) return false; + return submap.containsKey(meta) || submap.containsKey(WILDCARD); + } + + /** + * Get the associated value + * + * @param block block + * @param meta meta + * @return current mapping OR wildcard of that block. null if neither exists + */ + public V get(Block block, byte meta) { + TByteObjectMap<V> submap = backing.get(block); + if (submap == null) return null; + V v = submap.get(meta); + if (v != null) return v; + return submap.get(WILDCARD); + } + + /** + * Remove a mapping + * + * @param block block + * @param meta meta + * @return old value, or null if none + */ + public V remove(Block block, byte meta) { + TByteObjectMap<V> submap = backing.get(block); + if (submap == null) return null; + V v = submap.remove(meta); + if (v != null) { + size--; + if (submap.isEmpty()) backing.remove(block); + } + return v; + } + + /** + * Size of all mappings + * + * @return size + */ + public int size() { + return size; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + GT_BlockMap<?> that = (GT_BlockMap<?>) o; + + return backing.equals(that.backing); + } + + @Override + public int hashCode() { + return backing.hashCode(); + } +} diff --git a/src/main/java/gregtech/api/util/GT_BlockSet.java b/src/main/java/gregtech/api/util/GT_BlockSet.java new file mode 100644 index 0000000000..3c9905a757 --- /dev/null +++ b/src/main/java/gregtech/api/util/GT_BlockSet.java @@ -0,0 +1,38 @@ +package gregtech.api.util; + +import net.minecraft.block.Block; + +public class GT_BlockSet { + private final GT_BlockMap<Object> backing = new GT_BlockMap<>(); + + public boolean add(Block block, byte meta) { + return backing.put(block, meta, this) != this; + } + + public boolean contains(Block block, byte meta) { + return backing.get(block, meta) == this; + } + + public boolean remove(Block block, byte meta) { + return backing.remove(block, meta) == this; + } + + public int size() { + return backing.size(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + GT_BlockSet that = (GT_BlockSet) o; + + return backing.equals(that.backing); + } + + @Override + public int hashCode() { + return backing.hashCode(); + } +} diff --git a/src/main/java/gregtech/api/util/GT_Config.java b/src/main/java/gregtech/api/util/GT_Config.java index 6849988a77..f78abc52fb 100644 --- a/src/main/java/gregtech/api/util/GT_Config.java +++ b/src/main/java/gregtech/api/util/GT_Config.java @@ -92,6 +92,19 @@ public class GT_Config implements Runnable { return rResult; } + public String[] get(Object aCategory, ItemStack aStack, String... aDefault) { + return get(aCategory, getStackConfigName(aStack), aDefault); + } + + public String[] get(Object aCategory, String aName, String... aDefault) { + if (GT_Utility.isStringInvalid(aName)) return aDefault; + Property tProperty = mConfig.get(aCategory.toString().replaceAll("\\|", "_"), aName.replaceAll("\\|", "_"), aDefault); + String[] rResult = tProperty.getStringList(); + if (!tProperty.wasRead() && GregTech_API.sPostloadFinished) mConfig.save(); + return rResult; + } + + @Override public void run() { mConfig.save(); diff --git a/src/main/java/gregtech/api/util/GT_CoverBehaviorBase.java b/src/main/java/gregtech/api/util/GT_CoverBehaviorBase.java index a6970ed4bd..6f3c098899 100644 --- a/src/main/java/gregtech/api/util/GT_CoverBehaviorBase.java +++ b/src/main/java/gregtech/api/util/GT_CoverBehaviorBase.java @@ -1,9 +1,11 @@ package gregtech.api.util; import gregtech.api.enums.GT_Values; +import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.tileentity.ICoverable; import gregtech.api.net.GT_Packet_TileEntityCoverGUI; import gregtech.api.objects.GT_ItemStack; +import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; @@ -59,6 +61,63 @@ public abstract class GT_CoverBehaviorBase<T extends ISerializableObject> { // region facade + /** + * Get target facade block. Does not affect rendering of **this** block. It is only used as a hint for other block + * in case of CTM + * @return null if none, otherwise return facade target block + */ + public final Block getFacadeBlock(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return getFacadeBlockImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * Get target facade block. Does not affect rendering of **this** block. It is only used as a hint for other block + * in case of CTM + * @return 0 if none, otherwise return facade target meta + */ + public final int getFacadeMeta(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return getFacadeMetaImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * Get the display stack. Default to {@code int2Stack(aCoverID)} + */ + public final ItemStack getDisplayStack(int aCoverID, ISerializableObject aCoverVariable) { + return getDisplayStackImpl(aCoverID,forceCast(aCoverVariable)); + } + + /** + * Get the special cover texture associated with this cover. Return null if one should use the texture passed to + * {@link gregtech.api.GregTech_API#registerCover(ItemStack, ITexture, GT_CoverBehaviorBase)} or its overloads. + */ + public final ITexture getSpecialCoverTexture(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return getSpecialCoverTextureImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * Return whether cover data needs to be synced to client upon tile entity creation or cover placement. + * + * Note if you want to sync the data afterwards you will have to manually do it by calling {@link ICoverable#issueCoverUpdate(byte)} + * This option only affects the initial sync. + */ + public final boolean isDataNeededOnClient(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + return isDataNeededOnClientImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * Called upon receiving data from network. Use {@link ICoverable#isClientSide()} to determine the side. + */ + public final void onDataChanged(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + onDataChangedImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + + /** + * Called upon cover being removed. Called on both server and client. + */ + public final void onDropped(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity) { + onDroppedImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity); + } + public final boolean isRedstoneSensitive(byte aSide, int aCoverID, ISerializableObject aCoverVariable, ICoverable aTileEntity, long aTimer) { return isRedstoneSensitiveImpl(aSide, aCoverID, forceCast(aCoverVariable), aTileEntity, aTimer); } @@ -252,6 +311,33 @@ public abstract class GT_CoverBehaviorBase<T extends ISerializableObject> { // region impl + protected Block getFacadeBlockImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return null; + } + + protected int getFacadeMetaImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return 0; + } + + protected ItemStack getDisplayStackImpl(int aCoverID, T aCoverVariable) { + return GT_Utility.intToStack(aCoverID); + } + + protected ITexture getSpecialCoverTextureImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return null; + } + + protected boolean isDataNeededOnClientImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + return false; + } + + protected void onDataChangedImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + } + + + protected void onDroppedImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity) { + } + protected boolean isRedstoneSensitiveImpl(byte aSide, int aCoverID, T aCoverVariable, ICoverable aTileEntity, long aTimer) { return true; } @@ -454,6 +540,14 @@ public abstract class GT_CoverBehaviorBase<T extends ISerializableObject> { /** * Checks if the Cover can be placed on this. */ + public boolean isCoverPlaceable(byte aSide, ItemStack aStack, ICoverable aTileEntity) { + return isCoverPlaceable(aSide, new GT_ItemStack(aStack), aTileEntity); + } + + /** + * Checks if the Cover can be placed on this. You will probably want to call {@link #isCoverPlaceable(byte, ItemStack, ICoverable)} instead. + */ + @Deprecated public boolean isCoverPlaceable(byte aSide, GT_ItemStack aStack, ICoverable aTileEntity) { return true; } diff --git a/src/main/java/gregtech/api/util/GT_RenderingWorld.java b/src/main/java/gregtech/api/util/GT_RenderingWorld.java new file mode 100644 index 0000000000..920ce76357 --- /dev/null +++ b/src/main/java/gregtech/api/util/GT_RenderingWorld.java @@ -0,0 +1,191 @@ +package gregtech.api.util; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.EventPriority; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.TickEvent; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.ChunkPosition; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.event.world.ChunkEvent; +import net.minecraftforge.event.world.WorldEvent; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Provide a fake IBlockAccess to support CTM. Facade are supposed to set these when they are placed/received by client. + */ +public class GT_RenderingWorld implements IBlockAccess { + private static final GT_RenderingWorld INSTANCE = new GT_RenderingWorld(); + /* + * I do not think this map would ever grow too huge, so I won't go too overcomplicated on this one + */ + private final Map<ChunkPosition, BlockInfo> infos = new HashMap<>(); + private final Map<ChunkCoordIntPair, Set<ChunkPosition>> index = new HashMap<>(); + private IBlockAccess mWorld = Minecraft.getMinecraft().theWorld; + + private GT_RenderingWorld() { + new FMLEventHandler(); + new ForgeEventHandler(); + } + + public static GT_RenderingWorld getInstance() { + return INSTANCE; + } + + public static GT_RenderingWorld getInstance(IBlockAccess aWorld) { + if (aWorld == INSTANCE) + return INSTANCE; + if (aWorld == null) + INSTANCE.mWorld = Minecraft.getMinecraft().theWorld; + else + INSTANCE.mWorld = aWorld; + return INSTANCE; + } + + private void setWorld(IBlockAccess aWorld) { + if (aWorld == null) + mWorld = Minecraft.getMinecraft().theWorld; + else + mWorld = aWorld; + } + + public void register(int x, int y, int z, Block block, int meta) { + ChunkPosition key = new ChunkPosition(x, y, z); + infos.put(key, new BlockInfo(block, meta)); + index.computeIfAbsent(new ChunkCoordIntPair(x >> 4, z >> 4), p -> new HashSet<>()).add(key); + } + + public void unregister(int x, int y, int z, Block block, int meta) { + ChunkPosition key = new ChunkPosition(x, y, z); + if (infos.remove(key, new BlockInfo(block, meta))) { + ChunkCoordIntPair chunkKey = new ChunkCoordIntPair(x >> 4, z >> 4); + Set<ChunkPosition> set = index.get(chunkKey); + set.remove(key); + if (set.isEmpty()) + index.remove(chunkKey); + } + } + + @Override + public Block getBlock(int p_147439_1_, int p_147439_2_, int p_147439_3_) { + BlockInfo blockInfo = infos.get(new ChunkPosition(p_147439_1_, p_147439_2_, p_147439_3_)); + return blockInfo != null ? blockInfo.block : mWorld.getBlock(p_147439_1_, p_147439_2_, p_147439_3_); + } + + @Override + public TileEntity getTileEntity(int p_147438_1_, int p_147438_2_, int p_147438_3_) { + return mWorld.getTileEntity(p_147438_1_, p_147438_2_, p_147438_3_); + } + + @Override + public int getLightBrightnessForSkyBlocks(int p_72802_1_, int p_72802_2_, int p_72802_3_, int p_72802_4_) { + return mWorld.getLightBrightnessForSkyBlocks(p_72802_1_, p_72802_2_, p_72802_3_, p_72802_4_); + } + + @Override + public int getBlockMetadata(int p_72805_1_, int p_72805_2_, int p_72805_3_) { + BlockInfo blockInfo = infos.get(new ChunkPosition(p_72805_1_, p_72805_2_, p_72805_3_)); + return blockInfo != null ? blockInfo.meta : mWorld.getBlockMetadata(p_72805_1_, p_72805_2_, p_72805_3_); + } + + @Override + public int isBlockProvidingPowerTo(int p_72879_1_, int p_72879_2_, int p_72879_3_, int p_72879_4_) { + return mWorld.isBlockProvidingPowerTo(p_72879_1_, p_72879_2_, p_72879_3_, p_72879_4_); + } + + @Override + public boolean isAirBlock(int p_147437_1_, int p_147437_2_, int p_147437_3_) { + return getBlock(p_147437_1_, p_147437_2_, p_147437_3_).isAir(mWorld, p_147437_1_, p_147437_2_, p_147437_3_); + } + + @Override + public BiomeGenBase getBiomeGenForCoords(int p_72807_1_, int p_72807_2_) { + return mWorld.getBiomeGenForCoords(p_72807_1_, p_72807_2_); + } + + @Override + public int getHeight() { + return mWorld.getHeight(); + } + + @Override + public boolean extendedLevelsInChunkCache() { + return mWorld.extendedLevelsInChunkCache(); + } + + @Override + public boolean isSideSolid(int x, int y, int z, ForgeDirection side, boolean _default) { + return getBlock(x, y, z).isSideSolid(this, x, y, z, side); + } + + public class FMLEventHandler { + public FMLEventHandler() { + FMLCommonHandler.instance().bus().register(this); + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onRenderTickStart(TickEvent.RenderTickEvent e) { + if (e.phase == TickEvent.Phase.START) + mWorld = Minecraft.getMinecraft().theWorld; + } + } + + public class ForgeEventHandler { + private ForgeEventHandler() { + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void onChunkUnloaded(ChunkEvent.Unload e) { + if (!e.world.isRemote) return; + Set<ChunkPosition> set = index.remove(e.getChunk().getChunkCoordIntPair()); + if (set != null) + infos.keySet().removeAll(set); + } + + @SubscribeEvent + public void onWorldUnloaded(WorldEvent.Unload e) { + if (!e.world.isRemote) return; + infos.clear(); + index.clear(); + } + } + + private static class BlockInfo { + private final Block block; + private final int meta; + + public BlockInfo(Block block, int meta) { + this.block = block; + this.meta = meta; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + BlockInfo blockInfo = (BlockInfo) o; + + if (meta != blockInfo.meta) return false; + return block != null ? block.equals(blockInfo.block) : blockInfo.block == null; + } + + @Override + public int hashCode() { + int result = block != null ? block.hashCode() : 0; + result = 31 * result + meta; + return result; + } + } +} diff --git a/src/main/java/gregtech/api/util/ISerializableObject.java b/src/main/java/gregtech/api/util/ISerializableObject.java index b31abaa843..536aea7545 100644 --- a/src/main/java/gregtech/api/util/ISerializableObject.java +++ b/src/main/java/gregtech/api/util/ISerializableObject.java @@ -12,6 +12,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagInt; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; /** @@ -45,10 +46,11 @@ public interface ISerializableObject { /** * 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. + * @param aPlayer the player who is sending this packet to server. null if it's client reading data. */ // 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); + ISerializableObject readFromPacket(ByteArrayDataInput aBuf, @Nullable EntityPlayerMP aPlayer); /** * Reverse engineered and adapted {@link cpw.mods.fml.common.network.ByteBufUtils#readTag(ByteBuf)} diff --git a/src/main/java/gregtech/common/GT_Network.java b/src/main/java/gregtech/common/GT_Network.java index ef28a26a97..8db38d86f7 100644 --- a/src/main/java/gregtech/common/GT_Network.java +++ b/src/main/java/gregtech/common/GT_Network.java @@ -51,7 +51,9 @@ public class GT_Network extends MessageToMessageCodec<FMLProxyPacket, GT_Packet> new GT_Packet_SetConfigurationCircuit(), new GT_Packet_UpdateItem(), new GT_Packet_SetLockedFluid(), - new GT_Packet_GtTileEntityGuiRequest() + new GT_Packet_GtTileEntityGuiRequest(), + new GT_Packet_SendCoverData(), + new GT_Packet_RequestCoverData() ); } diff --git a/src/main/java/gregtech/common/GT_Proxy.java b/src/main/java/gregtech/common/GT_Proxy.java index 403f7a43b8..ec4362ec75 100644 --- a/src/main/java/gregtech/common/GT_Proxy.java +++ b/src/main/java/gregtech/common/GT_Proxy.java @@ -140,7 +140,8 @@ public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler { "arditeRod", "manyullynRod", "bronzeRod", "boneRod", "slimeRod", "redalloyBundled", "bluestoneBundled", "infusedteslatiteInsulated", "redalloyInsulated", "infusedteslatiteBundled")); private final DateFormat mDateFormat = DateFormat.getInstance(); - public ArrayList<String> mBufferedPlayerActivity = new ArrayList(); + public ArrayList<String> mBufferedPlayerActivity = new ArrayList<>(); + public final GT_BlockMap<Boolean> mCTMBlockCache = new GT_BlockMap<>(); public boolean mHardcoreCables = false; public boolean mDisableVanillaOres = true; public boolean mHardMachineCasings = true; diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Casings4.java b/src/main/java/gregtech/common/blocks/GT_Block_Casings4.java index 2bd94c6ccb..cef115f0c0 100644 --- a/src/main/java/gregtech/common/blocks/GT_Block_Casings4.java +++ b/src/main/java/gregtech/common/blocks/GT_Block_Casings4.java @@ -2,11 +2,13 @@ package gregtech.common.blocks; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import gregtech.GT_Mod; import gregtech.api.enums.ItemList; import gregtech.api.enums.Textures; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.render.TextureFactory; import gregtech.api.util.GT_LanguageManager; +import gregtech.api.util.GT_RenderingWorld; import gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_LargeTurbine; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; @@ -67,6 +69,9 @@ public class GT_Block_Casings4 extends GT_Block_Casings_Abstract { ItemList.Casing_EngineIntake.set(new ItemStack(this, 1, 13)); ItemList.Casing_MiningOsmiridium.set(new ItemStack(this, 1, 14)); ItemList.Casing_Firebricks.set(new ItemStack(this, 1, 15)); + + GT_Mod.gregtechproxy.mCTMBlockCache.put(this, (byte) 6, true); + GT_Mod.gregtechproxy.mCTMBlockCache.put(this, (byte) 8, true); } @Override @@ -148,6 +153,7 @@ public class GT_Block_Casings4 extends GT_Block_Casings_Abstract { @Override @SideOnly(Side.CLIENT) public IIcon getIcon(IBlockAccess aWorld, int xCoord, int yCoord, int zCoord, int aSide) { + aWorld = GT_RenderingWorld.getInstance(aWorld); int tMeta = aWorld.getBlockMetadata(xCoord, yCoord, zCoord); if (tMeta != 6 && tMeta != 8 && tMeta != 9 && tMeta != 10 && tMeta != 11 && tMeta != 12 || !mConnectedMachineTextures) { return getIcon(aSide, tMeta); diff --git a/src/main/java/gregtech/common/blocks/GT_Block_Machines.java b/src/main/java/gregtech/common/blocks/GT_Block_Machines.java index 2c9254bf28..ad97bb9572 100644 --- a/src/main/java/gregtech/common/blocks/GT_Block_Machines.java +++ b/src/main/java/gregtech/common/blocks/GT_Block_Machines.java @@ -1,5 +1,7 @@ package gregtech.common.blocks; +import com.cricketcraft.chisel.api.IFacade; +import cpw.mods.fml.common.Optional; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.GregTech_API; @@ -27,6 +29,7 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EnumCreatureType; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -47,7 +50,8 @@ import java.util.List; import static gregtech.GT_Mod.GT_FML_LOGGER; import static gregtech.api.objects.XSTR.XSTR_INSTANCE; -public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlock, ITileEntityProvider { +@Optional.Interface(iface = "com.cricketcraft.chisel.api.IFacade", modid = "ChiselAPI") +public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlock, ITileEntityProvider, IFacade { private static final ThreadLocal<IGregTechTileEntity> mTemporaryTileEntity = new ThreadLocal<>(); private boolean renderAsNormalBlock; @@ -648,4 +652,51 @@ public class GT_Block_Machines extends GT_Generic_Block implements IDebugableBlo } return false; } + + @Override + public Block getFacade(IBlockAccess aWorld, int aX, int aY, int aZ, int side) { + TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ); + if (tTileEntity instanceof IGregTechTileEntity) { + byte aSide = (byte) side; + IGregTechTileEntity tile = (IGregTechTileEntity) tTileEntity; + if (side != -1) { + Block facadeBlock = tile.getCoverBehaviorAtSideNew(aSide).getFacadeBlock(aSide, tile.getCoverIDAtSide(aSide), tile.getComplexCoverDataAtSide(aSide), tile); + if (facadeBlock != null) return facadeBlock; + } else { + // we do not allow more than one type of facade per block, so no need to check every side + // see comment in gregtech.common.covers.GT_Cover_FacadeBase.isCoverPlaceable + for (byte i = 0; i < 6; i++) { + Block facadeBlock = tile.getCoverBehaviorAtSideNew(i).getFacadeBlock(i, tile.getCoverIDAtSide(i), tile.getComplexCoverDataAtSide(i), tile); + if (facadeBlock != null) { + return facadeBlock; + } + } + } + } + return Blocks.air; + } + + @Override + public int getFacadeMetadata(IBlockAccess aWorld, int aX, int aY, int aZ, int side) { + TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ); + if (tTileEntity instanceof IGregTechTileEntity) { + byte aSide = (byte) side; + IGregTechTileEntity tile = (IGregTechTileEntity) tTileEntity; + if (side != -1) { + Block facadeBlock = tile.getCoverBehaviorAtSideNew(aSide).getFacadeBlock(aSide, tile.getCoverIDAtSide(aSide), tile.getComplexCoverDataAtSide(aSide), tile); + if (facadeBlock != null) + return tile.getCoverBehaviorAtSideNew(aSide).getFacadeMeta(aSide, tile.getCoverIDAtSide(aSide), tile.getComplexCoverDataAtSide(aSide), tile); + } else { + // we do not allow more than one type of facade per block, so no need to check every side + // see comment in gregtech.common.covers.GT_Cover_FacadeBase.isCoverPlaceable + for (byte i = 0; i < 6; i++) { + Block facadeBlock = tile.getCoverBehaviorAtSideNew(i).getFacadeBlock(i, tile.getCoverIDAtSide(i), tile.getComplexCoverDataAtSide(i), tile); + if (facadeBlock != null) { + return tile.getCoverBehaviorAtSideNew(i).getFacadeMeta(i, tile.getCoverIDAtSide(i), tile.getComplexCoverDataAtSide(i), tile); + } + } + } + } + return 0; + } } diff --git a/src/main/java/gregtech/common/blocks/GT_Item_Machines.java b/src/main/java/gregtech/common/blocks/GT_Item_Machines.java index bcc6d7e14c..73443006b2 100644 --- a/src/main/java/gregtech/common/blocks/GT_Item_Machines.java +++ b/src/main/java/gregtech/common/blocks/GT_Item_Machines.java @@ -6,15 +6,18 @@ import gregtech.api.enums.Materials; import gregtech.api.interfaces.metatileentity.IConnectable; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.metatileentity.CoverableGregTechTileEntity; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Cable; import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Fluid; import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Frame; import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Item; +import gregtech.api.util.GT_CoverBehaviorBase; import gregtech.api.util.GT_ItsNotMyFaultException; import gregtech.api.util.GT_LanguageManager; import gregtech.api.util.GT_Log; import gregtech.api.util.GT_Utility; +import gregtech.api.util.ISerializableObject; import gregtech.common.tileentities.storage.*; import net.minecraft.block.Block; import net.minecraft.entity.Entity; @@ -144,9 +147,14 @@ public class GT_Item_Machines extends ItemBlock implements IFluidContainerItem { if (mCoverSides != null && mCoverSides.length == 6) { for (byte i = 0; i < 6; i++) { int coverId = mCoverSides[i]; - ItemStack coverStack = GT_Utility.intToStack(coverId); - if (coverStack != null) { - aList.add(String.format("Cover on %s side: %s", directionNames[i], coverStack.getDisplayName())); + if (coverId == 0) continue; + GT_CoverBehaviorBase<?> behavior = GregTech_API.getCoverBehaviorNew(coverId); + if (behavior == null || behavior == GregTech_API.sNoBehavior) continue; + if (!aNBT.hasKey(CoverableGregTechTileEntity.COVER_DATA_NBT_KEYS[i])) continue; + ISerializableObject dataObject = behavior.createDataObject(aNBT.getTag(CoverableGregTechTileEntity.COVER_DATA_NBT_KEYS[i])); + ItemStack itemStack = behavior.getDisplayStack(coverId, dataObject); + if (itemStack != null) { + aList.add(String.format("Cover on %s side: %s", directionNames[i], itemStack.getDisplayName())); } } } diff --git a/src/main/java/gregtech/common/covers/GT_Cover_FacadeAE.java b/src/main/java/gregtech/common/covers/GT_Cover_FacadeAE.java new file mode 100644 index 0000000000..592b6f322d --- /dev/null +++ b/src/main/java/gregtech/common/covers/GT_Cover_FacadeAE.java @@ -0,0 +1,27 @@ +package gregtech.common.covers; + +import appeng.facade.IFacadeItem; +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class GT_Cover_FacadeAE extends GT_Cover_FacadeBase { + @Override + protected Block getTargetBlock(ItemStack aFacadeStack) { + Item item = aFacadeStack.getItem(); + if (!(item instanceof IFacadeItem)) return null; + return ((IFacadeItem) item).getBlock(aFacadeStack); + } + + @Override + protected int getTargetMeta(ItemStack aFacadeStack) { + Item item = aFacadeStack.getItem(); + if (!(item instanceof IFacadeItem)) return 0; + return ((IFacadeItem) item).getMeta(aFacadeStack); + } + + @Override + protected ItemStack getDisplayStackImpl(int aCoverID, FacadeData aCoverVariable) { + return aCoverVariable.mStack; + } +} diff --git a/src/main/java/gregtech/common/covers/GT_Cover_FacadeBase.java b/src/main/java/gregtech/common/covers/GT_Cover_FacadeBase.java new file mode 100644 index 0000000000..9f21b34c3f --- /dev/null +++ b/src/main/java/gregtech/common/covers/GT_Cover_FacadeBase.java @@ -0,0 +1,235 @@ +package gregtech.common.covers; + +import com.google.common.io.ByteArrayDataInput; +import cpw.mods.fml.common.network.ByteBufUtils; +import gregtech.api.GregTech_API; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.tileentity.ICoverable; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GT_CoverBehaviorBase; +import gregtech.api.util.GT_RenderingWorld; +import gregtech.api.util.GT_Utility; +import gregtech.api.util.ISerializableObject; +import io.netty.buffer.ByteBuf; +import net.minecraft.block.Block; +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.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.Fluid; + +import javax.annotation.Nonnull; + +public abstract class GT_Cover_FacadeBase extends GT_CoverBehaviorBase<GT_Cover_FacadeBase.FacadeData> { + /** + * This is the Dummy, if there is a generic Cover without behavior + */ + public GT_Cover_FacadeBase() { + super(FacadeData.class); + } + + @Override + public boolean isSimpleCover() { + return true; + } + + @Override + public FacadeData createDataObject(int aLegacyData) { + return new FacadeData(); + } + + @Override + public FacadeData createDataObject() { + return new FacadeData(); + } + + @Override + protected FacadeData onCoverScrewdriverClickImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + aCoverVariable.mFlags = ((aCoverVariable.mFlags + 1) & 15); + GT_Utility.sendChatToPlayer(aPlayer, ((aCoverVariable.mFlags & 1) != 0 ? trans("128", "Redstone ") : "") + ((aCoverVariable.mFlags & 2) != 0 ? trans("129", "Energy ") : "") + ((aCoverVariable.mFlags & 4) != 0 ? trans("130", "Fluids ") : "") + ((aCoverVariable.mFlags & 8) != 0 ? trans("131", "Items ") : "")); + return aCoverVariable; + } + + @Override + protected boolean letsRedstoneGoInImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) { + return (aCoverVariable.mFlags & 1) != 0; + } + + @Override + protected boolean letsRedstoneGoOutImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) { + return (aCoverVariable.mFlags & 1) != 0; + } + + @Override + protected boolean letsEnergyInImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) { + return (aCoverVariable.mFlags & 2) != 0; + } + + @Override + protected boolean letsEnergyOutImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) { + return (aCoverVariable.mFlags & 2) != 0; + } + + @Override + protected boolean letsFluidInImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + return (aCoverVariable.mFlags & 4) != 0; + } + + @Override + protected boolean letsFluidOutImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, Fluid aFluid, ICoverable aTileEntity) { + return (aCoverVariable.mFlags & 4) != 0; + } + + @Override + protected boolean letsItemsInImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, int aSlot, ICoverable aTileEntity) { + return (aCoverVariable.mFlags & 8) != 0; + } + + @Override + protected boolean letsItemsOutImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, int aSlot, ICoverable aTileEntity) { + return (aCoverVariable.mFlags & 8) != 0; + } + + @Override + public void placeCover(byte aSide, ItemStack aCover, ICoverable aTileEntity) { + aTileEntity.setCoverIDAtSide(aSide, GT_Utility.stackToInt(aCover)); + aTileEntity.setCoverDataAtSide(aSide, new FacadeData(GT_Utility.copyAmount(1, aCover), 0)); + if (aTileEntity.isClientSide()) + GT_RenderingWorld.getInstance().register(aTileEntity.getXCoord(), aTileEntity.getYCoord(), aTileEntity.getZCoord(), getTargetBlock(aCover), getTargetMeta(aCover)); + } + + @Override + protected ItemStack getDropImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) { + return aCoverVariable.mStack; + } + + @Override + protected ITexture getSpecialCoverTextureImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) { + if (GT_Utility.isStackInvalid(aCoverVariable.mStack)) return null; + Block block = getTargetBlock(aCoverVariable.mStack); + if (block == null) return null; + return TextureFactory.builder().setFromBlock(block, getTargetMeta(aCoverVariable.mStack)).useWorldCoord().setFromSide(ForgeDirection.getOrientation(aSide)).build(); + } + + @Override + protected Block getFacadeBlockImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) { + if (GT_Utility.isStackInvalid(aCoverVariable.mStack)) return null; + return getTargetBlock(aCoverVariable.mStack); + } + + @Override + protected int getFacadeMetaImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) { + if (GT_Utility.isStackInvalid(aCoverVariable.mStack)) return 0; + return getTargetMeta(aCoverVariable.mStack); + } + + protected abstract Block getTargetBlock(ItemStack aFacadeStack); + + protected abstract int getTargetMeta(ItemStack aFacadeStack); + + @Override + protected boolean isDataNeededOnClientImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) { + return true; + } + + @Override + protected void onDataChangedImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) { + if (aTileEntity.isClientSide()) + GT_RenderingWorld.getInstance().register(aTileEntity.getXCoord(), aTileEntity.getYCoord(), aTileEntity.getZCoord(), getTargetBlock(aCoverVariable.mStack), getTargetMeta(aCoverVariable.mStack)); + } + + @Override + protected void onDroppedImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity) { + if (aTileEntity.isClientSide()) { + for (byte i = 0; i < 6; i++) { + if (i == aSide) continue; + // since we do not allow multiple type of facade per block, this check would be enough. + if (aTileEntity.getCoverBehaviorAtSideNew(i) instanceof GT_Cover_FacadeBase) return; + } + if (aCoverVariable.mStack != null) + // mStack == null -> cover removed before data reach client + GT_RenderingWorld.getInstance().unregister(aTileEntity.getXCoord(), aTileEntity.getYCoord(), aTileEntity.getZCoord(), getTargetBlock(aCoverVariable.mStack), getTargetMeta(aCoverVariable.mStack)); + } + } + + @Override + protected boolean onCoverRightClickImpl(byte aSide, int aCoverID, FacadeData aCoverVariable, ICoverable aTileEntity, EntityPlayer aPlayer, float aX, float aY, float aZ) { + // in case cover data didn't hit client somehow. maybe he had a ridiculous view distance + aTileEntity.issueCoverUpdate(aSide); + return super.onCoverRightClickImpl(aSide, aCoverID, aCoverVariable, aTileEntity, aPlayer, aX, aY, aZ); + } + + @Override + public boolean isCoverPlaceable(byte aSide, ItemStack aStack, ICoverable aTileEntity) { + // blocks that are not rendered in pass 0 are rejected for now. + // to implement it require changing GT_Block_Machine to render in both pass, which is not really a good idea... + if (!super.isCoverPlaceable(aSide, aStack, aTileEntity)) return false; + Block targetBlock = getTargetBlock(aStack); + if (targetBlock == null) return false; + if (targetBlock.getRenderBlockPass() != GregTech_API.sBlockMachines.getRenderBlockPass()) return false; + // we allow one single type of facade on the same block for now + // otherwise it's not clear which block this block should impersonate + // this restriction can be lifted later by specifying a certain facade as dominate one as an extension to this class + for (byte i = 0; i < 6; i++) { + if (i == aSide) continue; + GT_CoverBehaviorBase<?> behavior = aTileEntity.getCoverBehaviorAtSideNew(i); + if (behavior == null) continue; + Block facadeBlock = behavior.getFacadeBlock(i, aTileEntity.getCoverIDAtSide(i), aTileEntity.getComplexCoverDataAtSide(i), aTileEntity); + if (facadeBlock == null) continue; + if (facadeBlock != targetBlock) return false; + if (behavior.getFacadeMeta(i, aTileEntity.getCoverIDAtSide(i), aTileEntity.getComplexCoverDataAtSide(i), aTileEntity) != getTargetMeta(aStack)) return false; + } + return true; + } + + public static class FacadeData implements ISerializableObject { + ItemStack mStack; + int mFlags; + + public FacadeData() { + } + + public FacadeData(ItemStack mStack, int mFlags) { + this.mStack = mStack; + this.mFlags = mFlags; + } + + @Nonnull + @Override + public ISerializableObject copy() { + return new FacadeData(mStack, mFlags); + } + + @Nonnull + @Override + public NBTBase saveDataToNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setTag("mStack", mStack.writeToNBT(new NBTTagCompound())); + tag.setByte("mFlags", (byte) mFlags); + return tag; + } + + @Override + public void writeToByteBuf(ByteBuf aBuf) { + ByteBufUtils.writeItemStack(aBuf, mStack); + aBuf.writeByte(mFlags); + } + + @Override + public void loadDataFromNBT(NBTBase aNBT) { + NBTTagCompound tag = (NBTTagCompound) aNBT; + mStack = ItemStack.loadItemStackFromNBT(tag.getCompoundTag("mStack")); + mFlags = tag.getByte("mFlags"); + } + + @Nonnull + @Override + public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) { + mStack = ISerializableObject.readItemStackFromGreggyByteBuf(aBuf); + mFlags = aBuf.readByte(); + return this; + } + } +} diff --git a/src/main/java/gregtech/common/render/GT_CopiedCTMBlockTexture.java b/src/main/java/gregtech/common/render/GT_CopiedCTMBlockTexture.java new file mode 100644 index 0000000000..fc83e4b687 --- /dev/null +++ b/src/main/java/gregtech/common/render/GT_CopiedCTMBlockTexture.java @@ -0,0 +1,128 @@ +package gregtech.common.render; + +import gregtech.api.interfaces.IBlockContainer; +import gregtech.api.interfaces.ITexture; +import gregtech.api.util.GT_RenderingWorld; +import gregtech.api.util.LightingHelper; +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.util.IIcon; +import net.minecraftforge.common.util.ForgeDirection; + +class GT_CopiedCTMBlockTexture implements ITexture, IBlockContainer { + private final Block mBlock; + private final byte mSide, mMeta; + + GT_CopiedCTMBlockTexture(Block aBlock, int aSide, int aMeta, short[] aRGBa, boolean allowAlpha) { + if (aRGBa.length != 4) throw new IllegalArgumentException("RGBa doesn't have 4 Values @ GT_CopiedCTMBlockTexture"); + mBlock = aBlock; + mSide = (byte) aSide; + mMeta = (byte) aMeta; + } + + private IIcon getIcon(int aSide, int aX, int aY, int aZ, RenderBlocks aRenderer) { + int tSide = mSide == 6 ? aSide : mSide; + return mBlock.getIcon(getBlockAccess(aRenderer), aX, aY, aZ, tSide); + } + + private GT_RenderingWorld getBlockAccess(RenderBlocks aRenderer) { + return GT_RenderingWorld.getInstance(aRenderer.blockAccess); + } + + @Override + public void renderXPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) { + IIcon aIcon = getIcon(ForgeDirection.EAST.ordinal(), aX, aY, aZ, aRenderer); + aRenderer.field_152631_f = true; + // TODO: Uncomment this once all addons have migrated to the new Texture API + //startDrawingQuads(aRenderer, 1.0f, 0.0f, 0.0f); + new LightingHelper(aRenderer) + .setupLightingXPos(aBlock, aX, aY, aZ) + .setupColor(ForgeDirection.EAST.ordinal(), mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ)); + aRenderer.renderFaceXPos(aBlock, aX, aY, aZ, aIcon); + // TODO: Uncomment this once all addons have migrated to the new Texture API + //draw(aRenderer); + aRenderer.field_152631_f = false; + } + + @Override + public void renderXNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) { + // TODO: Uncomment this once all addons have migrated to the new Texture API + //startDrawingQuads(aRenderer, -1.0f, 0.0f, 0.0f); + IIcon aIcon = getIcon(ForgeDirection.WEST.ordinal(), aX, aY, aZ, aRenderer); + new LightingHelper(aRenderer) + .setupLightingXNeg(aBlock, aX, aY, aZ) + .setupColor(ForgeDirection.WEST.ordinal(), mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ)); + aRenderer.renderFaceXNeg(aBlock, aX, aY, aZ, aIcon); + // TODO: Uncomment this once all addons have migrated to the new Texture API + //draw(aRenderer); + } + + @Override + public void renderYPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) { + // TODO: Uncomment this once all addons have migrated to the new Texture API + //startDrawingQuads(aRenderer, 0.0f, 1.0f, 0.0f); + IIcon aIcon = getIcon(ForgeDirection.UP.ordinal(), aX, aY, aZ, aRenderer); + new LightingHelper(aRenderer) + .setupLightingYPos(aBlock, aX, aY, aZ) + .setupColor(ForgeDirection.UP.ordinal(), mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ)); + aRenderer.renderFaceYPos(aBlock, aX, aY, aZ, aIcon); + // TODO: Uncomment this once all addons have migrated to the new Texture API + //draw(aRenderer); + } + + @Override + public void renderYNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) { + // TODO: Uncomment this once all addons have migrated to the new Texture API + //startDrawingQuads(aRenderer, 0.0f, -1.0f, 0.0f); + IIcon aIcon = getIcon(ForgeDirection.DOWN.ordinal(), aX, aY, aZ, aRenderer); + new LightingHelper(aRenderer) + .setupLightingYNeg(aBlock, aX, aY, aZ) + .setupColor(ForgeDirection.DOWN.ordinal(), mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ)); + aRenderer.renderFaceYNeg(aBlock, aX, aY, aZ, aIcon); + // TODO: Uncomment this once all addons have migrated to the new Texture API + //draw(aRenderer); + } + + @Override + public void renderZPos(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) { + // TODO: Uncomment this once all addons have migrated to the new Texture API + //startDrawingQuads(aRenderer, 0.0f, 0.0f, 1.0f); + IIcon aIcon = getIcon(ForgeDirection.SOUTH.ordinal(), aX, aY, aZ, aRenderer); + new LightingHelper(aRenderer) + .setupLightingZPos(aBlock, aX, aY, aZ) + .setupColor(ForgeDirection.SOUTH.ordinal(), mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ)); + aRenderer.renderFaceZPos(aBlock, aX, aY, aZ, aIcon); + // TODO: Uncomment this once all addons have migrated to the new Texture API + //draw(aRenderer); + } + + @Override + public void renderZNeg(RenderBlocks aRenderer, Block aBlock, int aX, int aY, int aZ) { + // TODO: Uncomment this once all addons have migrated to the new Texture API + //startDrawingQuads(aRenderer, 0.0f, 0.0f, -1.0f); + IIcon aIcon = getIcon(ForgeDirection.NORTH.ordinal(), aX, aY, aZ, aRenderer); + aRenderer.field_152631_f = true; + new LightingHelper(aRenderer) + .setupLightingZNeg(aBlock, aX, aY, aZ) + .setupColor(ForgeDirection.NORTH.ordinal(), mBlock.colorMultiplier(getBlockAccess(aRenderer), aX, aY, aZ)); + aRenderer.renderFaceZNeg(aBlock, aX, aY, aZ, aIcon); + // TODO: Uncomment this once all addons have migrated to the new Texture API + //draw(aRenderer); + aRenderer.field_152631_f = false; + } + + @Override + public boolean isValidTexture() { + return mBlock != null; + } + + @Override + public Block getBlock() { + return mBlock; + } + + @Override + public byte getMeta() { + return mMeta; + } +} diff --git a/src/main/java/gregtech/common/render/GT_TextureBuilder.java b/src/main/java/gregtech/common/render/GT_TextureBuilder.java index 82bce4c8c4..f79e438dd7 100644 --- a/src/main/java/gregtech/common/render/GT_TextureBuilder.java +++ b/src/main/java/gregtech/common/render/GT_TextureBuilder.java @@ -1,6 +1,8 @@ package gregtech.common.render; +import gregtech.GT_Mod; import gregtech.api.enums.Dyes; +import gregtech.api.enums.GT_Values; import gregtech.api.interfaces.IIconContainer; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.ITextureBuilder; @@ -23,6 +25,7 @@ public class GT_TextureBuilder implements ITextureBuilder { private boolean stdOrient; private boolean extFacing; private boolean glow; + private Boolean worldCoord = null; public GT_TextureBuilder() { textureLayers = new ArrayList<>(); @@ -78,6 +81,20 @@ public class GT_TextureBuilder implements ITextureBuilder { } @Override + public ITextureBuilder useWorldCoord() { + if (fromBlock == null) throw new IllegalStateException("no from block"); + this.worldCoord = true; + return this; + } + + @Override + public ITextureBuilder noWorldCoord() { + if (fromBlock == null) throw new IllegalStateException("no from block"); + this.worldCoord = false; + return this; + } + + @Override public ITextureBuilder extFacing() { this.extFacing = true; return this; @@ -91,7 +108,12 @@ public class GT_TextureBuilder implements ITextureBuilder { @Override public ITexture build() { - if (fromBlock != null) return new GT_CopiedBlockTexture(fromBlock, fromSide.ordinal(), fromMeta, rgba, allowAlpha); + if (fromBlock != null) { + if (worldCoord == Boolean.TRUE || worldCoord == null && isCTMBlock(fromBlock, fromMeta)) + return new GT_CopiedCTMBlockTexture(fromBlock, fromSide.ordinal(), fromMeta, rgba, allowAlpha); + else + return new GT_CopiedBlockTexture(fromBlock, fromSide.ordinal(), fromMeta, rgba, allowAlpha); + } if (!textureLayers.isEmpty()) return new GT_MultiTexture(textureLayers.toArray(new ITexture[0])); switch (iconContainerList.size()) { case 1: @@ -109,4 +131,19 @@ public class GT_TextureBuilder implements ITextureBuilder { throw new IllegalStateException("Invalid sideIconContainer count"); } } + + private boolean isCTMBlock(Block fromBlock, int fromMeta) { + return GT_Mod.gregtechproxy.mCTMBlockCache.computeIfAbsent(fromBlock, (byte) fromMeta, GT_TextureBuilder::apply); + } + + private static Boolean apply(Block b, Byte m) { + Class<?> clazz = b.getClass(); + while (clazz != Block.class) { + String className = clazz.getName(); + if (GT_Values.mCTMDisabledBlock.contains(className)) return false; + if (GT_Values.mCTMEnabledBlock.contains(className)) return true; + clazz = clazz.getSuperclass(); + } + return false; + } } diff --git a/src/main/java/gregtech/loaders/preload/GT_PreLoad.java b/src/main/java/gregtech/loaders/preload/GT_PreLoad.java index 165ff3e435..e3d4178d97 100644 --- a/src/main/java/gregtech/loaders/preload/GT_PreLoad.java +++ b/src/main/java/gregtech/loaders/preload/GT_PreLoad.java @@ -511,6 +511,9 @@ public class GT_PreLoad { tPrefix.mDefaultStackSize = ((byte) Math.min(64, Math.max(16, tMainConfig.get("features", "MaxOtherBlockStackSize", 64).getInt()))); } } + + GT_Values.mCTMEnabledBlock.addAll(Arrays.asList(tMainConfig.get("general", "ctm_block_whitelist", new String[]{"team.chisel.block.BlockCarvable", "team.chisel.block.BlockCarvableGlass"}).getStringList())); + GT_Values.mCTMDisabledBlock.addAll(Arrays.asList(tMainConfig.get("general", "ctm_block_blacklist", new String[]{"team.chisel.block.BlockRoadLine"}).getStringList())); } public static void loadClientConfig() { |