aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gtPlusPlus/xmod/gregtech/api/objects
diff options
context:
space:
mode:
authorJohann Bernhardt <johann.bernhardt@tum.de>2021-12-12 19:38:06 +0100
committerJohann Bernhardt <johann.bernhardt@tum.de>2021-12-12 19:38:06 +0100
commit311ab89f93558233a40079f7cb16605b141b5346 (patch)
treec5f44ef47f441a57c5f57aa801f639c7879ed760 /src/main/java/gtPlusPlus/xmod/gregtech/api/objects
parent896143b96132f5ac54aa8d8f7386f27487e5e530 (diff)
downloadGT5-Unofficial-311ab89f93558233a40079f7cb16605b141b5346.tar.gz
GT5-Unofficial-311ab89f93558233a40079f7cb16605b141b5346.tar.bz2
GT5-Unofficial-311ab89f93558233a40079f7cb16605b141b5346.zip
Move sources and resources
Diffstat (limited to 'src/main/java/gtPlusPlus/xmod/gregtech/api/objects')
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechFluid.java28
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechItemData.java144
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechMaterialStack.java49
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockBlueprint.java469
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockLayer.java643
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockRequirements.java108
6 files changed, 1441 insertions, 0 deletions
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechFluid.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechFluid.java
new file mode 100644
index 0000000000..9cc0e3a315
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechFluid.java
@@ -0,0 +1,28 @@
+package gtPlusPlus.xmod.gregtech.api.objects;
+
+import gregtech.api.GregTech_API;
+
+import gtPlusPlus.core.lib.CORE;
+import net.minecraftforge.fluids.Fluid;
+
+public class GregtechFluid extends Fluid implements Runnable {
+ public final String mTextureName;
+ private final short[] mRGBa;
+
+ public GregtechFluid(final String aName, final String aTextureName, final short[] aRGBa) {
+ super(aName);
+ this.mRGBa = aRGBa;
+ this.mTextureName = aTextureName;
+ GregTech_API.sGTBlockIconload.add(this);
+ }
+
+ @Override
+ public int getColor() {
+ return (Math.max(0, Math.min(255, this.mRGBa[0])) << 16) | (Math.max(0, Math.min(255, this.mRGBa[1])) << 8) | Math.max(0, Math.min(255, this.mRGBa[2]));
+ }
+
+ @Override
+ public void run() {
+ this.setIcons(GregTech_API.sBlockIcons.registerIcon(CORE.MODID+ ":" + "fluids/fluid." + this.mTextureName));
+ }
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechItemData.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechItemData.java
new file mode 100644
index 0000000000..eb5939caca
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechItemData.java
@@ -0,0 +1,144 @@
+package gtPlusPlus.xmod.gregtech.api.objects;
+
+import java.util.*;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.objects.GT_ArrayList;
+
+import gtPlusPlus.xmod.gregtech.api.enums.GregtechOrePrefixes;
+import gtPlusPlus.xmod.gregtech.api.enums.GregtechOrePrefixes.GT_Materials;
+
+public class GregtechItemData {
+ private static final GregtechMaterialStack[] EMPTY_GT_MaterialStack_ARRAY = new GregtechMaterialStack[0];
+
+ public final List<Object> mExtraData = new GT_ArrayList<>(false, 1);
+ public final GregtechOrePrefixes mPrefix;
+ public final GregtechMaterialStack mMaterial;
+ public final GregtechMaterialStack[] mByProducts;
+ public boolean mBlackListed = false;
+ public ItemStack mUnificationTarget = null;
+
+ public GregtechItemData(final GregtechOrePrefixes aPrefix, final GT_Materials aMaterial, final boolean aBlackListed) {
+ this.mPrefix = aPrefix;
+ this.mMaterial = aMaterial == null ? null : new GregtechMaterialStack(aMaterial, aPrefix.mMaterialAmount);
+ this.mBlackListed = aBlackListed;
+ this.mByProducts = (aPrefix.mSecondaryMaterial == null) || (aPrefix.mSecondaryMaterial.mMaterial == null) ? EMPTY_GT_MaterialStack_ARRAY : new GregtechMaterialStack[]{aPrefix.mSecondaryMaterial.clone()};
+ }
+
+ public GregtechItemData(final GregtechOrePrefixes aPrefix, final GT_Materials aMaterial) {
+ this(aPrefix, aMaterial, false);
+ }
+
+ public GregtechItemData(final GregtechMaterialStack aMaterial, final GregtechMaterialStack... aByProducts) {
+ this.mPrefix = null;
+ this.mMaterial = aMaterial.mMaterial == null ? null : aMaterial.clone();
+ this.mBlackListed = true;
+ if (aByProducts == null) {
+ this.mByProducts = EMPTY_GT_MaterialStack_ARRAY;
+ } else {
+ final GregtechMaterialStack[] tByProducts = aByProducts.length < 1 ? EMPTY_GT_MaterialStack_ARRAY : new GregtechMaterialStack[aByProducts.length];
+ int j = 0;
+ for (int i = 0; i < aByProducts.length; i++) {
+ if ((aByProducts[i] != null) && (aByProducts[i].mMaterial != null)) {
+ tByProducts[j++] = aByProducts[i].clone();
+ }
+ }
+ this.mByProducts = j > 0 ? new GregtechMaterialStack[j] : EMPTY_GT_MaterialStack_ARRAY;
+ for (int i = 0; i < this.mByProducts.length; i++) {
+ this.mByProducts[i] = tByProducts[i];
+ }
+ }
+ }
+
+ public GregtechItemData(final GT_Materials aMaterial, final long aAmount, final GregtechMaterialStack... aByProducts) {
+ this(new GregtechMaterialStack(aMaterial, aAmount), aByProducts);
+ }
+
+ public GregtechItemData(final GT_Materials aMaterial, final long aAmount, final GT_Materials aByProduct, final long aByProductAmount) {
+ this(new GregtechMaterialStack(aMaterial, aAmount), new GregtechMaterialStack(aByProduct, aByProductAmount));
+ }
+
+ public GregtechItemData(final GregtechItemData... aData) {
+ this.mPrefix = null;
+ this.mBlackListed = true;
+
+ final ArrayList<GregtechMaterialStack> aList = new ArrayList<>(), rList = new ArrayList<>();
+
+ for (final GregtechItemData tData : aData) {
+ if (tData != null) {
+ if (tData.hasValidMaterialData() && (tData.mMaterial.mAmount > 0)) {
+ aList.add(tData.mMaterial.clone());
+ }
+ for (final GregtechMaterialStack tMaterial : tData.mByProducts) {
+ if (tMaterial.mAmount > 0) {
+ aList.add(tMaterial.clone());
+ }
+ }
+ }
+ }
+
+ for (final GregtechMaterialStack aMaterial : aList) {
+ boolean temp = true;
+ for (final GregtechMaterialStack tMaterial : rList) {
+ if (aMaterial.mMaterial == tMaterial.mMaterial) {
+ tMaterial.mAmount += aMaterial.mAmount;
+ temp = false;
+ break;
+ }
+ }
+ if (temp) {
+ rList.add(aMaterial.clone());
+ }
+ }
+
+ Collections.sort(rList, new Comparator<GregtechMaterialStack>() {
+ @Override
+ public int compare(final GregtechMaterialStack a, final GregtechMaterialStack b) {
+ return a.mAmount == b.mAmount ? 0 : a.mAmount > b.mAmount ? -1 : +1;
+ }
+ });
+
+ if (rList.isEmpty()) {
+ this.mMaterial = null;
+ } else {
+ this.mMaterial = rList.get(0);
+ rList.remove(0);
+ }
+
+ this.mByProducts = rList.toArray(new GregtechMaterialStack[rList.size()]);
+ }
+
+ public boolean hasValidPrefixMaterialData() {
+ return (this.mPrefix != null) && (this.mMaterial != null) && (this.mMaterial.mMaterial != null);
+ }
+
+ public boolean hasValidPrefixData() {
+ return this.mPrefix != null;
+ }
+
+ public boolean hasValidMaterialData() {
+ return (this.mMaterial != null) && (this.mMaterial.mMaterial != null);
+ }
+
+ public ArrayList<GregtechMaterialStack> getAllGT_MaterialStacks() {
+ final ArrayList<GregtechMaterialStack> rList = new ArrayList<GregtechMaterialStack>();
+ if (this.hasValidMaterialData()) {
+ rList.add(this.mMaterial);
+ }
+ rList.addAll(Arrays.asList(this.mByProducts));
+ return rList;
+ }
+
+ public GregtechMaterialStack getByProduct(final int aIndex) {
+ return (aIndex >= 0) && (aIndex < this.mByProducts.length) ? this.mByProducts[aIndex] : null;
+ }
+
+ @Override
+ public String toString() {
+ if ((this.mPrefix == null) || (this.mMaterial == null) || (this.mMaterial.mMaterial == null)) {
+ return "";
+ }
+ return this.mPrefix.name() + this.mMaterial.mMaterial.name();
+ }
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechMaterialStack.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechMaterialStack.java
new file mode 100644
index 0000000000..6ec5907256
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/GregtechMaterialStack.java
@@ -0,0 +1,49 @@
+package gtPlusPlus.xmod.gregtech.api.objects;
+
+import gtPlusPlus.xmod.gregtech.api.enums.GregtechOrePrefixes.GT_Materials;
+
+public class GregtechMaterialStack implements Cloneable {
+ public long mAmount;
+ public GT_Materials mMaterial;
+
+ public GregtechMaterialStack(final GT_Materials aMaterial, final long aAmount) {
+ this.mMaterial = aMaterial == null ? GT_Materials._NULL : aMaterial;
+ this.mAmount = aAmount;
+ }
+
+ public GregtechMaterialStack copy(final long aAmount) {
+ return new GregtechMaterialStack(this.mMaterial, aAmount);
+ }
+
+ @Override
+ public GregtechMaterialStack clone() {
+ return new GregtechMaterialStack(this.mMaterial, this.mAmount);
+ }
+
+ @Override
+ public boolean equals(final Object aObject) {
+ if (aObject == this) {
+ return true;
+ }
+ if (aObject == null) {
+ return false;
+ }
+ if (aObject instanceof GT_Materials) {
+ return aObject == this.mMaterial;
+ }
+ if (aObject instanceof GregtechMaterialStack) {
+ return (((GregtechMaterialStack) aObject).mMaterial == this.mMaterial) && ((this.mAmount < 0) || (((GregtechMaterialStack) aObject).mAmount < 0) || (((GregtechMaterialStack) aObject).mAmount == this.mAmount));
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return ((this.mMaterial.mMaterialList.size() > 1) && (this.mAmount > 1) ? "(" : "") + this.mMaterial.getToolTip(true) + ((this.mMaterial.mMaterialList.size() > 1) && (this.mAmount > 1) ? ")" : "") + (this.mAmount > 1 ? this.mAmount : "");
+ }
+
+ @Override
+ public int hashCode() {
+ return this.mMaterial.hashCode();
+ }
+} \ No newline at end of file
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockBlueprint.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockBlueprint.java
new file mode 100644
index 0000000000..7af6af2ffd
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockBlueprint.java
@@ -0,0 +1,469 @@
+package gtPlusPlus.xmod.gregtech.api.objects;
+
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.api.objects.data.Pair;
+import gtPlusPlus.api.objects.data.Triplet;
+import gtPlusPlus.api.objects.minecraft.BlockPos;
+import gtPlusPlus.xmod.gregtech.api.objects.MultiblockLayer.LayerBlockData;
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraftforge.common.util.ForgeDirection;
+
+public abstract class MultiblockBlueprint {
+
+ private final MultiblockLayer[] mBlueprintData;
+
+ public final int height;
+ public final int width;
+ public final int depth;
+ public final int mMinimumCasingCount;
+ public final int mTextureID;
+
+ /**
+ * Cached Matrix of the Multiblock, which makes future structural checks far quicker.
+ */
+ private final BlockPos[][][] StructureMatrix;
+
+ /**
+ * Has {@value StructureMatrix} been set yet?
+ */
+ @SuppressWarnings("unused")
+ private boolean mGeneratedMatrix = false;
+
+ /**
+ * A detailed class which will contain blueprints for a Multiblock.
+ * Values are not relative to the controller, but in total.
+ * @param x - Overall width
+ * @param y - Overall height
+ * @param z - Overall depth
+ * @param aMinimumCasings - The lowest amount of casings required
+ * @param aTextureID - The texture ID used by hatches.
+ */
+ public MultiblockBlueprint(final int x, final int y, final int z, final int aMinimumCasings, final int aTextureID) {
+ mBlueprintData = new MultiblockLayer[y];
+ height = y;
+ width = x;
+ depth = z;
+ mMinimumCasingCount = aMinimumCasings;
+ mTextureID = aTextureID;
+ StructureMatrix = new BlockPos[width][height][depth];
+ //Logger.INFO("Created new Blueprint.");
+ }
+
+ /**
+ *
+ * @param aY - The Y level of the layer to return, where 0 is the bottom and N is the top.
+ * @return - A {@link MultiblockLayer} object.
+ */
+ public MultiblockLayer getLayer(int aY) {
+ return mBlueprintData[aY];
+ }
+
+ /**
+ *
+ * @param aLayer - A {@link MultiblockLayer} object.
+ * @param aY - The Y level of the layer, where 0 is the bottom and N is the top.
+ *
+ */
+ public void setLayer(MultiblockLayer aLayer, int aY) {
+ mBlueprintData[aY] = aLayer;
+ }
+
+ public MultiblockLayer getControllerLayer() {
+ for (MultiblockLayer u : mBlueprintData) {
+ if (u.hasController()) {
+ return u;
+ }
+ }
+ return null;
+ }
+
+ public int getControllerY() {
+ int i = 0;
+ for (MultiblockLayer u : mBlueprintData) {
+ if (u.hasController()) {
+ return i;
+ }
+ i++;
+ }
+ return 0;
+ }
+
+ @SuppressWarnings({ "unused", "rawtypes" })
+ public boolean checkMachine(final IGregTechTileEntity aBaseMetaTileEntity) {
+ //Check for Nulls
+ if (aBaseMetaTileEntity == null) {
+ return false;
+ }
+ final IMetaTileEntity aMetaTileEntity = aBaseMetaTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) {
+ return false;
+ }
+ GT_MetaTileEntity_MultiBlockBase aControllerObject = null;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_MultiBlockBase) {
+ aControllerObject = (GT_MetaTileEntity_MultiBlockBase) aMetaTileEntity;
+ }
+ if (aControllerObject == null) {
+ return false;
+ }
+
+ //Get some Vars
+ int xOffSetMulti = ((this.getControllerLayer().width-1)/2);
+ int zOffSetMulti = ((this.getControllerLayer().depth-1)/2);
+ final int xDir = ForgeDirection.getOrientation(aBaseMetaTileEntity.getBackFacing()).offsetX * xOffSetMulti;
+ final int zDir = ForgeDirection.getOrientation(aBaseMetaTileEntity.getBackFacing()).offsetZ * zOffSetMulti;
+ ForgeDirection aDir = ForgeDirection.getOrientation(aBaseMetaTileEntity.getBackFacing());
+ int tAmount = 0;
+
+ int contX = aControllerObject.getBaseMetaTileEntity().getXCoord(), contY = aControllerObject.getBaseMetaTileEntity().getYCoord(), contZ = aControllerObject.getBaseMetaTileEntity().getZCoord();
+
+ Logger.INFO("Controller is located at ["+contX+", "+contY+", "+contZ+"]");
+
+ boolean debugCacheDataVisually = true;
+
+
+ if (/*!mGeneratedMatrix || StructureMatrix == null*/ true) {
+ //Try Fancy Cache Stuff
+ BlockPos aPos = getOffsetRelativeToGridPosition(aBaseMetaTileEntity, 0, 0, 0);
+ for (int Y = 0; Y < height; Y++) {
+ for (int Z = 0; Z < depth; Z++) {
+ for (int X = 0; X < width; X++) {
+ int offsetX, offsetZ;
+ Pair<Integer, Integer> j = MultiblockLayer.rotateOffsetValues(aDir, X, Z);
+ offsetX = j.getKey();
+ offsetZ = j.getValue();
+
+ Logger.INFO("Pre-Rotated Offsets ["+X+", "+(aPos.yPos + Y)+", "+Z+"] | "+aDir.name());
+ Logger.INFO("Rotated Offsets ["+offsetX+", "+(aPos.yPos + Y)+", "+offsetZ+"]");
+
+ // Resolve Negatives
+ int negTestX, negTestZ;
+ if (aPos.xPos < 0) {
+ int testA = aPos.xPos;
+ testA -= -offsetX;
+ negTestX = testA;
+ } else {
+ negTestX = offsetX + aPos.xPos;
+ }
+ if (aPos.zPos < 0) {
+ int testA = aPos.zPos;
+ testA -= -offsetZ;
+ negTestZ = testA;
+ } else {
+ negTestZ = offsetZ + aPos.zPos;
+ }
+ Logger.INFO("Caching With Offset ["+negTestX+", "+(aPos.yPos + Y)+", "+negTestZ+"]");
+ StructureMatrix[X][Y][Z] = new BlockPos(negTestX, (aPos.yPos + Y), negTestZ, aPos.world);
+
+ if (debugCacheDataVisually) {
+ aBaseMetaTileEntity.getWorld().setBlock(negTestX, (aPos.yPos + Y), negTestZ, Blocks.glass);
+ }
+ }
+ }
+ }
+ Logger.INFO("Cached blueprint matrix.");
+ mGeneratedMatrix = true;
+ }
+ else {
+ Logger.INFO("Found cached blueprint matrix.");
+ }
+
+ if (StructureMatrix == null) {
+ Logger.INFO("Error caching blueprint matrix.");
+ return false;
+ }
+
+
+ int a1, a2, a3;
+ a1 = StructureMatrix.length;
+ a2 = StructureMatrix[0].length;
+ a3 = StructureMatrix[0][0].length;
+
+ Logger.INFO("Matrix Size ["+a1+", "+a2+", "+a3+"]");
+
+ for (int H = 0; H < a2; H++) {
+
+ MultiblockLayer currentLayer = this.getLayer(H);
+ for (int W = 0; W < a1; W++) {
+ for (int D = 0; D < a3; D++) {
+
+ BlockPos aToCheck = StructureMatrix[W][H][D];
+ if (aToCheck == null) {
+ Logger.INFO("Found bad data stored at X: "+W+", Y: "+H+", Z: "+D);
+ continue;
+ }
+ else {
+ //Logger.INFO("Found data stored at X: "+W+", Y: "+H+", Z: "+D);
+ Logger.INFO("Checking "+aToCheck.getLocationString());
+ }
+
+ final IGregTechTileEntity tTileEntity = aBaseMetaTileEntity.getIGregTechTileEntity(aToCheck.xPos, aToCheck.yPos, aToCheck.zPos);
+ final Block tBlock = aBaseMetaTileEntity.getBlock(aToCheck.xPos, aToCheck.yPos, aToCheck.zPos);
+ final int tMeta = aBaseMetaTileEntity.getMetaID(aToCheck.xPos, aToCheck.yPos, aToCheck.zPos);
+
+
+ LayerBlockData g1 = currentLayer.getDataFromCoordsWithDirection(aDir, W, D);
+ if (g1 == null) {
+ Logger.INFO("Failed to find LayerBlockData. Using AIR_FALLBACK");
+ //return false;*/
+ g1 = LayerBlockData.FALLBACK_AIR_CHECK;
+ }
+ else {
+ if (g1.isController) {
+ Logger.INFO("Controller is at X: "+W+", Y: "+H+", Z: "+D);
+ }
+ }
+
+ boolean isMatch = g1.match(tBlock, tMeta);
+
+
+ if (!isMatch) {
+ Logger.INFO("Checking ["+aToCheck.xPos+", "+ aToCheck.yPos +", "+ aToCheck.zPos+"]");
+ Logger.INFO("Checking Position relative to Grid. X: "+W+", Y: "+H+", Z: "+D);
+ Logger.INFO("Found "+tBlock.getLocalizedName()+" : "+tMeta + " | Bad ["+W+", "+D+"]");
+
+ LayerBlockData g = currentLayer.getDataFromCoordsWithDirection(aDir, W, D);
+
+ if (g == null) {
+ Logger.INFO("Expected "+" BAD DATA - Possibly Unset Area in Blueprint.");
+
+ }
+ else {
+ Logger.INFO("Expected "+g.mBlock.getLocalizedName()+" : "+g.mMeta + "");
+ }
+ aBaseMetaTileEntity.getWorld().setBlock(aToCheck.xPos, aToCheck.yPos, aToCheck.zPos, g.mBlock);
+ aBaseMetaTileEntity.getWorld().setBlockMetadataWithNotify(aToCheck.xPos, aToCheck.yPos, aToCheck.zPos, g.mMeta, 4);
+ //return false;
+ }
+ else {
+
+ LayerBlockData g = currentLayer.getDataFromCoordsWithDirection(aDir, W, D);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ boolean isHatchValidType = false;
+ if (g != null) {
+ if (g.canBeHatch && !g.isController && tTileEntity != null) {
+ IMetaTileEntity aMetaTileEntity2 = tTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity2 != null) {
+ if (aMetaTileEntity2 instanceof GT_MetaTileEntity_MultiBlockBase) {
+ isHatchValidType = true;
+ break;
+ }
+ else {
+ for (Class c : g.mHatchClass) {
+ if (c != null) {
+ if (c.isInstance(aMetaTileEntity2)) {
+ isHatchValidType = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!isHatchValidType && !g.isController && tTileEntity != null) {
+ Logger.INFO("Checking ["+aToCheck.xPos+", "+ aToCheck.yPos +", "+ aToCheck.zPos+"]");
+ Logger.INFO("Hatch Type did not match allowed types. "+tTileEntity.getClass().getSimpleName());
+ return false;
+ }
+ if (!aControllerObject.addToMachineList(tTileEntity, mTextureID)) {
+ tAmount++;
+ }
+
+
+ }
+ }
+ }
+ }
+
+ boolean hasCorrectHatches = (
+ aControllerObject.mInputBusses.size() >= this.getMinimumInputBus() &&
+ aControllerObject.mOutputBusses.size() >= this.getMinimumOutputBus() &&
+ aControllerObject.mInputHatches.size() >= this.getMinimumInputHatch() &&
+ aControllerObject.mOutputHatches.size() >= this.getMinimumOutputHatch() &&
+ aControllerObject.mDynamoHatches.size() >= this.getMinimumOutputEnergy() &&
+ aControllerObject.mEnergyHatches.size() >= this.getMinimumInputEnergy() &&
+ aControllerObject.mMaintenanceHatches.size() >= this.getMinimumMaintHatch() &&
+ aControllerObject.mMufflerHatches.size() >= this.getMinimumMufflers());
+
+
+ Logger.INFO("mInputBusses: "+aControllerObject.mInputBusses.size());
+ Logger.INFO("mOutputBusses: "+aControllerObject.mOutputBusses.size());
+ Logger.INFO("mInputHatches: "+aControllerObject.mInputHatches.size());
+ Logger.INFO("mOutputHatches: "+aControllerObject.mOutputHatches.size());
+ Logger.INFO("mEnergyHatches: "+aControllerObject.mEnergyHatches.size());
+ Logger.INFO("mDynamoHatches: "+aControllerObject.mDynamoHatches.size());
+ Logger.INFO("mMaintenanceHatches: "+aControllerObject.mMaintenanceHatches.size());
+ Logger.INFO("mMufflerHatches: "+aControllerObject.mMufflerHatches.size());
+
+ boolean built = hasCorrectHatches && tAmount >= mMinimumCasingCount;
+ Logger.INFO("Built? "+built);
+ Logger.INFO("hasCorrectHatches? "+hasCorrectHatches);
+ Logger.INFO("tAmount? "+tAmount);
+ return built;
+ }
+
+ public BlockPos getOffsetRelativeToGridPosition(final IGregTechTileEntity aBaseMetaTileEntity, final int x, final int y, final int z) {
+
+ if (aBaseMetaTileEntity == null) {
+ return null;
+ }
+
+ int controllerX, controllerY, controllerZ;
+ MultiblockLayer layerController = this.getControllerLayer();
+
+ if (layerController == null) {
+ return null;
+ }
+
+ int controllerYRelative = this.getControllerY();
+ Pair<Integer, Integer> controllerLocationRelativeToGrid = layerController.getControllerLocation();
+
+ if (controllerLocationRelativeToGrid == null) {
+ return null;
+ }
+
+ controllerX = aBaseMetaTileEntity.getXCoord();
+ controllerY = aBaseMetaTileEntity.getYCoord();
+ controllerZ = aBaseMetaTileEntity.getZCoord();
+
+ Logger.INFO("Controller is at ["+controllerX+", "+controllerY+", "+controllerZ+"]");
+
+ ForgeDirection aDir = ForgeDirection.getOrientation(aBaseMetaTileEntity.getBackFacing());
+ Logger.INFO("Controller is facing "+aDir.name());
+
+ //Find Bottom Left corner of Structure
+ // 0, 0, 0
+
+ int offsetX, offsetY, offsetZ;
+ int X = controllerLocationRelativeToGrid.getKey(), Z = controllerLocationRelativeToGrid.getValue();
+ Logger.INFO("Attempting to translate offsets ["+X+", "+Z+"]");
+ if (aDir == ForgeDirection.NORTH) {
+ offsetX = -X;
+ offsetZ = -Z;
+ }
+
+ else if (aDir == ForgeDirection.EAST) {
+ offsetX = Z;
+ offsetZ = -X;
+ }
+
+ else if (aDir == ForgeDirection.SOUTH) {
+ offsetX = X;
+ offsetZ = Z;
+ }
+
+ else if (aDir == ForgeDirection.WEST) {
+ offsetX = -Z;
+ offsetZ = X;
+ }
+ else {
+ offsetX = -X;
+ offsetZ = -Z;
+ }
+
+ offsetY = -controllerYRelative;
+
+ Logger.INFO("Attempting to use offsets ["+offsetX+", "+offsetY+", "+offsetZ+"]");
+
+ //Resolve Negatives
+ int negTestX, negTestZ;
+ if (controllerX < 0) {
+ Logger.INFO("Found Negative X Pos.");
+ int testA = controllerX;
+ testA -= offsetX;
+ Logger.INFO("Adding Inverted Offset of "+offsetX+", making "+testA);
+ negTestX = testA;
+ }
+ else {
+ negTestX = offsetX + controllerX;
+ }
+ if (controllerZ < 0) {
+ Logger.INFO("Found Negative Z Pos.");
+ int testA = controllerZ;
+ testA -= -offsetZ;
+ Logger.INFO("Adding Inverted Offset of "+offsetZ+", making "+testA);
+ negTestZ = testA;
+ }
+ else {
+ negTestZ = offsetZ + controllerZ;
+ }
+
+
+ //}
+ //Bottom left Corner position
+ BlockPos p = new BlockPos(negTestX, offsetY+controllerY, negTestZ, aBaseMetaTileEntity.getWorld());
+
+ Logger.INFO("World XYZ for Bottom left Corner Block of structure ["+p.xPos+", "+p.yPos+", "+p.zPos+"]");
+
+ //Add the xyz relative to the grid.
+ BlockPos offsetPos = new BlockPos(p.xPos+x, p.yPos+y, p.zPos+z, aBaseMetaTileEntity.getWorld());
+ Logger.INFO("World XYZ for Target Check Block in structure ["+offsetPos.xPos+", "+offsetPos.yPos+", "+offsetPos.zPos+"]");
+
+ return p;
+ }
+
+
+ public IGregTechTileEntity getTileAtOffset(final IGregTechTileEntity aBaseMetaTileEntity, int x, int y, int z){
+ BlockPos aPos = getOffsetRelativeToGridPosition(aBaseMetaTileEntity, x, y, z);
+ final IGregTechTileEntity tTileEntity = aBaseMetaTileEntity.getIGregTechTileEntityOffset(aPos.xPos, aPos.yPos, aPos.zPos);
+ //aBaseMetaTileEntity.getWorld().setBlock(xh, yh, zh, Blocks.gold_ore);
+ return tTileEntity;
+ }
+
+ public Pair<Block, Integer> getBlockAtOffset(final IGregTechTileEntity aBaseMetaTileEntity, int x, int y, int z){
+ BlockPos aPos = getOffsetRelativeToGridPosition(aBaseMetaTileEntity, x, y, z);
+ final Block tBlock = aBaseMetaTileEntity.getBlockOffset(aPos.xPos, aPos.yPos, aPos.zPos);
+ final int tMeta = aBaseMetaTileEntity.getMetaIDOffset(aPos.xPos, aPos.yPos, aPos.zPos);
+ return new Pair<Block, Integer>(tBlock, tMeta);
+ }
+
+ public Triplet<Integer, Integer, Integer> getOffsetFromControllerTo00(){
+ MultiblockLayer l = this.getControllerLayer();
+ if (l == null) {
+ return null;
+ }
+ int yOffset = this.getControllerY();
+ Pair<Integer, Integer> cl = l.getControllerLocation();
+
+ if (cl == null) {
+ return null;
+ }
+
+ return new Triplet<Integer, Integer, Integer> (cl.getKey(), yOffset, cl.getValue());
+ //return new Triplet<Integer, Integer, Integer> (cl.getKey(), yOffset, cl.getValue());
+
+ }
+
+ public abstract int getMinimumInputBus();
+ public abstract int getMinimumInputHatch();
+ public abstract int getMinimumOutputBus();
+ public abstract int getMinimumOutputHatch();
+ public abstract int getMinimumInputEnergy();
+ public abstract int getMinimumOutputEnergy();
+ public abstract int getMinimumMaintHatch();
+ public abstract int getMinimumMufflers();
+
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockLayer.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockLayer.java
new file mode 100644
index 0000000000..c5554a6679
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockLayer.java
@@ -0,0 +1,643 @@
+package gtPlusPlus.xmod.gregtech.api.objects;
+
+import java.util.HashMap;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Maintenance;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_OutputBus;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.api.objects.data.Pair;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.reflect.ReflectionUtils;
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockAir;
+import net.minecraft.init.Blocks;
+import net.minecraftforge.common.util.ForgeDirection;
+
+public class MultiblockLayer {
+
+ public final int width;
+ public final int depth;
+
+ private boolean mFinalised;
+
+
+ /**
+ * WARNING!! May be {@link null}.
+ */
+ private Pair<Integer, Integer> mControllerLocation;
+
+ /**
+ * Holds the North facing Orientation data.
+ */
+ public final LayerBlockData[][] mLayerData;
+ public final AutoMap<LayerBlockData[][]> mVariantOrientations = new AutoMap<LayerBlockData[][]>();
+
+ /**
+ * A detailed class which will contain a single x/z Layer for a {@link MultiblockBlueprint}.
+ * Values are not relative, but in total.
+ * @param x - Overall width
+ * @param z - Overall depth
+ */
+ public MultiblockLayer(final int x, final int z) {
+ width = x;
+ depth = z;
+ mLayerData = new LayerBlockData[x][z];
+ //Logger.INFO("Created new Blueprint Layer.");
+ }
+
+ /**
+ * A detailed class which will contain a single x/z Layer for a {@link MultiblockBlueprint}.
+ * Values are not relative, but in total.
+ */
+ public MultiblockLayer(final LayerBlockData[][] aData) {
+ width = aData.length;
+ depth = aData[0].length;
+ mLayerData = aData;
+ }
+
+ /**
+ *
+ * @param aBlock - The block expected as this location.
+ * @param aMeta - The meta for the block above.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @param canBeHatch - is this location able to be substituted for any hatch?
+ * @return - Is this data added to the layer data map?
+ */
+ public boolean addBlockForPos(Block aBlock, int aMeta, int x, int z, boolean canBeHatch) {
+ return addBlockForPos(aBlock, aMeta, x, z, canBeHatch, new Class[] {});
+ }
+
+ /**
+ *
+ * @param aBlock - The block expected as this location.
+ * @param aMeta - The meta for the block above.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @param canBeHatch - is this location able to be substituted for a hatch?
+ * @param aHatchTypeClass - Specify the class for the hatch if you want it explicit. Use base classes to allow custom hatches which extend.
+ * @return - Is this data added to the layer data map?
+ */
+ public boolean addBlockForPos(Block aBlock, int aMeta, int x, int z, boolean canBeHatch, Class aHatchTypeClass) {
+ return addBlockForPos(aBlock, aMeta, x, z, canBeHatch, new Class[] {aHatchTypeClass});
+ }
+
+ /**
+ *
+ * @param aBlock - The block expected as this location.
+ * @param aMeta - The meta for the block above.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @param canBeHatch - is this location able to be substituted for a hatch?
+ * @param aHatchTypeClass - Specify the class for the hatch if you want it explicit. Use base classes to allow custom hatches which extend.
+ * @return - Is this data added to the layer data map?
+ */
+ public boolean addBlockForPos(Block aBlock, int aMeta, int x, int z, boolean canBeHatch, Class[] aHatchTypeClass) {
+ if (x > width -1) {
+ return false;
+ }
+ if (z > depth - 1) {
+ return false;
+ }
+
+ if (canBeHatch && (aHatchTypeClass == null || aHatchTypeClass.length <= 0)){
+
+ if (!CORE.MAIN_GREGTECH_5U_EXPERIMENTAL_FORK) {
+ aHatchTypeClass = new Class[] {
+ GT_MetaTileEntity_Hatch_Dynamo.class,
+ GT_MetaTileEntity_Hatch_Energy.class,
+ GT_MetaTileEntity_Hatch_Input.class,
+ GT_MetaTileEntity_Hatch_InputBus.class,
+ GT_MetaTileEntity_Hatch_Maintenance.class,
+ GT_MetaTileEntity_Hatch_Muffler.class,
+ GT_MetaTileEntity_Hatch_Output.class,
+ GT_MetaTileEntity_Hatch_OutputBus.class,
+ GT_MetaTileEntity_Hatch.class
+ };
+ }
+ else {
+ Class aDataHatch = ReflectionUtils.getClass("gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_DataAccess");
+ if (aDataHatch != null) {
+ aHatchTypeClass = new Class[] {
+ aDataHatch,
+ GT_MetaTileEntity_Hatch_Dynamo.class,
+ GT_MetaTileEntity_Hatch_Energy.class,
+ GT_MetaTileEntity_Hatch_Input.class,
+ GT_MetaTileEntity_Hatch_InputBus.class,
+ GT_MetaTileEntity_Hatch_Maintenance.class,
+ GT_MetaTileEntity_Hatch_Muffler.class,
+ GT_MetaTileEntity_Hatch_Output.class,
+ GT_MetaTileEntity_Hatch_OutputBus.class,
+ GT_MetaTileEntity_Hatch.class
+ };
+ } else {
+ aHatchTypeClass = new Class[] {
+ GT_MetaTileEntity_Hatch_Dynamo.class,
+ GT_MetaTileEntity_Hatch_Energy.class,
+ GT_MetaTileEntity_Hatch_Input.class,
+ GT_MetaTileEntity_Hatch_InputBus.class,
+ GT_MetaTileEntity_Hatch_Maintenance.class,
+ GT_MetaTileEntity_Hatch_Muffler.class,
+ GT_MetaTileEntity_Hatch_Output.class,
+ GT_MetaTileEntity_Hatch_OutputBus.class,
+ GT_MetaTileEntity_Hatch.class
+ };
+ }
+ }
+ }
+
+
+
+ mLayerData[x][z] = new LayerBlockData(aBlock, aMeta, canBeHatch, aHatchTypeClass);
+ return true;
+ }
+
+ /**
+ * Adds a controller to the layer at the designated location, Details about the controller do not need to be specified.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @return - Is this controller added to the layer data map?
+ */
+ public boolean addController(int x, int z) {
+ setControllerLocation(new Pair<Integer, Integer>(x, z));
+ return addBlockForPos(GregTech_API.sBlockMachines, 0, x, z, true, GT_MetaTileEntity_MultiBlockBase.class);
+ }
+
+
+ /**
+ * Adds a Muffler to the layer at the designated location.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @return - Is this controller added to the layer data map?
+ */
+ public boolean addMuffler(Block aBlock, int aMeta, int x, int z) {
+ return addBlockForPos(aBlock, aMeta, x, z, true, GT_MetaTileEntity_Hatch_Muffler.class);
+ }
+
+
+ /**
+ * Adds a Maint Hatch to the layer at the designated location.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @return - Is this controller added to the layer data map?
+ */
+ public boolean addMaintHatch(Block aBlock, int aMeta, int x, int z) {
+ return addBlockForPos(aBlock, aMeta, x, z, true, GT_MetaTileEntity_Hatch_Maintenance.class);
+ }
+
+
+ /**
+ * Adds ah Input to the layer at the designated location.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @return - Is this controller added to the layer data map?
+ */
+ public boolean addInputBus(Block aBlock, int aMeta, int x, int z) {
+ return addBlockForPos(aBlock, aMeta, x, z, true, GT_MetaTileEntity_Hatch_InputBus.class);
+ }
+
+
+ /**
+ * Adds an Output to the layer at the designated location.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @return - Is this controller added to the layer data map?
+ */
+ public boolean addOutputBus(Block aBlock, int aMeta, int x, int z) {
+ return addBlockForPos(aBlock, aMeta, x, z, true, GT_MetaTileEntity_Hatch_OutputBus.class);
+ }
+
+ /**
+ * Adds ah Input to the layer at the designated location.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @return - Is this controller added to the layer data map?
+ */
+ public boolean addInputHatch(Block aBlock, int aMeta, int x, int z) {
+ return addBlockForPos(aBlock, aMeta, x, z, true, GT_MetaTileEntity_Hatch_Input.class);
+ }
+
+
+ /**
+ * Adds an Output to the layer at the designated location.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @return - Is this controller added to the layer data map?
+ */
+ public boolean addOutputHatch(Block aBlock, int aMeta, int x, int z) {
+ return addBlockForPos(aBlock, aMeta, x, z, true, GT_MetaTileEntity_Hatch_Output.class);
+ }
+
+ /**
+ * Adds ah Input to the layer at the designated location.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @return - Is this controller added to the layer data map?
+ */
+ public boolean addInput(Block aBlock, int aMeta, int x, int z) {
+ return addBlockForPos(aBlock, aMeta, x, z, true, new Class[] {GT_MetaTileEntity_Hatch_Input.class, GT_MetaTileEntity_Hatch_InputBus.class});
+ }
+
+
+ /**
+ * Adds an Output to the layer at the designated location.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @return - Is this controller added to the layer data map?
+ */
+ public boolean addOutput(Block aBlock, int aMeta, int x, int z) {
+ return addBlockForPos(aBlock, aMeta, x, z, true, new Class[] {GT_MetaTileEntity_Hatch_Output.class, GT_MetaTileEntity_Hatch_OutputBus.class});
+ }
+
+ /**
+ * Adds ah Input to the layer at the designated location.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @return - Is this controller added to the layer data map?
+ */
+ public boolean addEnergyInput(Block aBlock, int aMeta, int x, int z) {
+ return addBlockForPos(aBlock, aMeta, x, z, true, GT_MetaTileEntity_Hatch_Energy.class);
+ }
+
+
+ /**
+ * Adds an Output to the layer at the designated location.
+ * @param x - The X location, where 0 is the top left corner & counts upwards, moving right.
+ * @param z - The Z location, where 0 is the top left corner & counts upwards, moving down.
+ * @return - Is this controller added to the layer data map?
+ */
+ public boolean addEnergyOutput(Block aBlock, int aMeta, int x, int z) {
+ return addBlockForPos(aBlock, aMeta, x, z, true, GT_MetaTileEntity_Hatch_Dynamo.class);
+ }
+
+ /**
+ *
+ * @param aBlock - The block you expect.
+ * @param aMeta - The meta you expect.
+ * @param x - the non-relative x location you expect it.
+ * @param z - the non-relative z location you expect it.
+ * @param aDir - The direction the controller is facing.
+ * @return - True if the correct Block was found. May also return true if a hatch is found when allowed or it's the controller.
+ */
+ public boolean getBlockForPos(Block aBlock, int aMeta, int x, int z, ForgeDirection aDir) {
+ //Logger.INFO("Grid Index X: "+x+" | Z: "+z + " | "+aDir.name());
+ LayerBlockData g;
+ if (aDir == ForgeDirection.SOUTH) {
+ g = mVariantOrientations.get(2)[x][z];
+ }
+ else if (aDir == ForgeDirection.WEST) {
+ g = mVariantOrientations.get(3)[x][z];
+ }
+ else if (aDir == ForgeDirection.NORTH) {
+ LayerBlockData[][] aData = mVariantOrientations.get(0);
+ if (aData != null) {
+ //Logger.INFO("Found Valid Orientation Data. "+aData.length + ", "+aData[0].length);
+ g = aData[x][z];
+ }
+ else {
+ //Logger.INFO("Did not find valid orientation data.");
+ g = null;
+ }
+ }
+ else if (aDir == ForgeDirection.EAST) {
+ g = mVariantOrientations.get(1)[x][z];
+ }
+ else {
+ g = mLayerData[x][z];
+ }
+ if (g == null) {
+ Logger.INFO("Failed to find LayerBlockData. Using AIR_FALLBACK");
+ //return false;*/
+ g = LayerBlockData.FALLBACK_AIR_CHECK;
+ }
+
+ return g.match(aBlock, aMeta);
+ }
+
+
+
+ /**
+ * Is this layer final?
+ * @return - If true, layer data cannot be edited.
+ */
+ public final boolean isLocked() {
+ return mFinalised;
+ }
+
+ /**
+ * Used to finalize the layer, after which all four Orientations are then generated.
+ * Cannot be set to false, useful for not locking the layer if an error occurs.
+ * @param lockData
+ */
+ public final void lock(boolean lockData) {
+ if (!lockData) {
+ Logger.INFO("Failed to lock layer");
+ return;
+ }
+ //Logger.INFO("Trying to lock layer");
+ this.mFinalised = true;
+ generateOrientations();
+ //Logger.INFO("Trying to Build Blueprint Layer [Constructed orietations & finalized]");
+ }
+
+ private void generateOrientations() {
+ try {
+
+ //Logger.INFO("Trying to gen orients for layer");
+ //North
+ mVariantOrientations.put(mLayerData);
+ LayerBlockData[][] val;
+ //Logger.INFO("1 done");
+ //East
+ val = rotateArrayClockwise(mLayerData);
+ mVariantOrientations.put((LayerBlockData[][]) val);
+ //Logger.INFO("2 done");
+ //South
+ val = rotateArrayClockwise(mLayerData);
+ mVariantOrientations.put((LayerBlockData[][]) val);
+ //Logger.INFO("3 done");
+ //West
+ val = rotateArrayClockwise(mLayerData);
+ mVariantOrientations.put((LayerBlockData[][]) val);
+ //Logger.INFO("4 done");
+
+ }
+ catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ public static LayerBlockData[][] rotateArrayClockwise(LayerBlockData[][] mat) {
+ //Logger.INFO("Rotating Layer 90' Clockwise");
+ try {
+ final int M = mat.length;
+ final int N = mat[0].length;
+ //Logger.INFO("Dimension X: "+M);
+ //Logger.INFO("Dimension Z: "+N);
+ LayerBlockData[][] ret = new LayerBlockData[N][M];
+ for (int r = 0; r < M; r++) {
+ for (int c = 0; c < N; c++) {
+ ret[c][M-1-r] = mat[r][c];
+ }
+ }
+ //Logger.INFO("Returning Rotated Layer");
+ return ret;
+ }
+ catch (Throwable t) {
+ t.printStackTrace();
+ return null;
+ }
+ }
+
+ public boolean hasController() {
+ if (getControllerLocation() == null) {
+ return false;
+ }
+ return true;
+ }
+
+ public Pair<Integer, Integer> getControllerLocation() {
+ return mControllerLocation;
+ }
+
+ public void setControllerLocation(Pair<Integer, Integer> mControllerLocation) {
+ if (hasController()) {
+ return;
+ }
+ this.mControllerLocation = mControllerLocation;
+ }
+
+ public LayerBlockData getDataFromCoordsWithDirection(ForgeDirection aDir, int W, int D) {
+ LayerBlockData g;
+ if (aDir == ForgeDirection.SOUTH) {
+ g = this.mVariantOrientations.get(2)[W][D];
+ }
+ else if (aDir == ForgeDirection.WEST) {
+ g = this.mVariantOrientations.get(3)[W][D];
+ }
+ else if (aDir == ForgeDirection.NORTH) {
+ g = this.mVariantOrientations.get(0)[W][D];
+ }
+ else if (aDir == ForgeDirection.EAST) {
+ g = this.mVariantOrientations.get(1)[W][D];
+ }
+ else {
+ g = this.mLayerData[W][D];
+ }
+ return g;
+ }
+
+ public static Pair<Integer, Integer> rotateOffsetValues(ForgeDirection aDir, int X, int Z) {
+ int offsetX, offsetZ;
+
+ if (aDir == ForgeDirection.NORTH) {
+ offsetX = X;
+ offsetZ = Z;
+ }
+
+ else if (aDir == ForgeDirection.EAST) {
+ offsetX = -X;
+ offsetZ = Z;
+ }
+
+ else if (aDir == ForgeDirection.SOUTH) {
+ offsetX = -X;
+ offsetZ = -Z;
+ }
+
+ else if (aDir == ForgeDirection.WEST) {
+ offsetX = X;
+ offsetZ = -Z;
+ }
+ else {
+ offsetX = X;
+ offsetZ = Z;
+ }
+
+ return new Pair<Integer, Integer>(offsetX, offsetZ);
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /**
+ * Generates a complete {@link MultiblockLayer} from String data.
+ * @param aDataMap - A {@link HashMap} containing single character {@link String}s, which map to {@link Pair}<{@link Block}, {@link Integer}>s contains pairs of Blocks & Meta.
+ * @param aHorizontalStringRows - The horizontal rows used to map blocks to a grid. Each array slot is one vertical row going downwards as the index increases.
+ * @return
+ */
+ public static MultiblockLayer generateLayerFromData(HashMap<String, Pair<Block, Integer>> aDataMap, String[] aHorizontalStringRows) {
+ AutoMap<Pair<String, Pair<Block, Integer>>> x = new AutoMap<Pair<String, Pair<Block, Integer>>>();
+
+ for (String u : aDataMap.keySet()) {
+ Pair<Block, Integer> r = aDataMap.get(u);
+ if (r != null) {
+ x.put(new Pair<String, Pair<Block, Integer>>(u, r));
+ }
+ }
+
+ //String aFreeLetters = "abdefgijklmnopqrstuvwxyz";
+ /*for (Pair<Block, Integer> h : aDataMap.values()) {
+ String y = aFreeLetters.substring(0, 0);
+ aFreeLetters = aFreeLetters.replace(y.toLowerCase(), "");
+ Pair<String, Pair<Block, Integer>> t = new Pair<String, Pair<Block, Integer>>(y, h);
+ x.put(t);
+ }*/
+ return generateLayerFromData(x, aHorizontalStringRows);
+ }
+
+
+ /**
+ * Generates a complete {@link MultiblockLayer} from String data.
+ * @param aDataMap - An {@link AutoMap} which contains {@link Pair}s. These Pairs hold a single character {@link String} and another Pair. This inner pair holds a {@link Block} and an {@link Integer}.
+ * @param aHorizontalStringRows - An array which holds the horizontal (X/Width) string data for the layer.
+ * @return A complete Multiblock Layer.
+ */
+ public static MultiblockLayer generateLayerFromData(AutoMap<Pair<String, Pair<Block, Integer>>> aDataMap, String[] aHorizontalStringRows) {
+ int width = aHorizontalStringRows[0].length();
+ int depth = aHorizontalStringRows.length;
+ MultiblockLayer L = new MultiblockLayer(width, depth);
+ HashMap<String, Pair<Block, Integer>> K = new HashMap<String, Pair<Block, Integer>>();
+
+ //24 Free Letters
+ //C = Controller
+ //H = Hatch
+ String aFreeLetters = "abdefgijklmnopqrstuvwxyz";
+ AutoMap<Pair<String, Pair<Block, Integer>>> j = new AutoMap<Pair<String, Pair<Block, Integer>>>();
+
+ //Map the keys to a Hashmap
+ for (Pair<String, Pair<Block, Integer>> t : aDataMap) {
+ String aKeyTemp = t.getKey();
+ if (aKeyTemp.toUpperCase().equals("C")){
+ j.put(t);
+ }
+ else if (aKeyTemp.toUpperCase().equals("H")){
+ j.put(t);
+ }
+ else {
+ K.put(aKeyTemp.toLowerCase(), t.getValue());
+ aFreeLetters.replace(aKeyTemp.toLowerCase(), "");
+ }
+ }
+
+ //Map any Invalid Characters to new ones, in case someone uses C/H.
+ if (j.size() > 0) {
+ for (Pair<String, Pair<Block, Integer>> h : j) {
+ String newKey = aFreeLetters.substring(0, 0);
+ K.put(newKey.toLowerCase(), h.getValue());
+ aFreeLetters.replace(newKey.toLowerCase(), "");
+ }
+ }
+
+ int xPos = 0;
+ int zPos = 0;
+
+ //Vertical Iterator
+ for (String s : aHorizontalStringRows) {
+ //Horizontal Iterator
+ for (int q = 0; q < s.length(); q++) {
+ //Get char as a String at index q.
+ String c = s.substring(q, q);
+ //if the character at c matches the character in this row, we add it to the map.
+ if (c.toLowerCase().equals(s.toLowerCase())) {
+ Pair<Block, Integer> p = K.get(c);
+ if (c.toLowerCase().equals("c")) {
+ L.addController(xPos, zPos);
+ }
+ else if (c.toLowerCase().equals("h")) {
+ L.addBlockForPos(p.getKey(), p.getValue(), xPos, zPos, true);
+ }
+ else {
+ L.addBlockForPos(p.getKey(), p.getValue(), xPos, zPos, false);
+ }
+ }
+ xPos++;
+ }
+ xPos = 0;
+ zPos++;
+ }
+ L.lock(true);
+ return L;
+ }
+
+
+
+
+ public static class LayerBlockData{
+
+ public static final LayerBlockData FALLBACK_AIR_CHECK = new LayerBlockData(Blocks.air, 0, false);
+
+ public final Block mBlock;
+ public final int mMeta;
+ public final boolean canBeHatch;
+ public final Class[] mHatchClass;
+
+ public final boolean isController;
+
+
+ public LayerBlockData(Block aBlock, int aMeta, boolean aHatch) {
+ this(aBlock, aMeta, aHatch, new Class[] {});
+ }
+
+ public LayerBlockData(Block aBlock, int aMeta, boolean aHatch, Class clazz) {
+ this(aBlock, aMeta, aHatch, new Class[] {clazz});
+ }
+
+ public LayerBlockData(Block aBlock, int aMeta, boolean aHatch, Class[] clazz) {
+ mBlock = aBlock;
+ mMeta = aMeta;
+ canBeHatch = aHatch;
+ mHatchClass = clazz;
+ if (clazz != null && clazz.length > 0 && clazz[0].equals(GT_MetaTileEntity_MultiBlockBase.class)) {
+ isController = true;
+ }
+ else {
+ isController = false;
+ }
+ }
+
+ public boolean match(Block blockToTest, int metaToTest) {
+
+ //If Both are some kind of Air Block, good enough.
+ if (blockToTest instanceof BlockAir && mBlock instanceof BlockAir) {
+ return true;
+ }
+
+ if (isController && blockToTest == GregTech_API.sBlockMachines) {
+ return true;
+ }
+
+ if (canBeHatch && blockToTest == GregTech_API.sBlockMachines) {
+ return true;
+ }
+
+ if (blockToTest == mBlock && metaToTest == mMeta) {
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockRequirements.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockRequirements.java
new file mode 100644
index 0000000000..10909081d1
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/objects/MultiblockRequirements.java
@@ -0,0 +1,108 @@
+package gtPlusPlus.xmod.gregtech.api.objects;
+
+public class MultiblockRequirements {
+
+ public int mInputBusMinimum = 0;
+ public int mInputHatchMinimum = 0;
+
+ public int mOutputBusMinimum = 0;
+ public int mOutputHatchMinimum = 0;
+
+ public int mMaintMinimum = 1;
+
+ public int mEnergyHatchMinimum = 1;
+ public int mDynamoHatchMinimum = 0;
+
+ public final int mMinimumCasingCount;
+
+ public final MultiblockBlueprint mBlueprint;
+
+ //public static final int mControlCoreMinimum = 1;
+ /**
+ *
+ * @param aInputBusses
+ * @param aOutputBusses
+ * @param aInputHatches
+ * @param aOutputHatches
+ * @param aEnergyHatches
+ * @param aDynamoHatches
+ * @param aMaintHatches
+ * @param aBlueprint - A data object containing the structural data for this Multiblock
+ */
+ public MultiblockRequirements(int aCasingCount, MultiblockBlueprint aBlueprint) {
+ mMinimumCasingCount = aCasingCount;
+ mBlueprint = aBlueprint;
+ }
+
+ public final int getInputBusMinimum() {
+ return this.mInputBusMinimum;
+ }
+
+ public final MultiblockRequirements setInputBusMinimum(int mInputBusMinimum) {
+ this.mInputBusMinimum = mInputBusMinimum;
+ return this;
+ }
+
+ public final int getInputHatchMinimum() {
+ return this.mInputHatchMinimum;
+ }
+
+ public final MultiblockRequirements setInputHatchMinimum(int mInputHatchMinimum) {
+ this.mInputHatchMinimum = mInputHatchMinimum;
+ return this;
+ }
+
+ public final int getOutputBusMinimum() {
+ return this.mOutputBusMinimum;
+ }
+
+ public final MultiblockRequirements setOutputBusMinimum(int mOutputBusMinimum) {
+ this.mOutputBusMinimum = mOutputBusMinimum;
+ return this;
+ }
+
+ public final int getOutputHatchMinimum() {
+ return this.mOutputHatchMinimum;
+ }
+
+ public final MultiblockRequirements setOutputHatchMinimum(int mOutputHatchMinimum) {
+ this.mOutputHatchMinimum = mOutputHatchMinimum;
+ return this;
+ }
+
+ public final int getMaintMinimum() {
+ return this.mMaintMinimum;
+ }
+
+ public final MultiblockRequirements setMaintMinimum(int mMaintMinimum) {
+ this.mMaintMinimum = mMaintMinimum;
+ return this;
+ }
+
+ public final int getEnergyHatchMinimum() {
+ return this.mEnergyHatchMinimum;
+ }
+
+ public final MultiblockRequirements setEnergyHatchMinimum(int mEnergyHatchMinimum) {
+ this.mEnergyHatchMinimum = mEnergyHatchMinimum;
+ return this;
+ }
+
+ public final int getDynamoHatchMinimum() {
+ return this.mDynamoHatchMinimum;
+ }
+
+ public final MultiblockRequirements setDynamoHatchMinimum(int mDynamoHatchMinimum) {
+ this.mDynamoHatchMinimum = mDynamoHatchMinimum;
+ return this;
+ }
+
+ public final MultiblockBlueprint getBlueprint() {
+ return this.mBlueprint;
+ }
+
+ public final int getMinimumCasingCount() {
+ return this.mMinimumCasingCount;
+ }
+
+}