diff options
author | iouter <62897714+iouter@users.noreply.github.com> | 2022-01-07 12:36:06 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-07 12:36:06 +0800 |
commit | 0834d4b8b45a881f36ed5b295ac0fb38df49fa9a (patch) | |
tree | 6fb4a45cf17dd22748148417bc7bb0efb850cea3 /src/main/java/gtPlusPlus/api/objects/minecraft | |
parent | ea1439a4195c8f77c45625ea2593a232bf19984e (diff) | |
parent | 9b2e050151ad93170e84321d067d1e9d4ded4ba5 (diff) | |
download | GT5-Unofficial-0834d4b8b45a881f36ed5b295ac0fb38df49fa9a.tar.gz GT5-Unofficial-0834d4b8b45a881f36ed5b295ac0fb38df49fa9a.tar.bz2 GT5-Unofficial-0834d4b8b45a881f36ed5b295ac0fb38df49fa9a.zip |
Merge branch 'GTNewHorizons:master' into master
Diffstat (limited to 'src/main/java/gtPlusPlus/api/objects/minecraft')
22 files changed, 2190 insertions, 0 deletions
diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/AABB.java b/src/main/java/gtPlusPlus/api/objects/minecraft/AABB.java new file mode 100644 index 0000000000..722ac00b64 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/AABB.java @@ -0,0 +1,65 @@ +package gtPlusPlus.api.objects.minecraft; + +import gtPlusPlus.core.util.minecraft.EntityUtils; +import net.minecraft.entity.Entity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.world.World; + +/** + * Generates an AABB around an entity. + * @author Alkalus + * + */ +public class AABB { + + private final AxisAlignedBB mAabb; + private final World mWorld; + + /** + * Creates a AxisAlignedBB based around an Entity. + * @param aEntity - The Entity to work with. + * @param x - Maximum X from origin. + * @param y - Maximum Y from origin. + * @param z - Maximum Z from origin. + */ + public AABB(Entity aEntity, int x, int y, int z) { + if (aEntity == null) { + mAabb = null; + mWorld = null; + } + else { + mWorld = aEntity.worldObj; + BlockPos aEntityLocation = EntityUtils.findBlockPosUnderEntity(aEntity); + int xMin, xMax, yMin, yMax, zMin, zMax; + xMin = aEntityLocation.xPos; + yMin = aEntityLocation.yPos; + zMin = aEntityLocation.zPos; + xMax = aEntityLocation.xPos + x; + yMax = aEntityLocation.yPos + y; + zMax = aEntityLocation.zPos + z; + mAabb = AxisAlignedBB.getBoundingBox(xMin, yMin, zMin, xMax, yMax, zMax); + } + + } + + /** + * Used to get the AxisAlignedBB from this class. + * @return + */ + public AxisAlignedBB get() { + return mAabb; + } + + /** + * Used to determine if this object is valid or not. + * @return + */ + public boolean valid() { + return mAabb != null && mWorld != null; + } + + public World world() { + return mWorld; + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_FluidTank.java b/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_FluidTank.java new file mode 100644 index 0000000000..0b8f97b378 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_FluidTank.java @@ -0,0 +1,188 @@ +package gtPlusPlus.api.objects.minecraft; + +import gtPlusPlus.core.util.minecraft.FluidUtils; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fluids.FluidTankInfo; + +public class BTF_FluidTank extends FluidTank { + + public FluidStack mFluid; + + public BTF_FluidTank(int capacity) { + super(capacity); + } + + /** + * Let's replace the Default handling with GT's own handling code, because it's probably better, right? + * @author Alkalus/GregoriusT + */ + + + public FluidStack getFluid() { + return this.getDrainableStack(); + } + + public int getFluidAmount() { + return this.getDrainableStack() != null ? this.getDrainableStack().amount : 0; + } + + public NBTTagCompound writeToNBT(NBTTagCompound aNBT) { + super.writeToNBT(aNBT); + if (this.mFluid != null) { + aNBT.setTag("mFluid", this.mFluid.writeToNBT(new NBTTagCompound())); + } + return aNBT; + } + + public FluidTank readFromNBT(NBTTagCompound aNBT) { + this.mFluid = FluidStack.loadFluidStackFromNBT(aNBT.getCompoundTag("mFluid")); + return this; + } + +/* public abstract boolean isLiquidInput(byte arg0); + + public abstract boolean isLiquidOutput(byte arg0); + + public abstract boolean doesFillContainers(); + + public abstract boolean doesEmptyContainers();*/ + + public boolean canTankBeFilled() { + return true; + } + + public boolean canTankBeEmptied() { + return true; + } + + + public boolean isFluidInputAllowed(FluidStack aFluid) { + return true; + } + + public FluidStack getFillableStack() { + return this.mFluid; + } + + public FluidStack setFillableStack(FluidStack aFluid) { + this.mFluid = aFluid; + return this.mFluid; + } + + public FluidStack getDrainableStack() { + return this.mFluid; + } + + public FluidStack setDrainableStack(FluidStack aFluid) { + this.mFluid = aFluid; + return this.mFluid; + } + + public FluidStack getDisplayedFluid() { + return this.getDrainableStack(); + } + + public boolean isFluidChangingAllowed() { + return true; + } + + public int fill(FluidStack aFluid, boolean doFill) { + if (aFluid != null && aFluid.getFluid().getID() > 0 && aFluid.amount > 0 && this.canTankBeFilled() + && this.isFluidInputAllowed(aFluid)) { + if (this.getFillableStack() != null && this.getFillableStack().getFluid().getID() > 0) { + if (!this.getFillableStack().isFluidEqual(aFluid)) { + return 0; + } else { + int space = this.getCapacity() - this.getFillableStack().amount; + if (aFluid.amount <= space) { + if (doFill) { + FluidStack arg9999 = this.getFillableStack(); + arg9999.amount += aFluid.amount; + } + + return aFluid.amount; + } else { + if (doFill) { + this.getFillableStack().amount = this.getCapacity(); + } + + return space; + } + } + } else if (aFluid.amount <= this.getCapacity()) { + if (doFill) { + this.setFillableStack(aFluid.copy()); + } + + return aFluid.amount; + } else { + if (doFill) { + this.setFillableStack(aFluid.copy()); + this.getFillableStack().amount = this.getCapacity(); + } + + return this.getCapacity(); + } + } else { + return 0; + } + } + + public FluidStack drain(int maxDrain, boolean doDrain) { + if (this.getDrainableStack() != null && this.canTankBeEmptied()) { + if (this.getDrainableStack().amount <= 0 && this.isFluidChangingAllowed()) { + this.setDrainableStack((FluidStack) null); + return null; + } else { + int used = maxDrain; + if (this.getDrainableStack().amount < maxDrain) { + used = this.getDrainableStack().amount; + } + + if (doDrain) { + FluidStack arg9999 = this.getDrainableStack(); + arg9999.amount -= used; + } + + FluidStack drained = this.getDrainableStack().copy(); + drained.amount = used; + if (this.getDrainableStack().amount <= 0 && this.isFluidChangingAllowed()) { + this.setDrainableStack((FluidStack) null); + } + + return drained; + } + } else { + return null; + } + } + + @Override + public int getCapacity() { + return super.getCapacity(); + } + + @Override + public FluidTankInfo getInfo() { + return new FluidTankInfo(this); + } + + @Override + public void setFluid(FluidStack fluid) { + setFillableStack(fluid); + } + + @Override + public void setCapacity(int capacity) { + super.setCapacity(capacity); + } + + public FluidStack drain(FluidStack aFluid, boolean doDrain) { + return drain(aFluid.amount, doDrain); + } + + + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_Inventory.java b/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_Inventory.java new file mode 100644 index 0000000000..04ce0dff19 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/BTF_Inventory.java @@ -0,0 +1,228 @@ +package gtPlusPlus.api.objects.minecraft; + +import java.util.ArrayList; + +import gregtech.api.util.GT_Utility; +import gtPlusPlus.core.tileentities.base.TileEntityBase; +import gtPlusPlus.core.util.data.ArrayUtils; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.ISidedInventory; +import net.minecraft.item.ItemStack; + +public class BTF_Inventory implements ISidedInventory{ + + public final ItemStack[] mInventory; + public final TileEntityBase mTile; + + public BTF_Inventory(int aSlots, TileEntityBase tile) { + this.mInventory = new ItemStack[aSlots]; + this.mTile = tile; + } + + public ItemStack[] getRealInventory() { + purgeNulls(); + return this.mInventory; + } + + public int getSizeInventory() { + return this.mInventory.length; + } + + public ItemStack getStackInSlot(int aIndex) { + return aIndex >= 0 && aIndex < this.mInventory.length ? this.mInventory[aIndex] : null; + } + + public void setInventorySlotContents(int aIndex, ItemStack aStack) { + if (aIndex >= 0 && aIndex < this.mInventory.length) { + this.mInventory[aIndex] = aStack; + } + } + + public boolean isAccessAllowed(EntityPlayer aPlayer) { + return true; + } + + public boolean isValidSlot(int aIndex) { + return true; + } + + public int getInventoryStackLimit() { + return 64; + } + + + public boolean setStackToZeroInsteadOfNull(int aIndex) { + return false; +} + + public boolean isItemValidForSlot(int aIndex, ItemStack aStack) { + return isValidSlot(aIndex); + } + + public ItemStack decrStackSize(int aIndex, int aAmount) { + ItemStack tStack = this.getStackInSlot(aIndex); + ItemStack rStack = GT_Utility.copy(new Object[]{tStack}); + if (tStack != null) { + if (tStack.stackSize <= aAmount) { + if (this.setStackToZeroInsteadOfNull(aIndex)) { + tStack.stackSize = 0; + } else { + this.setInventorySlotContents(aIndex, (ItemStack) null); + } + } else { + rStack = tStack.splitStack(aAmount); + if (tStack.stackSize == 0 && !this.setStackToZeroInsteadOfNull(aIndex)) { + this.setInventorySlotContents(aIndex, (ItemStack) null); + } + } + } + + return rStack; + } + + public int[] getAccessibleSlotsFromSide(int aSide) { + ArrayList<Integer> tList = new ArrayList<Integer>(); + TileEntityBase tTileEntity = this.mTile; + boolean tSkip = tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, + tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), -2, + tTileEntity) + || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, + tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), -2, + tTileEntity); + + for (int rArray = 0; rArray < this.getSizeInventory(); ++rArray) { + if (this.isValidSlot(rArray) && (tSkip + || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsOut((byte) aSide, + tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), + rArray, tTileEntity) + || tTileEntity.getCoverBehaviorAtSide((byte) aSide).letsItemsIn((byte) aSide, + tTileEntity.getCoverIDAtSide((byte) aSide), tTileEntity.getCoverDataAtSide((byte) aSide), + rArray, tTileEntity))) { + tList.add(Integer.valueOf(rArray)); + } + } + + int[] arg6 = new int[tList.size()]; + + for (int i = 0; i < arg6.length; ++i) { + arg6[i] = ((Integer) tList.get(i)).intValue(); + } + + return arg6; + } + + public boolean canInsertItem(int aIndex, ItemStack aStack, int aSide) { + return this.isValidSlot(aIndex) && aStack != null && aIndex < this.mInventory.length + && (this.mInventory[aIndex] == null || GT_Utility.areStacksEqual(aStack, this.mInventory[aIndex])) + && this.allowPutStack(this.mTile, aIndex, (byte) aSide, aStack); + } + + public boolean canExtractItem(int aIndex, ItemStack aStack, int aSide) { + return this.isValidSlot(aIndex) && aStack != null && aIndex < this.mInventory.length + && this.allowPullStack(this.mTile, aIndex, (byte) aSide, aStack); + } + + public boolean allowPullStack(TileEntityBase mTile2, int aIndex, byte aSide, ItemStack aStack) { + return aIndex >= 0 && aIndex < this.getSizeInventory(); + } + + public boolean allowPutStack(TileEntityBase aBaseMetaTileEntity, int aIndex, byte aSide, ItemStack aStack) { + return (aIndex >= 0 && aIndex < this.getSizeInventory()) && (this.mInventory[aIndex] == null || GT_Utility.areStacksEqual(this.mInventory[aIndex], aStack)); + } + + public ItemStack getStackInSlotOnClosing(int i) { + return null; + } + + public final boolean hasCustomInventoryName() { + return mTile != null ? mTile.hasCustomInventoryName() : false; + } + + + public void markDirty() { + if (mTile != null) { + purgeNulls(); + mTile.markDirty(); + } + } + + public boolean isUseableByPlayer(EntityPlayer entityplayer) { + return true; + } + + public void openInventory() { + + } + + public void closeInventory() { + + } + + @Override + public final String getInventoryName() { + return this.mTile != null ? mTile.getInventoryName() : ""; + } + + public boolean isFull() { + for (int s=0;s<this.getSizeInventory();s++) { + ItemStack slot = mInventory[s]; + if (slot == null || slot.stackSize != slot.getMaxStackSize()) { + return false; + } + } + return true; + } + + public boolean isEmpty() { + for (int s=0;s<this.getSizeInventory();s++) { + ItemStack slot = mInventory[s]; + if (slot == null) { + continue; + } + else { + return false; + } + } + return true; + } + + public boolean addItemStack(ItemStack aInput) { + if (aInput != null & (isEmpty() || !isFull())) { + for (int s = 0; s < this.getSizeInventory(); s++) { + if (mInventory != null && mInventory[s] != null) { + ItemStack slot = mInventory[s]; + if (slot == null || (slot != null && GT_Utility.areStacksEqual(aInput, slot) && slot.stackSize != slot.getItem().getItemStackLimit(slot))) { + if (slot == null) { + slot = aInput.copy(); + } else { + slot.stackSize++; + } + this.setInventorySlotContents(s, slot); + return true; + } + } + } + } + return false; + } + + public final void purgeNulls() { + ItemStack[] aTemp = ArrayUtils.removeNulls(this.mInventory); + for (int g=0;g<this.getSizeInventory();g++) { + if (aTemp.length < this.getSizeInventory()) { + if (g <= aTemp.length-1) { + this.mInventory[g] = aTemp[g]; + } + else { + this.mInventory[g] = null; + } + } + else { + this.mInventory[g] = aTemp[g]; + } + } + + } + + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/BlockPos.java b/src/main/java/gtPlusPlus/api/objects/minecraft/BlockPos.java new file mode 100644 index 0000000000..ab359c3853 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/BlockPos.java @@ -0,0 +1,250 @@ +package gtPlusPlus.api.objects.minecraft; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import net.minecraft.block.Block; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +import gtPlusPlus.api.objects.data.AutoMap; +import net.minecraftforge.common.DimensionManager; + +public class BlockPos implements Serializable{ + + private static final long serialVersionUID = -7271947491316682006L; + public final int xPos; + public final int yPos; + public final int zPos; + public final int dim; + public final transient World world; + + public static BlockPos generateBlockPos(String sUUID) { + String[] s2 = sUUID.split("@"); + return new BlockPos(s2); + } + + public BlockPos(String[] s){ + this(Integer.parseInt(s[1]), Integer.parseInt(s[2]), Integer.parseInt(s[3]), Integer.parseInt(s[0])); + } + + public BlockPos(int x, int y, int z){ + this(x, y, z, 0); + } + + public BlockPos(int x, int y, int z, int dim){ + this(x, y, z, DimensionManager.getWorld(dim)); + } + + public BlockPos(int x, int y, int z, World dim){ + this.xPos = x; + this.yPos = y; + this.zPos = z; + + if (dim != null) { + this.dim = dim.provider.dimensionId; + this.world = dim; + } + else { + this.dim = 0; + this.world = null; + } + + } + + public BlockPos(IGregTechTileEntity b) { + this (b.getXCoord(), b.getYCoord(), b.getZCoord(), b.getWorld()); + } + + public BlockPos(TileEntity b) { + this (b.xCoord, b.yCoord, b.zCoord, b.getWorldObj()); + } + + public String getLocationString() { + return "[X: "+this.xPos+"][Y: "+this.yPos+"][Z: "+this.zPos+"][Dim: "+this.dim+"]"; + } + + public String getUniqueIdentifier() { + String S = ""+this.dim+"@"+this.xPos+"@"+this.yPos+"@"+this.zPos; + return S; + } + + @Override + public int hashCode() { + int hash = 5; + hash += (13 * this.xPos); + hash += (19 * this.yPos); + hash += (31 * this.zPos); + hash += (17 * this.dim); + return hash; + } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } + if (other == this) { + return true; + } + if(!(other instanceof BlockPos)) { + return false; + } + BlockPos otherPoint = (BlockPos)other; + return this.xPos == otherPoint.xPos && this.yPos == otherPoint.yPos && this.zPos == otherPoint.zPos && this.dim == otherPoint.dim; + } + + public int distanceFrom(BlockPos target) { + if (target.dim != this.dim) { + return Short.MIN_VALUE; + } + return distanceFrom(target.xPos, target.yPos, target.zPos); + } + + /** + * + * @param x X coordinate of target. + * @param y Y coordinate of target. + * @param z Z coordinate of target. + * @return square of distance + */ + public int distanceFrom(int x, int y, int z) { + int distanceX = this.xPos - x; + int distanceY = this.yPos - y; + int distanceZ = this.zPos - z; + return distanceX * distanceX + distanceY * distanceY + distanceZ * distanceZ; + } + + public boolean isWithinRange(BlockPos target, int range) { + if (target.dim != this.dim) { + return false; + } + return isWithinRange(target.xPos, target.yPos, target.zPos, range); + } + + public boolean isWithinRange(int x, int y, int z, int range) { + return distanceFrom(x, y, z) <= (range * range); + } + + + public BlockPos getUp() { + return new BlockPos(this.xPos, this.yPos+1, this.zPos, this.dim); + } + + public BlockPos getDown() { + return new BlockPos(this.xPos, this.yPos-1, this.zPos, this.dim); + } + + public BlockPos getXPos() { + return new BlockPos(this.xPos+1, this.yPos, this.zPos, this.dim); + } + + public BlockPos getXNeg() { + return new BlockPos(this.xPos-1, this.yPos, this.zPos, this.dim); + } + + public BlockPos getZPos() { + return new BlockPos(this.xPos, this.yPos, this.zPos+1, this.dim); + } + + public BlockPos getZNeg() { + return new BlockPos(this.xPos, this.yPos, this.zPos-1, this.dim); + } + + public AutoMap<BlockPos> getSurroundingBlocks(){ + AutoMap<BlockPos> sides = new AutoMap<BlockPos>(); + sides.put(getUp()); + sides.put(getDown()); + sides.put(getXPos()); + sides.put(getXNeg()); + sides.put(getZPos()); + sides.put(getZNeg()); + return sides; + } + + public Block getBlockAtPos() { + return getBlockAtPos(this); + } + + public Block getBlockAtPos(BlockPos pos) { + return getBlockAtPos(world, pos); + } + + public Block getBlockAtPos(World world, BlockPos pos) { + return world.getBlock(pos.xPos, pos.yPos, pos.zPos); + } + + public int getMetaAtPos() { + return getMetaAtPos(this); + } + + public int getMetaAtPos(BlockPos pos) { + return getMetaAtPos(world, pos); + } + + public int getMetaAtPos(World world, BlockPos pos) { + return world.getBlockMetadata(pos.xPos, pos.yPos, pos.zPos); + } + + public boolean hasSimilarNeighbour() { + return hasSimilarNeighbour(false); + } + + /** + * @param strict - Does this check Meta Data? + * @return - Does this block have a neighbour that is the same? + */ + public boolean hasSimilarNeighbour(boolean strict) { + for (BlockPos g : getSurroundingBlocks().values()) { + if (getBlockAtPos(g) == getBlockAtPos()) { + if (!strict) { + return true; + } + else { + if (getMetaAtPos() == getMetaAtPos(g)) { + return true; + } + } + } + } + return false; + } + + public AutoMap<BlockPos> getSimilarNeighbour() { + return getSimilarNeighbour(false); + } + + /** + * @param strict - Does this check Meta Data? + * @return - Does this block have a neighbour that is the same? + */ + public AutoMap<BlockPos> getSimilarNeighbour(boolean strict) { + AutoMap<BlockPos> sides = new AutoMap<BlockPos>(); + for (BlockPos g : getSurroundingBlocks().values()) { + if (getBlockAtPos(g) == getBlockAtPos()) { + if (!strict) { + sides.put(g); + } + else { + if (getMetaAtPos() == getMetaAtPos(g)) { + sides.put(g); + } + } + } + } + return sides; + } + + public Set<BlockPos> getValidNeighboursAndSelf(){ + AutoMap<BlockPos> h = getSimilarNeighbour(true); + h.put(this); + Set<BlockPos> result = new HashSet<BlockPos>(); + for (BlockPos f : h.values()) { + result.add(f); + } + return result; + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/CubicObject.java b/src/main/java/gtPlusPlus/api/objects/minecraft/CubicObject.java new file mode 100644 index 0000000000..8c76513d09 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/CubicObject.java @@ -0,0 +1,62 @@ +package gtPlusPlus.api.objects.minecraft; + +import gtPlusPlus.api.objects.data.AutoMap; +import net.minecraftforge.common.util.ForgeDirection; + +public class CubicObject<T> { + + public final T NORTH; + public final T SOUTH; + + public final T WEST; + public final T EAST; + + public final T UP; + public final T DOWN; + + public CubicObject(AutoMap<T> aDataSet) { + this(aDataSet.get(0), aDataSet.get(1), aDataSet.get(2), aDataSet.get(3), aDataSet.get(4), aDataSet.get(5)); + } + + public CubicObject(T[] aDataSet) { + this(aDataSet[0], aDataSet[1], aDataSet[2], aDataSet[3], aDataSet[4], aDataSet[5]); + } + + public CubicObject(T aDOWN, T aUP, T aNORTH, T aSOUTH, T aWEST, T aEAST) { + DOWN = aDOWN; + UP = aUP; + NORTH = aNORTH; + SOUTH = aSOUTH; + WEST = aWEST; + EAST = aEAST; + } + + public T get(int aSide) { + return get(ForgeDirection.getOrientation(aSide)); + } + + public T get(ForgeDirection aSide) { + if (aSide == ForgeDirection.DOWN) { + return DOWN; + } + else if (aSide == ForgeDirection.UP) { + return UP; + } + else if (aSide == ForgeDirection.NORTH) { + return NORTH; + } + else if (aSide == ForgeDirection.SOUTH) { + return SOUTH; + } + else if (aSide == ForgeDirection.WEST) { + return WEST; + } + else if (aSide == ForgeDirection.EAST) { + return EAST; + } + else { + return null; + } + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/DimChunkPos.java b/src/main/java/gtPlusPlus/api/objects/minecraft/DimChunkPos.java new file mode 100644 index 0000000000..010e522a14 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/DimChunkPos.java @@ -0,0 +1,52 @@ +package gtPlusPlus.api.objects.minecraft; + +import net.minecraft.client.Minecraft; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +public class DimChunkPos { + + public final int dimension; + public final int xPos; + public final int zPos; + public final Chunk mainChunk; + + + public DimChunkPos(World world, BlockPos block){ + this.dimension = world.provider.dimensionId; + this.mainChunk = world.getChunkFromBlockCoords(block.xPos, block.zPos); + this.xPos = this.mainChunk.xPosition; + this.zPos = this.mainChunk.zPosition; + } + + + public DimChunkPos(TileEntity tile){ + this.dimension = tile.getWorldObj().provider.dimensionId; + this.mainChunk = tile.getWorldObj().getChunkFromBlockCoords(tile.xCoord, tile.zCoord); + this.xPos = this.mainChunk.xPosition; + this.zPos = this.mainChunk.zPosition; + } + + public DimChunkPos(int dim, int x, int z){ + this.dimension = dim; + this.xPos = x; + this.zPos = z; + Chunk h = Minecraft.getMinecraft().getIntegratedServer().worldServerForDimension(dim).getChunkFromChunkCoords(xPos, zPos); + if (h == null) { + this.mainChunk = null; + } + else { + this.mainChunk = h; + } + } + + public Chunk getChunk() { + if (this.mainChunk != null) { + return this.mainChunk; + } + Chunk h = Minecraft.getMinecraft().getIntegratedServer().worldServerForDimension(this.dimension).getChunkFromChunkCoords(xPos, zPos); + return h; + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/FakeBlockPos.java b/src/main/java/gtPlusPlus/api/objects/minecraft/FakeBlockPos.java new file mode 100644 index 0000000000..d5db8081dc --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/FakeBlockPos.java @@ -0,0 +1,253 @@ +package gtPlusPlus.api.objects.minecraft; + +import java.util.HashSet; +import java.util.Set; + +import gtPlusPlus.api.objects.data.AutoMap; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; + +public class FakeBlockPos extends BlockPos { + + private static final long serialVersionUID = -6442245826092414593L; + private transient Block aBlockAtPos; + private int aBlockMetaAtPos = 0; + + public static FakeBlockPos generateBlockPos(String sUUID) { + String[] s2 = sUUID.split("@"); + return new FakeBlockPos(s2); + } + + public FakeBlockPos(String[] s){ + this(Integer.parseInt(s[1]), Integer.parseInt(s[2]), Integer.parseInt(s[3]), Integer.parseInt(s[0])); + } + + public FakeBlockPos(int x, int y, int z, Block aBlock, int aMeta){ + this(x, y, z, 0); + aBlockAtPos = aBlock; + aBlockMetaAtPos = aMeta; + } + + private FakeBlockPos(int x, int y, int z, int dim){ + this(x, y, z, DimensionManager.getWorld(dim)); + } + + private FakeBlockPos(int x, int y, int z, World dim){ + super(x, y, z, null); + } + + public String getLocationString() { + String S = ""+this.xPos+"@"+this.yPos+"@"+this.zPos; + return S; + } + + public String getUniqueIdentifier() { + String S = ""+this.xPos+"@"+this.yPos+"@"+this.zPos+this.aBlockAtPos.getLocalizedName()+"@"+this.aBlockMetaAtPos; + return S; + } + + @Override + public int hashCode() { + int hash = 5; + hash += (13 * this.xPos); + hash += (19 * this.yPos); + hash += (31 * this.zPos); + hash += (17 * this.dim); + return hash; + } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } + if (other == this) { + return true; + } + if(!(other instanceof FakeBlockPos)) { + return false; + } + FakeBlockPos otherPoint = (FakeBlockPos) other; + return this.xPos == otherPoint.xPos && this.yPos == otherPoint.yPos && this.zPos == otherPoint.zPos; + } + + public int distanceFrom(FakeBlockPos target) { + if (target.dim != this.dim) { + return Short.MIN_VALUE; + } + return distanceFrom(target.xPos, target.yPos, target.zPos); + } + + /** + * + * @param x X coordinate of target. + * @param y Y coordinate of target. + * @param z Z coordinate of target. + * @return square of distance + */ + public int distanceFrom(int x, int y, int z) { + int distanceX = this.xPos - x; + int distanceY = this.yPos - y; + int distanceZ = this.zPos - z; + return distanceX * distanceX + distanceY * distanceY + distanceZ * distanceZ; + } + + public boolean isWithinRange(FakeBlockPos target, int range) { + if (target.dim != this.dim) { + return false; + } + return isWithinRange(target.xPos, target.yPos, target.zPos, range); + } + + public boolean isWithinRange(int x, int y, int z, int range) { + return distanceFrom(x, y, z) <= (range * range); + } + + + public FakeBlockPos getUp() { + return new FakeBlockPos(this.xPos, this.yPos+1, this.zPos, this.dim); + } + + public FakeBlockPos getDown() { + return new FakeBlockPos(this.xPos, this.yPos-1, this.zPos, this.dim); + } + + public FakeBlockPos getXPos() { + return new FakeBlockPos(this.xPos+1, this.yPos, this.zPos, this.dim); + } + + public FakeBlockPos getXNeg() { + return new FakeBlockPos(this.xPos-1, this.yPos, this.zPos, this.dim); + } + + public FakeBlockPos getZPos() { + return new FakeBlockPos(this.xPos, this.yPos, this.zPos+1, this.dim); + } + + public FakeBlockPos getZNeg() { + return new FakeBlockPos(this.xPos, this.yPos, this.zPos-1, this.dim); + } + + public AutoMap<BlockPos> getSurroundingBlocks(){ + AutoMap<BlockPos> sides = new AutoMap<BlockPos>(); + sides.put(getUp()); + sides.put(getDown()); + sides.put(getXPos()); + sides.put(getXNeg()); + sides.put(getZPos()); + sides.put(getZNeg()); + return sides; + } + + public Block getBlockAtPos() { + return getBlockAtPos(this); + } + + public Block getBlockAtPos(FakeBlockPos pos) { + return getBlockAtPos(world, pos); + } + + public Block getBlockAtPos(World world, FakeBlockPos pos) { + return aBlockAtPos; + } + + public int getMetaAtPos() { + return getMetaAtPos(this); + } + + public int getMetaAtPos(FakeBlockPos pos) { + return getMetaAtPos(world, pos); + } + + public int getMetaAtPos(World world, FakeBlockPos pos) { + return aBlockMetaAtPos; + } + + public boolean hasSimilarNeighbour() { + return hasSimilarNeighbour(false); + } + + /** + * @param strict - Does this check Meta Data? + * @return - Does this block have a neighbour that is the same? + */ + public boolean hasSimilarNeighbour(boolean strict) { + for (BlockPos g : getSurroundingBlocks().values()) { + if (getBlockAtPos(g) == getBlockAtPos()) { + if (!strict) { + return true; + } + else { + if (getMetaAtPos() == getMetaAtPos(g)) { + return true; + } + } + } + } + return false; + } + + public AutoMap<BlockPos> getSimilarNeighbour() { + return getSimilarNeighbour(false); + } + + /** + * @param strict - Does this check Meta Data? + * @return - Does this block have a neighbour that is the same? + */ + public AutoMap<BlockPos> getSimilarNeighbour(boolean strict) { + AutoMap<BlockPos> sides = new AutoMap<BlockPos>(); + for (BlockPos g : getSurroundingBlocks().values()) { + if (getBlockAtPos(g) == getBlockAtPos()) { + if (!strict) { + sides.put(g); + } + else { + if (getMetaAtPos() == getMetaAtPos(g)) { + sides.put(g); + } + } + } + } + return sides; + } + + public Set<BlockPos> getValidNeighboursAndSelf(){ + AutoMap<BlockPos> h = getSimilarNeighbour(true); + h.put(this); + Set<BlockPos> result = new HashSet<BlockPos>(); + for (BlockPos f : h.values()) { + result.add(f); + } + return result; + } + + /** + * Called when a plant grows on this block, only implemented for saplings using the WorldGen*Trees classes right now. + * Modder may implement this for custom plants. + * This does not use ForgeDirection, because large/huge trees can be located in non-representable direction, + * so the source location is specified. + * Currently this just changes the block to dirt if it was grass. + * + * Note: This happens DURING the generation, the generation may not be complete when this is called. + * + * @param world Current world + * @param x Soil X + * @param y Soil Y + * @param z Soil Z + * @param sourceX Plant growth location X + * @param sourceY Plant growth location Y + * @param sourceZ Plant growth location Z + */ + public void onPlantGrow(FakeWorld world, int x, int y, int z, int sourceX, int sourceY, int sourceZ) + { + if (getBlockAtPos() == Blocks.grass || getBlockAtPos() == Blocks.farmland) + { + this.aBlockAtPos = Blocks.dirt; + this.aBlockMetaAtPos = 0; + } + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/FakeWorld.java b/src/main/java/gtPlusPlus/api/objects/minecraft/FakeWorld.java new file mode 100644 index 0000000000..8ee033a341 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/FakeWorld.java @@ -0,0 +1,173 @@ +package gtPlusPlus.api.objects.minecraft; + +import java.util.HashMap; + +import gregtech.api.enums.Materials; +import gtPlusPlus.api.objects.Logger; +import gtPlusPlus.api.objects.data.AutoMap; +import gtPlusPlus.core.util.math.MathUtils; +import gtPlusPlus.core.util.minecraft.ItemUtils; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraftforge.common.util.ForgeDirection; + +public class FakeWorld implements IBlockAccess { + + public static HashMap<String, FakeBlockPos> mStaticFakeWorldData; + + public HashMap<String, FakeBlockPos> mFakeWorldData = new HashMap<String, FakeBlockPos>(); + + /** + * Must be an odd number + */ + private int aWorldSize = 99; + private final int aDistanceFromOrigin; + private final int aWorldHeight; + + public FakeWorld() { + this(99); + } + + public FakeWorld(int aSize) { + if (MathUtils.isNumberEven(aSize)) { + aSize++; + } + aWorldSize = aSize; + aDistanceFromOrigin = ((aWorldSize-1)/2); + aWorldHeight = aDistanceFromOrigin >= 255 ? 255 : aDistanceFromOrigin; + Logger.WARNING("Created a Fake World with data:"); + Logger.WARNING("World Size: "+aWorldSize); + Logger.WARNING("Distance from Origin in each dir: "+aDistanceFromOrigin); + Logger.WARNING("World Height: "+aWorldHeight); + init(); + } + + public void init() { + + /*if (mStaticFakeWorldData == null) { + Logger.WARNING("Setting all Blocks in Fake World to Air."); + mStaticFakeWorldData = new HashMap<String, FakeBlockPos>(); + for (int y=0;y<=aWorldHeight;y++) { + for (int x=-aDistanceFromOrigin;x<=aDistanceFromOrigin;x++) { + for (int z=-aDistanceFromOrigin;z<=aDistanceFromOrigin;z++) { + FakeBlockPos aTempPos = new FakeBlockPos(x, y, z, Blocks.air, 0); + mStaticFakeWorldData.put(aTempPos.getLocationString(), aTempPos); + } + } + } + }*/ + //if (mStaticFakeWorldData != null) { + //Logger.WARNING(" Instancing static air world."); + mFakeWorldData = new HashMap<String, FakeBlockPos>(); + //mFakeWorldData = (HashMap<String, FakeBlockPos>) mStaticFakeWorldData.clone(); + //} + + + //Logger.WARNING("Initialisation of FakeWorld is now complete."); + } + + public FakeBlockPos getBlockAtCoords(int x, int y, int z) { + String S = ""+x+"@"+y+"@"+z; + FakeBlockPos aBlock = mFakeWorldData.get(S); + if (aBlock == null) { + return new FakeBlockPos(x, y, z, Blocks.air, 0); + } + return aBlock; + } + + public void setBlockAtCoords(int x, int y, int z, Block aBlock, int aMeta) { + FakeBlockPos aTempPos = new FakeBlockPos(x, y, z, aBlock, aMeta); + Logger.WARNING("Setting "+x+", "+y+", "+z+" to "+aBlock.getLocalizedName()+":"+aMeta); + mFakeWorldData.put(aTempPos.getLocationString(), aTempPos); + } + + public AutoMap<ItemStack> getAllBlocksStoredInFakeWorld(){ + AutoMap<ItemStack> aOutput = new AutoMap<ItemStack>(); + for (FakeBlockPos aPos : mFakeWorldData.values()) { + if (aPos == null || aPos.getBlockAtPos() == Blocks.air) { + continue; + } + else { + ItemStack aTempStack = ItemUtils.simpleMetaStack(aPos.getBlockAtPos(), aPos.getMetaAtPos(), 1); + if (ItemUtils.checkForInvalidItems(aTempStack)) { + //Logger.WARNING("Output: "+aTempStack.getDisplayName()); + aOutput.put(aTempStack); + } + } + } + return aOutput; + } + + public Block getBlock(int x, int y, int z) { + FakeBlockPos aPos = getBlockAtCoords(x, y, z); + return aPos.getBlockAtPos(); + } + + public boolean isAirBlock(int x, int y, int z) { + Block aBlock = getBlock(x, y, z); + return aBlock == Blocks.air || aBlock.getMaterial() == Material.air; + } + + + + + + + + + + + + + + @Override + public TileEntity getTileEntity(int p_147438_1_, int p_147438_2_, int p_147438_3_) { + return null; + } + + @Override + public int getLightBrightnessForSkyBlocks(int p_72802_1_, int p_72802_2_, int p_72802_3_, int p_72802_4_) { + return 0; + } + + @Override + public int getBlockMetadata(int x, int y, int z) { + return getBlockAtCoords(x, y, z).getMetaAtPos(); + } + + @Override + public int isBlockProvidingPowerTo(int p_72879_1_, int p_72879_2_, int p_72879_3_, int p_72879_4_) { + return 0; + } + + @Override + public BiomeGenBase getBiomeGenForCoords(int p_72807_1_, int p_72807_2_) { + return BiomeGenBase.plains; + } + + @Override + public int getHeight() { + return aWorldHeight; + } + + @Override + public boolean extendedLevelsInChunkCache() { + return false; + } + + @Override + public boolean isSideSolid(int x, int y, int z, ForgeDirection side, boolean _default) { + if (!isAirBlock(x, y, z)) { + return true; + } + return false; + } + + + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/FluidGT6.java b/src/main/java/gtPlusPlus/api/objects/minecraft/FluidGT6.java new file mode 100644 index 0000000000..2535046792 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/FluidGT6.java @@ -0,0 +1,31 @@ +package gtPlusPlus.api.objects.minecraft; + +import gregtech.api.GregTech_API; + +import gtPlusPlus.core.lib.CORE; +import net.minecraftforge.fluids.Fluid; + +public class FluidGT6 extends Fluid implements Runnable +{ + private final short[] mRGBa; + public final String mTextureName; + + public FluidGT6(final String aName, final String aTextureName, final short[] aRGBa) { + super(aName); + this.mRGBa = aRGBa; + this.mTextureName = aTextureName; + if (GregTech_API.sGTBlockIconload != null) { + 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)); + } +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/FormattedTooltipString.java b/src/main/java/gtPlusPlus/api/objects/minecraft/FormattedTooltipString.java new file mode 100644 index 0000000000..ec13c82ea0 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/FormattedTooltipString.java @@ -0,0 +1,25 @@ +package gtPlusPlus.api.objects.minecraft; + +public class FormattedTooltipString { + + public final String mText; + public final boolean mPrefix; + + public FormattedTooltipString(String aText, boolean aPrefix) { + mText = aText; + mPrefix = aPrefix; + } + + public String getTooltip(Object aTagValue) { + String aTip; + + if (mPrefix) { + aTip = mText+": "+aTagValue.toString(); + } + else { + aTip = ""+aTagValue.toString()+": "+mText; + } + return aTip; + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/GenericStack.java b/src/main/java/gtPlusPlus/api/objects/minecraft/GenericStack.java new file mode 100644 index 0000000000..9c1b231961 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/GenericStack.java @@ -0,0 +1,42 @@ +package gtPlusPlus.api.objects.minecraft; + +import net.minecraft.item.ItemStack; + +import net.minecraftforge.fluids.FluidStack; + +public class GenericStack { + + private ItemStack mItemStack; + private FluidStack mFluidStack; + + public GenericStack(ItemStack s){ + this.mItemStack = s; + this.mFluidStack = null; + } + + public GenericStack(FluidStack f){ + this.mItemStack = null; + this.mFluidStack = f; + } + + public GenericStack() { + this.mItemStack = null; + this.mFluidStack = null; + } + + public synchronized final FluidStack getFluidStack() { + return mFluidStack; + } + + public synchronized final ItemStack getItemStack() { + return mItemStack; + } + + public synchronized final void setItemStack(ItemStack mItemStack) { + this.mItemStack = mItemStack; + } + + public synchronized final void setFluidStack(FluidStack mFluidStack) { + this.mFluidStack = mFluidStack; + } +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/ItemPackage.java b/src/main/java/gtPlusPlus/api/objects/minecraft/ItemPackage.java new file mode 100644 index 0000000000..fa85f23cf3 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/ItemPackage.java @@ -0,0 +1,58 @@ +package gtPlusPlus.api.objects.minecraft; + +import cpw.mods.fml.common.event.FMLLoadCompleteEvent; +import gtPlusPlus.api.interfaces.RunnableWithInfo; +import gtPlusPlus.core.handler.COMPAT_HANDLER; + +public abstract class ItemPackage implements RunnableWithInfo<String> { + + public ItemPackage() { + this(false); + } + + public ItemPackage(boolean hasExtraLateRun) { + // Register for late run + COMPAT_HANDLER.mObjectsToRunInPostInit.put(this); + if (hasExtraLateRun) { + COMPAT_HANDLER.mObjectsToRunInOnLoadComplete.put(this); + } + init(); + } + + @Override + public final void run() { + generateRecipes(); + } + + @Override + public final String getInfoData() { + return errorMessage(); + } + + public abstract String errorMessage(); + + public abstract boolean generateRecipes(); + + private final void init() { + items(); + blocks(); + fluids(); + } + + public abstract void items(); + + public abstract void blocks(); + + public abstract void fluids(); + + /** + * Override this to handle GT Recipe map manipulation after they're Baked. + * @param event - the {@link FMLLoadCompleteEvent}. + * @return - Did we do anything? + */ + public boolean onLoadComplete(FMLLoadCompleteEvent event) { + return false; + }; + + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/ItemStackData.java b/src/main/java/gtPlusPlus/api/objects/minecraft/ItemStackData.java new file mode 100644 index 0000000000..476926826b --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/ItemStackData.java @@ -0,0 +1,35 @@ +package gtPlusPlus.api.objects.minecraft; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import gtPlusPlus.core.util.minecraft.ItemUtils; + +public class ItemStackData { + + protected final Item mItem; + protected final int mDamage; + protected final int mStackSize; + protected final NBTTagCompound mNBT; + protected final String mUniqueDataTag; + + public ItemStackData (ItemStack aStack) { + mItem = aStack.getItem(); + mDamage = aStack.getItemDamage(); + mStackSize = aStack.stackSize; + mNBT = (aStack.getTagCompound() != null ? aStack.getTagCompound() : new NBTTagCompound()); + mUniqueDataTag = ""+Item.getIdFromItem(mItem)+""+mDamage+""+mStackSize+""+mNBT.getId(); + } + + public String getUniqueDataIdentifier() { + return this.mUniqueDataTag; + } + + public ItemStack getStack() { + ItemStack aTemp = ItemUtils.simpleMetaStack(mItem, mDamage, mStackSize); + aTemp.setTagCompound(mNBT); + return aTemp; + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/NoConflictGTRecipeMap.java b/src/main/java/gtPlusPlus/api/objects/minecraft/NoConflictGTRecipeMap.java new file mode 100644 index 0000000000..78e925fe04 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/NoConflictGTRecipeMap.java @@ -0,0 +1,123 @@ +package gtPlusPlus.api.objects.minecraft; + +import java.util.Collection; +import java.util.Iterator; + +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.util.GT_Recipe; + +import gtPlusPlus.api.objects.data.AutoMap; + +public class NoConflictGTRecipeMap implements Collection<GT_Recipe> { + + private AutoMap<GT_Recipe> mRecipeCache = new AutoMap<GT_Recipe>(); + private final IGregTechTileEntity mMachineType; + + public NoConflictGTRecipeMap () { + this(null); + } + + public NoConflictGTRecipeMap (IGregTechTileEntity tile0) { + this.mMachineType = tile0; + } + public boolean put(GT_Recipe recipe) { + return add(recipe); + } + + public boolean add(GT_Recipe recipe) { + return mRecipeCache.setValue(recipe); + } + + public Collection<GT_Recipe> getRecipeMap() { + return mRecipeCache.values(); + } + + public boolean isMapValidForMachine(IGregTechTileEntity tile) { + return tile == mMachineType; + } + + @Override + public boolean addAll(Collection<? extends GT_Recipe> arg0) { + int a = 0; + for (Object v : arg0) { + if (!this.mRecipeCache.containsValue((GT_Recipe) v)) { + this.mRecipeCache.put((GT_Recipe) v); + a++; + } + } + return a > 0; + } + + @Override + public void clear() { + mRecipeCache.clear(); + } + + @Override + public boolean contains(Object arg0) { + return mRecipeCache.containsValue((GT_Recipe) arg0); + } + + @Override + public boolean containsAll(Collection<?> arg0) { + int a = 0; + for (Object v : arg0) { + if (this.mRecipeCache.containsValue((GT_Recipe) v)) { + a++; + } + } + return a == arg0.size(); + } + + @Override + public boolean isEmpty() { + return mRecipeCache.isEmpty(); + } + + @Override + public Iterator<GT_Recipe> iterator() { + return mRecipeCache.iterator(); + } + + @Override + public boolean remove(Object arg0) { + return mRecipeCache.remove((GT_Recipe) arg0); + } + + @Override + public boolean removeAll(Collection<?> arg0) { + int a = 0; + for (Object v : arg0) { + if (this.mRecipeCache.containsValue((GT_Recipe) v)) { + this.mRecipeCache.remove((GT_Recipe) v); + a++; + } + } + return a > 0; + } + + @Override + public boolean retainAll(Collection<?> arg0) { + int mStartSize = this.mRecipeCache.size(); + this.mRecipeCache = (AutoMap<GT_Recipe>) arg0; + int mEndsize = this.mRecipeCache.size(); + return mStartSize != mEndsize; + } + + @Override + public int size() { + return this.mRecipeCache.size(); + } + + @Override + public Object[] toArray() { + return this.mRecipeCache.toArray(); + } + + @Override + public <T> T[] toArray(T[] arg0) { + return (T[]) this.mRecipeCache.toArray(); + } + + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/SafeTexture.java b/src/main/java/gtPlusPlus/api/objects/minecraft/SafeTexture.java new file mode 100644 index 0000000000..7c418b5a77 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/SafeTexture.java @@ -0,0 +1,64 @@ +package gtPlusPlus.api.objects.minecraft; + +import java.util.HashMap; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.GregTech_API; +import gtPlusPlus.core.util.Utils; +import net.minecraft.util.IIcon; + +/** + * A Server Side safe object that can hold {@link IIcon}s. + * @author Alkalus + * + */ +public class SafeTexture implements Runnable { + + @SideOnly(Side.CLIENT) + private static final HashMap<Integer, IIcon> mHashToIconCache = new HashMap<Integer, IIcon>(); + + @SideOnly(Side.CLIENT) + private static final HashMap<String, Integer> mPathToHashCash = new HashMap<String, Integer>(); + + private static final HashMap<String, SafeTexture> mTextureObjectCache = new HashMap<String, SafeTexture>(); + + private final int mHash; + + private final String mTextureName; + + private final static String getKey(String aTexPath) { + String aNameKey = Utils.sanitizeString(aTexPath); + aNameKey = aNameKey.replace('/', ' '); + aNameKey = aNameKey.toLowerCase(); + return aNameKey; + } + + public static SafeTexture register(String aTexturePath) { + String aNameKey = getKey(aTexturePath); + SafeTexture g = mTextureObjectCache.get(aNameKey); + if (g == null) { + g = new SafeTexture(aTexturePath); + mTextureObjectCache.put(aNameKey, g); + mPathToHashCash.put(aTexturePath, aTexturePath.hashCode()); + } + return g; + } + + private SafeTexture(String aTexturePath) { + mTextureName = aTexturePath; + mHash = getKey(aTexturePath).hashCode(); + GregTech_API.sGTBlockIconload.add(this); + } + + @SideOnly(Side.CLIENT) + public IIcon getIcon() { + return mHashToIconCache.get(mHash); + } + + @Override + public void run() { + mHashToIconCache.put(getKey(mTextureName).hashCode(), GregTech_API.sBlockIcons.registerIcon(mTextureName)); + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/ShapedRecipe.java b/src/main/java/gtPlusPlus/api/objects/minecraft/ShapedRecipe.java new file mode 100644 index 0000000000..c0e9b20c54 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/ShapedRecipe.java @@ -0,0 +1,250 @@ +package gtPlusPlus.api.objects.minecraft; + +import gtPlusPlus.api.objects.Logger; +import gtPlusPlus.api.objects.data.AutoMap; +import gtPlusPlus.api.objects.data.Pair; +import gtPlusPlus.core.util.minecraft.ItemUtils; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.ShapedOreRecipe; + +public class ShapedRecipe { + + private final static String CHARS = "abcdefghijklmnop"; + public ShapedOreRecipe mRecipe; + + ItemStack[] mBlackList = null; + + public ShapedRecipe( + Object aInput1, Object aInput2, Object aInput3, + Object aInput4, Object aInput5, Object aInput6, + Object aInput7, Object aInput8, Object aInput9, + ItemStack aOutput) { + + this(new Object[] {aInput1, aInput2, aInput3, aInput4, aInput5, aInput6, aInput7, aInput8, aInput9}, aOutput); + + } + + public ShapedRecipe(Object[] aInputs, ItemStack aOutput) { + String aGridWhole = ""; + String aGrid[] = new String[3]; + char[] aChar = new char[9]; + String[] aLoggingInfo = new String[9]; + + if (mBlackList == null) { + mBlackList = new ItemStack[] {}; + } + + //Just to be safe + try { + int xSlot = 0; + int xNull = 0; + for (Object u : aInputs) { + String mInfo = ""; + if (u instanceof String) { + mInfo = (String) u; + Logger.RECIPE("Input slot "+xSlot+++" contains "+mInfo); + } + else if (u instanceof ItemStack || u instanceof Item) { + if (u instanceof Item) { + u = ItemUtils.getSimpleStack((Item) u); + } + mInfo = ((ItemStack) u).getDisplayName(); + Logger.RECIPE("Input slot "+xSlot+++" contains "+mInfo); + } + else if (u == null) { + xNull++; + } + } + Logger.RECIPE("Found "+xNull+" null inputs."); + //Check if the output is invalid + if (aOutput != null && xNull < 9) { + + for (ItemStack q : mBlackList) { + if (q != null) { + if (q.isItemEqual(aOutput)) { + Logger.RECIPE("Found recipe Alkalus is Debugging."); + } + } + } + + Object[] mVarags2 = null; + Logger.RECIPE("Generating Shaped Crafting Recipe for "+aOutput.getDisplayName()); + + if (aInputs.length < 9 || aInputs.length > 9) { + Logger.RECIPE("[Fix] Recipe for "+aOutput.getDisplayName()+" has incorrect number of inputs. Size: "+aInputs.length+"."); + //Logger.RECIPE("[1234abcd] Reciped exists at location: "+ReflectionUtils.getMethodName(1)); + //Logger.RECIPE("[1234abcd] Reciped exists at location: "+ReflectionUtils.getMethodName(2)); + //Logger.RECIPE("[1234abcd] Reciped exists at location: "+ReflectionUtils.getMethodName(3)); + //Logger.RECIPE("[1234abcd] Reciped exists at location: "+ReflectionUtils.getMethodName(4)); + //Logger.RECIPE("Reciped exists at location: "+ReflectionUtils.getMethodName(1)); + } + + + //Build a Pair for each slot + AutoMap<Pair<Character, Object>> aRecipePairs = new AutoMap<Pair<Character, Object>>(); + int aCharSlot = 0; + int aMemSlot = 0; + int aInfoSlot = 0; + for (Object stack : aInputs) { + if (stack != null) { + String mInfo = ""; + if (stack instanceof String) { + mInfo = (String) stack; + } + else if (stack instanceof ItemStack || stack instanceof Item) { + if (stack instanceof Item) { + stack = ItemUtils.getSimpleStack((Item) stack); + } + mInfo = ((ItemStack) stack).getDisplayName(); + } + aRecipePairs.put(new Pair<Character, Object>(CHARS.charAt(aCharSlot), stack)); + Logger.RECIPE("Storing '"+CHARS.charAt(aCharSlot)+"' with an object of type "+stack.getClass().getSimpleName()+" and a value of "+mInfo); + aChar[aMemSlot++] = CHARS.charAt(aCharSlot); + aCharSlot++; + aLoggingInfo[aInfoSlot++] = mInfo; + } + else { + aRecipePairs.put(new Pair<Character, Object>(' ', (ItemStack) null)); + Logger.RECIPE("Storing ' ' with an object of type null"); + aChar[aMemSlot++] = ' '; + aLoggingInfo[aInfoSlot++] = "Empty"; + } + } + + Logger.RECIPE(aRecipePairs.size()+" Char|Object pairs registered for recipe."); + //If we have enough valid slots, iterate them and build a String which represents the entire grid. + //If this String is the correct length, we will split it into thirds and build the grid String array. + if (aRecipePairs.size() == 9) { + + for (Pair<Character, Object> h : aRecipePairs) { + if (h.getKey() != null) { + aGridWhole += String.valueOf(h.getKey()); + Logger.RECIPE("Adding '"+String.valueOf(h.getKey())+"' to aGridWhole."); + } + } + + Logger.RECIPE("aGridWhole: "+aGridWhole+" | size: "+aGridWhole.length()); + + //Build crafting grid + if (aGridWhole.length() == 9) { + Logger.RECIPE("aGridWhole size == 9"); + aGrid[0] = ""+aGridWhole.charAt(0)+aGridWhole.charAt(1)+aGridWhole.charAt(2); + aGrid[1] = ""+aGridWhole.charAt(3)+aGridWhole.charAt(4)+aGridWhole.charAt(5); + aGrid[2] = ""+aGridWhole.charAt(6)+aGridWhole.charAt(7)+aGridWhole.charAt(8); + } + else { + Logger.RECIPE("[Fix] Grid length for recipe outputting "+aOutput.getDisplayName()+" is not 9."); + } + + //Rebuild the Map without spaces + aRecipePairs.clear(); + aCharSlot = 0; + + //The amount of spaces in the Varags that the Shape strings takes. + //Currently they are inserted as a single array into index 0. + final int KEY_COUNTER = 1; + + int counter = KEY_COUNTER; + for (Object stack : aInputs) { + if (stack != null) { + String mInfo = ""; + if (stack instanceof String) { + mInfo = (String) stack; + } + else if (stack instanceof ItemStack || stack instanceof Item) { + if (stack instanceof Item) { + stack = ItemUtils.getSimpleStack((Item) stack); + } + mInfo = ((ItemStack) stack).getDisplayName(); + } + aRecipePairs.put(new Pair<Character, Object>(CHARS.charAt(aCharSlot), stack)); + Logger.RECIPE("Registering Pair of '"+CHARS.charAt(aCharSlot)+"' and a "+stack.getClass().getSimpleName()+" object. Object has a value of "+mInfo); + aCharSlot++; + counter++; + } + } + + Logger.RECIPE("Counter started at "+KEY_COUNTER+", counter is now at "+counter+". Trying to create Varag array with a size of "+(KEY_COUNTER+(counter-KEY_COUNTER)*2)); + //Counter started at 3, counter is now at 4. Trying to create Varag array with a size of 2 + + //Register the shaped grid straight to the varags + mVarags2 = new Object[(KEY_COUNTER+(counter-KEY_COUNTER)*2)]; + /*mVarags2[0] = aGrid[0]; + mVarags2[1] = aGrid[1]; + mVarags2[2] = aGrid[2];*/ + mVarags2[0] = aGrid; + + //Add Each Char, then Item to the varags, sequentially. + int counter2 = KEY_COUNTER; + for (Pair<Character, Object> r : aRecipePairs) { + char c = r.getKey(); + Object o = r.getValue(); + + if (o instanceof ItemStack || o instanceof Item) { + if (o instanceof Item) { + o = ItemUtils.getSimpleStack((Item) o); + } + o = ((ItemStack) o).copy(); + } + + mVarags2[counter2] = (char) c; + mVarags2[counter2+1] = o; + counter2 += 2; + } + + Logger.RECIPE("Recipe Summary"); + Logger.RECIPE("+ = + = + = +"); + Logger.RECIPE("= "+aChar[0]+" = "+aChar[1]+" = "+aChar[2]+" ="); + Logger.RECIPE("+ = + = + = +"); + Logger.RECIPE("= "+aChar[3]+" = "+aChar[4]+" = "+aChar[5]+" ="); + Logger.RECIPE("+ = + = + = +"); + Logger.RECIPE("= "+aChar[6]+" = "+aChar[7]+" = "+aChar[8]+" ="); + Logger.RECIPE("+ = + = + = +"); + for (int r=0;r<9;r++) { + if (aChar[r] != ' ') { + Logger.RECIPE(""+aChar[r]+" : "+aLoggingInfo[r]); + } + } + + } + else { + Logger.RECIPE("[Fix] Recipe for "+aOutput.getDisplayName()+" contains a strange number of inputs."); + } + + //Try set the recipe for this object. + ShapedOreRecipe testRecipe = null; + try { + testRecipe = new ShapedOreRecipe(aOutput, mVarags2); + } + catch (Throwable t) { + Logger.RECIPE("[Fix][0] Error thrown when making a ShapedOreRecipe object."); + t.printStackTrace(); + } + if (testRecipe == null) { + this.mRecipe = null; + Logger.RECIPE("[Fix] Failed to generate a shaped recipe."); + } + else { + this.mRecipe = testRecipe; + Logger.RECIPE("Generated a shaped recipe successfully."); + } + } + + //Output was not valid + else { + this.mRecipe = null; + Logger.RECIPE("[Fix] Failed to generate a shaped recipe. Output was not valid."); + } + + + } + catch(Throwable t) { + this.mRecipe = null; + Logger.RECIPE("[Fix][1] Error thrown when making a ShapedOreRecipe object."); + t.printStackTrace(); + } + + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/TexturePackage.java b/src/main/java/gtPlusPlus/api/objects/minecraft/TexturePackage.java new file mode 100644 index 0000000000..e610f8fdf0 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/TexturePackage.java @@ -0,0 +1,55 @@ +package gtPlusPlus.api.objects.minecraft; + +import java.util.LinkedHashMap; +import java.util.Set; + +import gtPlusPlus.api.objects.data.AutoMap; +import net.minecraft.util.IIcon; + +public class TexturePackage { + + private AutoMap<IIcon> mAnimationArray = new AutoMap<IIcon>(); + + public IIcon getFrame(int aFrame) { + if (aFrame < 0 || aFrame >= mAnimationArray.size()) { + return mAnimationArray.get(0); + } + return mAnimationArray.get(aFrame); + } + + public boolean addFrame(IIcon aFrame) { + if (aFrame != null) { + return mAnimationArray.add(aFrame); + } + return false; + } + + public boolean addFrames(AutoMap<IIcon> aFrames) { + for (IIcon h : aFrames) { + if (!addFrame(h)) { + return false; + } + } + return true; + } + + public boolean addFrames(LinkedHashMap<?, IIcon> aFrames) { + for (IIcon h : aFrames.values()) { + if (!addFrame(h)) { + return false; + } + } + return true; + } + + public boolean addFrames(Set<IIcon> aFrames) { + for (IIcon h : aFrames) { + if (!addFrame(h)) { + return false; + } + } + return true; + } + + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/ThreadPooCollector.java b/src/main/java/gtPlusPlus/api/objects/minecraft/ThreadPooCollector.java new file mode 100644 index 0000000000..0ff6e112ac --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/ThreadPooCollector.java @@ -0,0 +1,111 @@ +package gtPlusPlus.api.objects.minecraft; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; + +import gtPlusPlus.GTplusplus; +import gtPlusPlus.GTplusplus.INIT_PHASE; +import gtPlusPlus.api.objects.data.Pair; +import gtPlusPlus.core.tileentities.machines.TileEntityPooCollector; +import gtPlusPlus.core.util.Utils; +import net.minecraft.entity.passive.EntityAnimal; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +public class ThreadPooCollector extends Thread { + + public boolean canRun = true; + public boolean isRunning = false; + + private static final long INIT_TIME; + private static long internalTickCounter = 0; + + private static final ThreadPooCollector mThread; + private static final HashMap<String, Pair<BlockPos, TileEntityPooCollector>> mPooCollectors = new LinkedHashMap<String, Pair<BlockPos, TileEntityPooCollector>>(); + + + static { + mThread = new ThreadPooCollector(); + INIT_TIME = (System.currentTimeMillis()); + } + + public ThreadPooCollector() { + setName("gtpp.handler.poop"); + start(); + } + + public static ThreadPooCollector getInstance() { + return mThread; + } + + public static void addTask(TileEntityPooCollector aTile) { + BlockPos aTempPos = new BlockPos(aTile); + mPooCollectors.put(aTempPos.getUniqueIdentifier(), new Pair<BlockPos, TileEntityPooCollector>(aTempPos, aTile)); + } + + public static void stopThread() { + mThread.canRun = false; + } + + + @Override + public void run() { + + if (!isRunning) { + isRunning = true; + } + else { + return; + } + + while (canRun) { + if (mPooCollectors.isEmpty() || GTplusplus.CURRENT_LOAD_PHASE != INIT_PHASE.STARTED) { + continue; + } else { + internalTickCounter = Utils.getTicksFromSeconds( + Utils.getSecondsFromMillis(Utils.getMillisSince(INIT_TIME, System.currentTimeMillis()))); + if (internalTickCounter % 100 == 0) { + for (Pair<BlockPos, TileEntityPooCollector> pair : mPooCollectors.values()) { + if (pair != null) { + BlockPos p = pair.getKey(); + if (p != null) { + if (p.world != null) { + World w = p.world; + if (w == null) { + continue; + } + Chunk c = w.getChunkFromBlockCoords(p.xPos, p.zPos); + if (c != null) { + if (c.isChunkLoaded) { + int startX = p.xPos - 2; + int startY = p.yPos; + int startZ = p.zPos - 2; + int endX = p.xPos + 3; + int endY = p.yPos + 5; + int endZ = p.zPos + 3; + AxisAlignedBB box = AxisAlignedBB.getBoundingBox(startX, startY, startZ, + endX, endY, endZ); + if (box != null) { + @SuppressWarnings("unchecked") + List<EntityAnimal> animals = w.getEntitiesWithinAABB(EntityAnimal.class, box); + if (animals != null && !animals.isEmpty()) { + pair.getValue().onPostTick(animals); + } + } else { + continue; + } + } + } + } + } + } + } + } + } + } + } + + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoEUBonusMultiBehaviour.java b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoEUBonusMultiBehaviour.java new file mode 100644 index 0000000000..78341db7a1 --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoEUBonusMultiBehaviour.java @@ -0,0 +1,27 @@ +package gtPlusPlus.api.objects.minecraft.multi; + +import gtPlusPlus.xmod.gregtech.api.enums.GregtechItemList; +import net.minecraft.item.ItemStack; + +public class NoEUBonusMultiBehaviour extends SpecialMultiBehaviour { + + public NoEUBonusMultiBehaviour() { + // Used by other mods which may wish to not obtain bonus outputs on their Sifting or Maceration recipes. + } + + @Override + public ItemStack getTriggerItem() { + return GregtechItemList.Chip_MultiNerf_NoEuBonus.get(1); + } + + @Override + public String getTriggerItemTooltip() { + return "Prevents EU discounts on GT++ multiblocks when used"; + } + + @Override + public int getEUPercent() { + return 0; + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoOutputBonusMultiBehaviour.java b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoOutputBonusMultiBehaviour.java new file mode 100644 index 0000000000..8137f2573d --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoOutputBonusMultiBehaviour.java @@ -0,0 +1,27 @@ +package gtPlusPlus.api.objects.minecraft.multi; + +import gtPlusPlus.xmod.gregtech.api.enums.GregtechItemList; +import net.minecraft.item.ItemStack; + +public class NoOutputBonusMultiBehaviour extends SpecialMultiBehaviour { + + public NoOutputBonusMultiBehaviour() { + // Used by other mods which may wish to not obtain bonus outputs on their Sifting or Maceration recipes. + } + + @Override + public ItemStack getTriggerItem() { + return GregtechItemList.Chip_MultiNerf_NoOutputBonus.get(1); + } + + @Override + public String getTriggerItemTooltip() { + return "Prevents bonus output % on GT++ multiblocks when used"; + } + + @Override + public int getOutputChanceRoll() { + return 10000; + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoSpeedBonusMultiBehaviour.java b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoSpeedBonusMultiBehaviour.java new file mode 100644 index 0000000000..fe7a90960d --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/NoSpeedBonusMultiBehaviour.java @@ -0,0 +1,27 @@ +package gtPlusPlus.api.objects.minecraft.multi; + +import gtPlusPlus.xmod.gregtech.api.enums.GregtechItemList; +import net.minecraft.item.ItemStack; + +public class NoSpeedBonusMultiBehaviour extends SpecialMultiBehaviour { + + public NoSpeedBonusMultiBehaviour() { + // Used by other mods which may wish to not obtain bonus outputs on their Sifting or Maceration recipes. + } + + @Override + public ItemStack getTriggerItem() { + return GregtechItemList.Chip_MultiNerf_NoSpeedBonus.get(1); + } + + @Override + public String getTriggerItemTooltip() { + return "Prevents speed bonuses on GT++ multiblocks when used"; + } + + @Override + public int getSpeedBonusPercent() { + return 0; + } + +} diff --git a/src/main/java/gtPlusPlus/api/objects/minecraft/multi/SpecialMultiBehaviour.java b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/SpecialMultiBehaviour.java new file mode 100644 index 0000000000..e562ccc40b --- /dev/null +++ b/src/main/java/gtPlusPlus/api/objects/minecraft/multi/SpecialMultiBehaviour.java @@ -0,0 +1,44 @@ +package gtPlusPlus.api.objects.minecraft.multi; + +import gregtech.api.util.GT_Utility; +import net.minecraft.item.ItemStack; + +/** + * Extend this class to implement custom behaviour for multiblocks. + * The Trigger item when in a special slot or input bus, will cause the multiblock to behave as specified. + * Not overriding a method here will cause the default values to be used. + * @author Alkalus + * + */ +public abstract class SpecialMultiBehaviour { + + private final int mMaxParallelRecipes = Short.MIN_VALUE; + private final int mEUPercent = Short.MIN_VALUE; + private final int mSpeedBonusPercent = Short.MIN_VALUE; + private final int mOutputChanceRoll = Short.MIN_VALUE; + + public abstract ItemStack getTriggerItem(); + + public abstract String getTriggerItemTooltip(); + + public int getMaxParallelRecipes() { + return this.mMaxParallelRecipes; + } + + public int getEUPercent() { + return this.mEUPercent; + } + + public int getSpeedBonusPercent() { + return this.mSpeedBonusPercent; + } + + public int getOutputChanceRoll() { + return this.mOutputChanceRoll; + } + + public final boolean isTriggerItem(ItemStack aToMatch) { + return GT_Utility.areStacksEqual(getTriggerItem(), aToMatch, false); + } + +} |