diff options
| author | Raven Szewczyk <git@eigenraven.me> | 2024-05-30 18:26:10 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-30 19:26:10 +0200 |
| commit | 337594e83a74c432c140b3df3287575b81bce467 (patch) | |
| tree | abe57b3390d3dd037ea1442f83c4519ebcb9de07 /src/main/java/kubatech/api | |
| parent | 752f262ccd545bdb785ef0e9ce922bf1117d23d6 (diff) | |
| download | GT5-Unofficial-337594e83a74c432c140b3df3287575b81bce467.tar.gz GT5-Unofficial-337594e83a74c432c140b3df3287575b81bce467.tar.bz2 GT5-Unofficial-337594e83a74c432c140b3df3287575b81bce467.zip | |
Complete backend rework of the EIG (#2616)
* Complete backend rework of the EIG
* Mergening Related Updates
Also some loader references refactoring
* fix
(cherry picked from commit 7fd5d7417bddfb6e49ede3986d9a547f15b21289)
* More Mergening fixes
Updates the declaration of the stem mixin to match the new format.
* Inline EIG IC2 bucket constants
addresses: https://github.com/GTNewHorizons/GT5-Unofficial/pull/2616#discussion_r1620596497
* Fix Seed Removal in regular seed simulations
Should address https://github.com/GTNewHorizons/GT5-Unofficial/pull/2616#discussion_r1620583338
---------
Co-authored-by: Guillaume Mercier <10gui-gui10@live.ca>
Co-authored-by: Martin Robertz <dream-master@gmx.net>
Diffstat (limited to 'src/main/java/kubatech/api')
| -rw-r--r-- | src/main/java/kubatech/api/EIGDynamicInventory.java | 510 | ||||
| -rw-r--r-- | src/main/java/kubatech/api/IBlockStemAccesor.java | 8 | ||||
| -rw-r--r-- | src/main/java/kubatech/api/eig/EIGBucket.java | 247 | ||||
| -rw-r--r-- | src/main/java/kubatech/api/eig/EIGDropTable.java | 224 | ||||
| -rw-r--r-- | src/main/java/kubatech/api/eig/EIGMode.java | 154 | ||||
| -rw-r--r-- | src/main/java/kubatech/api/eig/IEIGBucketFactory.java | 15 | ||||
| -rw-r--r-- | src/main/java/kubatech/api/enums/EIGModes.java | 42 | ||||
| -rw-r--r-- | src/main/java/kubatech/api/enums/EIGSetupPhase.java | 16 | ||||
| -rw-r--r-- | src/main/java/kubatech/api/gui/AutoScalingStackSizeText.java | 72 | ||||
| -rw-r--r-- | src/main/java/kubatech/api/implementations/KubaTechGTMultiBlockBase.java | 6 | ||||
| -rw-r--r-- | src/main/java/kubatech/api/utils/StringUtils.java | 6 |
11 files changed, 1299 insertions, 1 deletions
diff --git a/src/main/java/kubatech/api/EIGDynamicInventory.java b/src/main/java/kubatech/api/EIGDynamicInventory.java new file mode 100644 index 0000000000..1c703fe2fa --- /dev/null +++ b/src/main/java/kubatech/api/EIGDynamicInventory.java @@ -0,0 +1,510 @@ +package kubatech.api; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.function.Supplier; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; + +import org.lwjgl.opengl.GL11; + +import com.gtnewhorizons.modularui.api.GlStateManager; +import com.gtnewhorizons.modularui.api.ModularUITextures; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.drawable.ItemDrawable; +import com.gtnewhorizons.modularui.api.drawable.UITexture; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.math.Color; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.internal.Theme; +import com.gtnewhorizons.modularui.common.internal.wrapper.ModularGui; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.ChangeableWidget; +import com.gtnewhorizons.modularui.common.widget.DynamicPositionedRow; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.Scrollable; +import com.kuba6000.mobsinfo.api.utils.ItemID; + +import kubatech.api.gui.AutoScalingStackSizeText; +import kubatech.api.helpers.GTHelper; +import kubatech.api.utils.ModUtils; + +public class EIGDynamicInventory<T> { + + int width, height; + Supplier<Integer> maxSeedCountGetter; + Supplier<Integer> maxSeedTypeGetter; + Supplier<Integer> usedSeedCountGetter; + Supplier<Integer> usedSeedTypesGetter; + private int maxSeedTypes = 0; + private int maxSeedCount = 0; + private int usedSeedTypes = 0; + private int usedSeedCount = 0; + List<T> inventory; + TInventoryGetter<T> inventoryGetter; + TInventoryInjector inventoryInjector = null; + TInventoryExtractor<T> inventoryExtractor = null; + TInventoryReplacerOrMerger inventoryReplacer = null; + Supplier<Boolean> isEnabledGetter = null; + boolean isEnabled = true; + + public EIGDynamicInventory(int width, int height, Supplier<Integer> maxSeedTypeGetter, + Supplier<Integer> maxSeedCountGetter, Supplier<Integer> usedSeedTypesGetter, + Supplier<Integer> usedSeedCountGetter, List<T> inventory, TInventoryGetter<T> inventoryGetter) { + this.width = width; + this.height = height; + this.maxSeedTypeGetter = maxSeedTypeGetter; + this.maxSeedCountGetter = maxSeedCountGetter; + this.usedSeedTypesGetter = usedSeedTypesGetter; + this.usedSeedCountGetter = usedSeedCountGetter; + this.inventory = inventory; + this.inventoryGetter = inventoryGetter; + } + + public EIGDynamicInventory<T> allowInventoryInjection(TInventoryInjector inventoryInjector) { + this.inventoryInjector = inventoryInjector; + return this; + } + + public EIGDynamicInventory<T> allowInventoryExtraction(TInventoryExtractor<T> inventoryExtractor) { + this.inventoryExtractor = inventoryExtractor; + return this; + } + + public EIGDynamicInventory<T> allowInventoryReplace(TInventoryReplacerOrMerger inventoryReplacer) { + this.inventoryReplacer = inventoryReplacer; + return this; + } + + public EIGDynamicInventory<T> setEnabled(Supplier<Boolean> isEnabled) { + this.isEnabledGetter = isEnabled; + return this; + } + + public UITexture getItemSlot() { + return ModularUITextures.ITEM_SLOT; + } + + @SuppressWarnings("UnstableApiUsage") + public Widget asWidget(ModularWindow.Builder builder, UIBuildContext buildContext) { + ChangeableWidget container = new ChangeableWidget(() -> createWidget(buildContext.getPlayer())); + // TODO: Only reset the widget when there are more slot stacks, otherwise just refresh them somehow + + container + // max seed types + .attachSyncer(new FakeSyncWidget.IntegerSyncer(() -> { + int i = this.maxSeedTypeGetter.get(); + if (this.maxSeedTypes != i) { + this.maxSeedTypes = i; + container.notifyChangeNoSync(); + } + return i; + }, i -> { + if (this.maxSeedTypes != i) { + this.maxSeedTypes = i; + container.notifyChangeNoSync(); + } + }), builder) + // used seed types + .attachSyncer(new FakeSyncWidget.IntegerSyncer(() -> { + int i = this.usedSeedTypesGetter.get(); + if (this.usedSeedTypes != i) { + this.usedSeedTypes = i; + container.notifyChangeNoSync(); + } + return i; + }, i -> { + if (this.usedSeedTypes != i) { + this.usedSeedTypes = i; + container.notifyChangeNoSync(); + } + }), builder) + // max seed count + .attachSyncer(new FakeSyncWidget.IntegerSyncer(() -> { + int i = this.maxSeedCountGetter.get(); + if (this.maxSeedCount != i) { + this.maxSeedCount = i; + container.notifyChangeNoSync(); + } + return i; + }, i -> { + if (this.maxSeedCount != i) { + this.maxSeedCount = i; + container.notifyChangeNoSync(); + } + }), builder) + // used seed count + .attachSyncer(new FakeSyncWidget.IntegerSyncer(() -> { + int i = this.usedSeedCountGetter.get(); + if (this.usedSeedCount != i) { + this.usedSeedCount = i; + container.notifyChangeNoSync(); + } + return i; + }, i -> { + if (this.usedSeedCount != i) { + this.usedSeedCount = i; + container.notifyChangeNoSync(); + } + }), builder) + + .attachSyncer(new FakeSyncWidget.ListSyncer<>(() -> { + List<GTHelper.StackableItemSlot> newDrawables = new ArrayList<>(); + for (int i = 0, mStorageSize = inventory.size(); i < mStorageSize; i++) { + T slot = inventory.get(i); + if (slot == null) { + continue; + } + ItemStack stack = inventoryGetter.get(slot); + newDrawables + .add(new GTHelper.StackableItemSlot(1, stack, new ArrayList<>(Collections.singletonList(i)))); + } + if (!Objects.equals(newDrawables, drawables)) { + drawables = newDrawables; + container.notifyChangeNoSync(); + } + return drawables; + }, l -> { + drawables.clear(); + drawables.addAll(l); + container.notifyChangeNoSync(); + }, (buffer, i) -> { + try { + i.write(buffer); + } catch (IOException e) { + throw new RuntimeException(e); + } + }, buffer -> { + try { + return GTHelper.StackableItemSlot.read(buffer); + } catch (IOException e) { + throw new RuntimeException(e); + } + }), builder); + if (isEnabledGetter != null) { + container.attachSyncer(new FakeSyncWidget.BooleanSyncer(isEnabledGetter, i -> isEnabled = i), builder); + } + return container; + } + + List<GTHelper.StackableItemSlot> drawables = new ArrayList<>(); + + private Widget createWidget(EntityPlayer player) { + Scrollable dynamicInventoryWidget = new Scrollable().setVerticalScroll(); + + ArrayList<Widget> buttons = new ArrayList<>(); + + if (!ModUtils.isClientThreaded()) { + HashMap<ItemID, Integer> itemMap = new HashMap<>(); + HashMap<ItemID, ItemStack> stackMap = new HashMap<>(); + HashMap<ItemID, ArrayList<Integer>> realSlotMap = new HashMap<>(); + drawables = new ArrayList<>(); + for (int i = 0, inventorySize = inventory.size(); i < inventorySize; i++) { + T slot = inventory.get(i); + if (slot == null) { + continue; + } + ItemStack stack = inventoryGetter.get(slot); + drawables + .add(new GTHelper.StackableItemSlot(1, stack, new ArrayList<Integer>(Collections.singleton(i)))); + } + } + + for (int ID = 0; ID < drawables.size(); ID++) { + final int finalID = ID; + + buttons.add(new ButtonWidget() { + + @Override + public void drawBackground(float partialTicks) { + super.drawBackground(partialTicks); + if (!isEnabled) { + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_BLEND); + GlStateManager.colorMask(true, true, true, false); + ModularGui.drawSolidRect(1, 1, 16, 16, Color.withAlpha(Color.BLACK.normal, 0x80)); + GlStateManager.colorMask(true, true, true, true); + GL11.glDisable(GL11.GL_BLEND); + } + // Copied from SlotWidget#draw + else if (isHovering() && !getContext().getCursor() + .hasDraggable()) { + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_BLEND); + GlStateManager.colorMask(true, true, true, false); + ModularGui.drawSolidRect(1, 1, 16, 16, Theme.INSTANCE.getSlotHighlight()); + GlStateManager.colorMask(true, true, true, true); + GL11.glDisable(GL11.GL_BLEND); + } + } + }.setPlayClickSound(false) + .setOnClick((clickData, widget) -> { + if (!(player instanceof EntityPlayerMP)) return; + if (!isEnabledGetter.get()) return; + + if (clickData.mouseButton == 2) { + // special button handler goes here + if (drawables.size() <= finalID) return; + if (player.capabilities.isCreativeMode && player.inventory.getItemStack() == null) { + int realID = drawables.get(finalID).realSlots.get(0); + ItemStack stack = inventoryGetter.get(inventory.get(realID)) + .copy(); + stack.stackSize = stack.getMaxStackSize(); + player.inventory.setItemStack(stack); + ((EntityPlayerMP) player).isChangingQuantityOnly = false; + ((EntityPlayerMP) player).updateHeldItem(); + return; + } + } else if (clickData.shift) { + if (inventoryExtractor == null) return; + if (drawables.size() <= finalID) return; + int realID = drawables.get(finalID).realSlots.get(0); + T toRemoveFrom = this.inventory.get(realID); + ItemStack removed = this.inventoryExtractor.extract(toRemoveFrom, (EntityPlayerMP) player); + if (removed != null) { + if (player.inventory.addItemStackToInventory(removed)) + player.inventoryContainer.detectAndSendChanges(); + else player.entityDropItem(removed, 0.f); + return; + } + } else { + ItemStack input = player.inventory.getItemStack(); + if (input != null) { + if (inventoryInjector == null) return; + if (clickData.mouseButton == 1) { + ItemStack copy = input.copy(); + copy.stackSize = 1; + inventoryInjector.inject(copy); + if (copy.stackSize == 1) return; + input.stackSize--; + if (input.stackSize > 0) { + // clearing and updating the held item value like this is the only + // way i found to be able to reliably update the item count in the UI. + player.inventory.setItemStack(null); + ((EntityPlayerMP) player).updateHeldItem(); + player.inventory.setItemStack(input); + ((EntityPlayerMP) player).updateHeldItem(); + return; + } else player.inventory.setItemStack(null); + } else { + inventoryInjector.inject(input); + if (input.stackSize > 0) { + // clearing and updating the held item value like this is the only + // way i found to be able to reliably update the item count in the UI. + player.inventory.setItemStack(null); + ((EntityPlayerMP) player).updateHeldItem(); + player.inventory.setItemStack(input); + ((EntityPlayerMP) player).updateHeldItem(); + return; + } else player.inventory.setItemStack(null); + } + ((EntityPlayerMP) player).isChangingQuantityOnly = false; + ((EntityPlayerMP) player).updateHeldItem(); + return; + } + if (drawables.size() > finalID) { + if (inventoryExtractor == null) return; + int realID = drawables.get(finalID).realSlots.get(0); + T toRemoveFrom = this.inventory.get(realID); + ItemStack removed = this.inventoryExtractor.extract(toRemoveFrom, (EntityPlayerMP) player); + if (removed != null) { + player.inventory.setItemStack(removed); + ((EntityPlayerMP) player).isChangingQuantityOnly = false; + ((EntityPlayerMP) player).updateHeldItem(); + return; + } + } + } + }) + .setBackground(() -> { + ItemStack stack = drawables.get(finalID).stack; + float slotSize = 16.0f; + IDrawable itemDrawable = new ItemDrawable(stack).withFixedSize(slotSize, slotSize, 1, 1); + IDrawable stackSizeText = new AutoScalingStackSizeText(stack.stackSize).color(Color.WHITE.normal) + .shadow() + .alignment(Alignment.BottomRight) + .measure(); + + return new IDrawable[] { getItemSlot(), itemDrawable, stackSizeText }; + }) + .dynamicTooltip(() -> { + if (drawables.size() > finalID) { + ItemStack stack = drawables.get(finalID).stack; + List<String> tip = new LinkedList<>(); + for (Object o : stack.getTooltip(player, false)) { + tip.add(o.toString()); + } + if (tip.size() >= 1 && tip.get(0) != null) { + tip.set(0, stack.stackSize + " x " + tip.get(0)); + } + return tip; + } + return Collections.emptyList(); + }) + .setSize(18, 18)); + } + + // only add the extra slot if we are still able to insert + if (this.usedSeedCount < this.maxSeedCount) { + buttons.add(new ButtonWidget() { + + @Override + public void drawBackground(float partialTicks) { + super.drawBackground(partialTicks); + if (!isEnabled) { + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_BLEND); + GlStateManager.colorMask(true, true, true, false); + ModularGui.drawSolidRect(1, 1, 16, 16, Color.withAlpha(Color.BLACK.normal, 0x80)); + GlStateManager.colorMask(true, true, true, true); + GL11.glDisable(GL11.GL_BLEND); + } + // Copied from SlotWidget#draw + else if (isHovering() && !getContext().getCursor() + .hasDraggable()) { + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_BLEND); + GlStateManager.colorMask(true, true, true, false); + ModularGui.drawSolidRect(1, 1, 16, 16, Theme.INSTANCE.getSlotHighlight()); + GlStateManager.colorMask(true, true, true, true); + GL11.glDisable(GL11.GL_BLEND); + } + } + }.setPlayClickSound(false) + .setOnClick((clickData, widget) -> { + if (!(player instanceof EntityPlayerMP)) return; + if (!isEnabledGetter.get()) return; + ItemStack input = player.inventory.getItemStack(); + if (input != null) { + if (clickData.mouseButton == 1) { + ItemStack copy = input.copy(); + copy.stackSize = 1; + inventoryInjector.inject(copy); + if (copy.stackSize == 1) return; + + input.stackSize--; + if (input.stackSize > 0) { + // clearing and updating the held item value like this is the only + // way i found to be able to reliably update the item count in the UI. + player.inventory.setItemStack(null); + ((EntityPlayerMP) player).updateHeldItem(); + player.inventory.setItemStack(input); + ((EntityPlayerMP) player).updateHeldItem(); + return; + } else player.inventory.setItemStack(null); + } else { + inventoryInjector.inject(input); + if (input.stackSize > 0) { + // clearing and updating the held item value like this is the only + // way i found to be able to reliably update the item count in the UI. + player.inventory.setItemStack(null); + ((EntityPlayerMP) player).updateHeldItem(); + player.inventory.setItemStack(input); + ((EntityPlayerMP) player).updateHeldItem(); + return; + } else player.inventory.setItemStack(null); + } + ((EntityPlayerMP) player).isChangingQuantityOnly = false; + ((EntityPlayerMP) player).updateHeldItem(); + return; + } + }) + .setBackground(() -> { + IDrawable itemSlot = getItemSlot(); + + IDrawable stackSizeText = new AutoScalingStackSizeText(this.maxSeedCount - this.usedSeedCount) + .color(Color.WHITE.normal) + .shadow() + .alignment(Alignment.BottomRight) + .measure(); + + return new IDrawable[] { itemSlot, stackSizeText }; + }) + .dynamicTooltip(() -> { + // TODO: all l10n for insertion slot tooltip. + List<String> tip = new ArrayList<>(); + tip.add( + EnumChatFormatting.DARK_PURPLE + "Remaining seed types: " + + (this.maxSeedTypes - this.usedSeedTypes)); + tip.add( + EnumChatFormatting.DARK_GREEN + "Remaining seed capacity: " + + (this.maxSeedCount - this.usedSeedCount)); + return tip; + }) + .setSize(18, 18)); + } + + final int perRow = width / 18; + for (int i = 0, imax = ((buttons.size() - 1) / perRow); i <= imax; i++) { + DynamicPositionedRow row = new DynamicPositionedRow().setSynced(false); + for (int j = 0, jmax = (i == imax ? (buttons.size() - 1) % perRow : (perRow - 1)); j <= jmax; j++) { + final int finalI = i * perRow; + final int finalJ = j; + final int ID = finalI + finalJ; + row.widget(buttons.get(ID)); + } + dynamicInventoryWidget.widget(row.setPos(0, i * 18)); + } + dynamicInventoryWidget.setSize(width, height); + return dynamicInventoryWidget; + } + + @FunctionalInterface + public interface TInventoryGetter<T> { + + /** + * Allows to get an ItemStack from the dynamic inventory + * + * @param from Dynamic inventory item from which we want to take an item out + * @return ItemStack or null if inaccessible + */ + ItemStack get(T from); + } + + @FunctionalInterface + public interface TInventoryInjector { + + /** + * Allows to insert an item to the dynamic inventory + * + * @param what ItemStack which we are trying to insert + * @return Leftover ItemStack (stackSize == 0 if everything has been inserted) or null + */ + ItemStack inject(ItemStack what); + } + + @FunctionalInterface + public interface TInventoryExtractor<T> { + + /** + * Allows to extract an item from the dynamic inventory + * + * @return Item that we took out or null + */ + ItemStack extract(T container, EntityPlayerMP player); + } + + @FunctionalInterface + public interface TInventoryReplacerOrMerger { + + /** + * Allows to replace an item in Dynamic Inventory + * + * @param where which index we want to replace + * @param stack what stack we want to replace it with + * @return Stack that we are left with or null + */ + ItemStack replaceOrMerge(int where, ItemStack stack); + } + +} diff --git a/src/main/java/kubatech/api/IBlockStemAccesor.java b/src/main/java/kubatech/api/IBlockStemAccesor.java new file mode 100644 index 0000000000..8f2c37e15f --- /dev/null +++ b/src/main/java/kubatech/api/IBlockStemAccesor.java @@ -0,0 +1,8 @@ +package kubatech.api; + +import net.minecraft.block.Block; + +public interface IBlockStemAccesor { + + Block getCropBlock(); +} diff --git a/src/main/java/kubatech/api/eig/EIGBucket.java b/src/main/java/kubatech/api/eig/EIGBucket.java new file mode 100644 index 0000000000..6a3dbdb642 --- /dev/null +++ b/src/main/java/kubatech/api/eig/EIGBucket.java @@ -0,0 +1,247 @@ +package kubatech.api.eig; + +import static kubatech.api.utils.ItemUtils.readItemStackFromNBT; +import static kubatech.api.utils.ItemUtils.writeItemStackToNBT; + +import java.util.LinkedList; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.EnumChatFormatting; + +import gregtech.api.util.GT_Utility; +import kubatech.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeIndustrialGreenhouse; + +public abstract class EIGBucket { + + protected ItemStack seed; + protected int seedCount; + protected ItemStack[] supportItems; + + public EIGBucket(ItemStack seed, int seedCount, ItemStack[] supportItem) { + this.seed = seed.copy(); + this.seed.stackSize = 1; + this.seedCount = seedCount; + this.supportItems = supportItem; + } + + public EIGBucket(NBTTagCompound nbt) { + this.seed = readItemStackFromNBT(nbt.getCompoundTag("seed")); + this.seedCount = nbt.getInteger("count"); + + // parse support items + if (nbt.hasKey("supportItems", 9)) { + NBTTagList supportItemsNBTList = nbt.getTagList("supportItems", 10); + if (supportItemsNBTList.tagCount() > 0) { + this.supportItems = new ItemStack[supportItemsNBTList.tagCount()]; + for (int i = 0; i < supportItemsNBTList.tagCount(); i++) { + this.supportItems[i] = readItemStackFromNBT(supportItemsNBTList.getCompoundTagAt(i)); + } + } else { + supportItems = null; + } + } else { + supportItems = null; + } + } + + /** + * Creates a persistent save of the bucket's current data. + * + * @return The nbt data for this bucket. + */ + public NBTTagCompound save() { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setString("type", this.getNBTIdentifier()); + nbt.setTag("seed", writeItemStackToNBT(this.seed)); + nbt.setInteger("count", this.seedCount); + if (this.supportItems != null && this.supportItems.length > 0) { + NBTTagList supportItemNBT = new NBTTagList(); + for (ItemStack supportItem : this.supportItems) { + supportItemNBT.appendTag(writeItemStackToNBT(supportItem)); + } + nbt.setTag("supportItems", supportItemNBT); + } + return nbt; + } + + /** + * Gets an item stack representing the seeds in this bucket + * + * @return an item stack representing the seeds in this bucket. + */ + public ItemStack getSeedStack() { + ItemStack copied = this.seed.copy(); + copied.stackSize = this.seedCount; + return copied; + } + + /** + * Gets the number of seeds in this bucket + * + * @return gets the number of seeds in this bucket. + */ + public int getSeedCount() { + return this.seedCount; + } + + /** + * Gets the display name of the seed in this bucket + * + * @return The display name of the seed. + */ + public String getDisplayName() { + return this.seed.getDisplayName(); + } + + public String getInfoData() { + StringBuilder sb = new StringBuilder(); + // display invalid buckets, we don't want people to think they lost their seeds or something. + sb.append(this.isValid() ? EnumChatFormatting.GREEN : EnumChatFormatting.RED); + sb.append("x"); + sb.append(this.getSeedCount()); + sb.append(" "); + sb.append(this.getDisplayName()); + this.getAdditionalInfoData(sb); + sb.append(EnumChatFormatting.RESET); + return sb.toString(); + } + + protected void getAdditionalInfoData(StringBuilder sb) {} + + /** + * Attempts to add seeds to tbe bucket if the input is compatible + * + * @param input A stack of an item that may be able to be added to our current bucket. + * @param maxConsume The maximum amount of seeds to add to this bucket. + * @param simulate True if you want to see if you can add more seeds (useful for support item checks) + * @return number of seeds consumed, 0 for wrong item, -1 if it missed the support items, -2 if you tried to consume + * 0 or less items; + */ + public int tryAddSeed(GT_MetaTileEntity_ExtremeIndustrialGreenhouse greenhouse, ItemStack input, int maxConsume, + boolean simulate) { + // Abort is input if empty + if (input == null || input.stackSize <= 0) return -2; + // Cap max to input count + maxConsume = Math.min(maxConsume, input.stackSize); + // Abort if item isn't an identical seed. + if (!GT_Utility.areStacksEqual(this.seed, input, false)) return 0; + + // no support items, consume and exit early. + if (this.supportItems == null || this.supportItems.length <= 0) { + if (!simulate) { + input.stackSize -= maxConsume; + this.seedCount += maxConsume; + } + return maxConsume; + } + + // Check if the item is found + LinkedList<ItemStack> toConsumeFrom = new LinkedList<>(); + supportLoop: for (ItemStack supportItem : this.supportItems) { + for (ItemStack otherInput : greenhouse.getStoredInputs()) { + // filter usable inputs + if (otherInput == null || otherInput.stackSize <= 0) continue; + if (!GT_Utility.areStacksEqual(supportItem, otherInput, false)) continue; + // update max consume again + maxConsume = Math.min(maxConsume, otherInput.stackSize); + toConsumeFrom.addLast(otherInput); + continue supportLoop; + } + // no support found, no seeds added + return -1; + } + + // consume items + if (!simulate) { + input.stackSize -= maxConsume; + for (ItemStack stack : toConsumeFrom) { + stack.stackSize -= maxConsume; + } + this.seedCount += maxConsume; + } + return maxConsume; + } + + /** + * Attempts to remove a seed from the bucket + * + * @param toRemove The maximum amount of items to remove. + * @return The items that were removed from the bucket. Null if the bucket is empty. + */ + public ItemStack[] tryRemoveSeed(int toRemove, boolean simulate) { + // validate inputs + toRemove = Math.min(this.seedCount, toRemove); + if (toRemove <= 0) return null; + + // consume and return output + ItemStack[] ret = new ItemStack[1 + (this.supportItems == null ? 0 : this.supportItems.length)]; + ret[0] = this.seed.copy(); + ret[0].stackSize = toRemove; + if (this.supportItems != null) { + for (int i = 0; i < this.supportItems.length; i++) { + ret[i + 1] = this.supportItems[i].copy(); + ret[i + 1].stackSize = toRemove; + } + } + if (!simulate) { + this.seedCount -= toRemove; + } + return ret; + } + + /** + * Sets the seed count to 0 and returns item stacks representing every item in this bucket. + * + * @return The contents of the bucket + */ + public ItemStack[] emptyBucket() { + if (this.seedCount <= 0) return null; + ItemStack[] ret = new ItemStack[1 + (this.supportItems == null ? 0 : this.supportItems.length)]; + ret[0] = this.seed.copy(); + ret[0].stackSize = this.seedCount; + if (this.supportItems != null) { + for (int i = 0; i < this.supportItems.length; i++) { + ret[i + 1] = this.supportItems[i].copy(); + ret[i + 1].stackSize = this.seedCount; + } + } + this.seedCount = 0; + return ret; + } + + /** + * Returns true if the bucket can output items. + * + * @return true if the bucket is valid. + */ + public boolean isValid() { + return this.seed != null && this.seedCount > 0; + } + + /** + * Gets the identifier used to identify this class during reconstruction + * + * @return the identifier for this bucket type. + */ + protected abstract String getNBTIdentifier(); + + /** + * Adds item drops to the item tracker. + * + * @param multiplier A multiplier to apply to the output. + * @param tracker The item drop tracker + */ + public abstract void addProgress(double multiplier, EIGDropTable tracker); + + /** + * Attempts to revalidate a seed bucket. If it returns false, attempt to seed and support items and delete the + * bucket. + * + * @param greenhouse The greenhouse that contains the bucket. + * @return True if the bucket was successfully validated. {@link EIGBucket#isValid()} should also return true. + */ + public abstract boolean revalidate(GT_MetaTileEntity_ExtremeIndustrialGreenhouse greenhouse); + +} |
