aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaven Szewczyk <git@eigenraven.me>2024-05-30 18:26:10 +0100
committerGitHub <noreply@github.com>2024-05-30 19:26:10 +0200
commit337594e83a74c432c140b3df3287575b81bce467 (patch)
treeabe57b3390d3dd037ea1442f83c4519ebcb9de07
parent752f262ccd545bdb785ef0e9ce922bf1117d23d6 (diff)
downloadGT5-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>
-rw-r--r--dependencies.gradle1
-rw-r--r--src/functionalTest/java/kubatech/test/EIGTests.java227
-rw-r--r--src/main/java/gregtech/mixin/Mixin.java7
-rw-r--r--src/main/java/gregtech/mixin/mixins/early/minecraft/BlockStemMixin.java23
-rw-r--r--src/main/java/kubatech/CommonProxy.java2
-rw-r--r--src/main/java/kubatech/api/EIGDynamicInventory.java510
-rw-r--r--src/main/java/kubatech/api/IBlockStemAccesor.java8
-rw-r--r--src/main/java/kubatech/api/eig/EIGBucket.java247
-rw-r--r--src/main/java/kubatech/api/eig/EIGDropTable.java224
-rw-r--r--src/main/java/kubatech/api/eig/EIGMode.java154
-rw-r--r--src/main/java/kubatech/api/eig/IEIGBucketFactory.java15
-rw-r--r--src/main/java/kubatech/api/enums/EIGModes.java42
-rw-r--r--src/main/java/kubatech/api/enums/EIGSetupPhase.java16
-rw-r--r--src/main/java/kubatech/api/gui/AutoScalingStackSizeText.java72
-rw-r--r--src/main/java/kubatech/api/implementations/KubaTechGTMultiBlockBase.java6
-rw-r--r--src/main/java/kubatech/api/utils/StringUtils.java6
-rw-r--r--src/main/java/kubatech/loaders/EIGBucketLoader.java27
-rw-r--r--src/main/java/kubatech/loaders/RecipeLoader.java11
-rw-r--r--src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_ExtremeIndustrialGreenhouse.java1570
-rw-r--r--src/main/java/kubatech/tileentity/gregtech/multiblock/eigbuckets/EIGFlowerBucket.java73
-rw-r--r--src/main/java/kubatech/tileentity/gregtech/multiblock/eigbuckets/EIGIC2Bucket.java905
-rw-r--r--src/main/java/kubatech/tileentity/gregtech/multiblock/eigbuckets/EIGRainbowCactusBucket.java77
-rw-r--r--src/main/java/kubatech/tileentity/gregtech/multiblock/eigbuckets/EIGSeedBucket.java286
-rw-r--r--src/main/java/kubatech/tileentity/gregtech/multiblock/eigbuckets/EIGStemBucket.java158
-rw-r--r--src/main/java/kubatech/tileentity/gregtech/multiblock/eigmodes/EIGIC2Mode.java95
-rw-r--r--src/main/java/kubatech/tileentity/gregtech/multiblock/eigmodes/EIGNormalMode.java91
-rw-r--r--src/main/resources/assets/kubatech/lang/en_US.lang3
27 files changed, 3791 insertions, 1065 deletions
diff --git a/dependencies.gradle b/dependencies.gradle
index d4d2bdf0f5..04d535fce8 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -61,6 +61,7 @@ dependencies {
compileOnlyApi("com.github.GTNewHorizons:Railcraft:9.15.8:dev") { transitive = false }
compileOnly("TGregworks:TGregworks:1.7.10-GTNH-1.0.26:deobf") {transitive = false}
+ compileOnly("com.github.GTNewHorizons:ThaumicBases:1.6.4:dev") { transitive = false }
compileOnly("com.github.GTNewHorizons:EnderCore:0.4.6:dev") { transitive = false }
implementation("com.github.GTNewHorizons:Galacticraft:3.1.5-GTNH:dev") { transitive = false }
implementation("com.github.GTNewHorizons:TinkersConstruct:1.12.2-GTNH:dev")
diff --git a/src/functionalTest/java/kubatech/test/EIGTests.java b/src/functionalTest/java/kubatech/test/EIGTests.java
index 1bb88814a4..7cdfa8dae4 100644
--- a/src/functionalTest/java/kubatech/test/EIGTests.java
+++ b/src/functionalTest/java/kubatech/test/EIGTests.java
@@ -20,15 +20,10 @@
package kubatech.test;
-import static gregtech.api.util.GT_RecipeBuilder.MINUTES;
-import static gregtech.api.util.GT_RecipeBuilder.SECONDS;
-import static kubatech.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeIndustrialGreenhouse.EIG_BALANCE_IC2_ACCELERATOR_TIER;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.fail;
+import static gregtech.api.util.GT_RecipeBuilder.HOURS;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.File;
-import java.util.Arrays;
-import java.util.Comparator;
import java.util.Map;
import net.minecraft.block.Block;
@@ -37,7 +32,6 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.MinecraftServer;
-import net.minecraft.util.ChatComponentText;
import net.minecraft.world.MinecraftException;
import net.minecraft.world.World;
import net.minecraft.world.WorldProvider;
@@ -45,6 +39,7 @@ import net.minecraft.world.WorldProviderSurface;
import net.minecraft.world.WorldServer;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldType;
+import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.chunk.storage.IChunkLoader;
import net.minecraft.world.storage.IPlayerFileData;
import net.minecraft.world.storage.ISaveHandler;
@@ -53,8 +48,6 @@ import net.minecraftforge.common.DimensionManager;
import org.junit.jupiter.api.Test;
-import com.gtnewhorizon.gtnhlib.util.map.ItemStackMap;
-
import gregtech.api.GregTech_API;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.common.blocks.GT_Item_Machines;
@@ -62,13 +55,16 @@ import ic2.api.crops.CropCard;
import ic2.api.crops.Crops;
import ic2.core.Ic2Items;
import ic2.core.crop.TileEntityCrop;
+import ic2.core.item.ItemCropSeed;
+import kubatech.api.eig.EIGDropTable;
import kubatech.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeIndustrialGreenhouse;
+import kubatech.tileentity.gregtech.multiblock.eigbuckets.EIGIC2Bucket;
public class EIGTests {
private static final int EIG_CONTROLLER_METADATA = 12_792;
- private static final int NUMBER_OF_CROPS_PER_TEST = 90;
- private static final int NUMBER_OF_TESTS_TO_DO = 30;
+ private static final int EIG_SIMULATION_TIME = 24 * HOURS;
+ private static final int NUMBER_OF_TESTS_TO_DO = 1000;
static World myWorld;
@@ -144,85 +140,73 @@ public class EIGTests {
public int getBlockLightValue(int p_72957_1_, int p_72957_2_, int p_72957_3_) {
return 4;
}
+
+ @Override
+ public BiomeGenBase getBiomeGenForCoords(int x, int z) {
+ // give the environment a fighting chance of being bearable for crops
+ return BiomeGenBase.jungle;
+ }
};
}
}
- private static int leftOverTicksFromRealRun = 0;
-
- ItemStackMap<Integer> getRealDrops(TileEntityCrop cropTile, CropCard cc, int growth, int gain, int resistance) {
+ EIGDropTable getRealDrops(TileEntityCrop cropTile, CropCard cc, int growth, int gain, int resistance) {
cropTile.setCrop(cc);
cropTile.setGrowth((byte) growth);
cropTile.setGain((byte) gain);
cropTile.setResistance((byte) resistance);
- cropTile.tick();
-
- ItemStackMap<Integer> expected = new ItemStackMap<>();
-
- // run for 30 minutes
- for (int k = 0; k < NUMBER_OF_CROPS_PER_TEST; k++) {
- cropTile.ticker = 1;
- cropTile.setSize((byte) cc.maxSize());
- cropTile.setSize(cc.getSizeAfterHarvest(cropTile));
- cropTile.growthPoints = 0;
- int lastHarvestedAt = 0;
- int i;
- for (i = 0; i < (30 * MINUTES) * (1 << EIG_BALANCE_IC2_ACCELERATOR_TIER);) {
- i += TileEntityCrop.tickRate;
- cropTile.tick();
- if (!cc.canGrow(cropTile)) {
- lastHarvestedAt = i;
- ItemStack[] stacks = cropTile.harvest_automated(false);
- for (ItemStack stack : stacks) {
- expected.merge(stack, stack.stackSize, Integer::sum);
- }
+ EIGDropTable expected = new EIGDropTable();
+ byte startingHumidity = cropTile.humidity;
+ byte startingNutrients = cropTile.nutrients;
+ byte startingAirQuality = cropTile.airQuality;
+ int startingNutrientStorage = cropTile.nutrientStorage;
+ int startingWaterStorage = cropTile.waterStorage;
+ // reset the crop to it's stage after harvest
+ cropTile.setSize((byte) cc.maxSize());
+ cropTile.setSize(cc.getSizeAfterHarvest(cropTile));
+ for (int timeElapsed = 0; timeElapsed < EIG_SIMULATION_TIME; timeElapsed += TileEntityCrop.tickRate) {
+ // force reset the stats to max because the eig shouldn't make them change.
+ // some crops check water storage in the can grow and we are ticking which consumes water.
+ cropTile.humidity = startingHumidity;
+ cropTile.nutrients = startingNutrients;
+ cropTile.airQuality = startingAirQuality;
+ cropTile.nutrientStorage = startingNutrientStorage;
+ cropTile.waterStorage = startingWaterStorage;
+ // if fully grown harvest the crop
+ if (cropTile.getSize() >= cc.maxSize()) {
+ ItemStack[] stacks = cropTile.harvest_automated(false);
+ for (ItemStack stack : stacks) {
+ expected.addDrop(stack, stack.stackSize);
}
}
- leftOverTicksFromRealRun += i - lastHarvestedAt;
+ cropTile.tick();
}
-
+ // ensure it leaves the same way it came in
+ cropTile.humidity = startingHumidity;
+ cropTile.nutrients = startingNutrients;
+ cropTile.airQuality = startingAirQuality;
+ cropTile.nutrientStorage = startingNutrientStorage;
+ cropTile.waterStorage = startingWaterStorage;
return expected;
}
- ItemStackMap<Integer> getEIGDrops(GT_MetaTileEntity_ExtremeIndustrialGreenhouse EIG, ItemStack stack) {
- ItemStackMap<Integer> generated = new ItemStackMap<>();
- int imax = (30 * MINUTES) / (5 * SECONDS);
- double ticks_to_ignore_per_operation = Math
- .ceil((double) leftOverTicksFromRealRun / (NUMBER_OF_CROPS_PER_TEST * imax));
- for (int j = 0; j < NUMBER_OF_CROPS_PER_TEST; j++) {
- GT_MetaTileEntity_ExtremeIndustrialGreenhouse.GreenHouseSlot slot = new GT_MetaTileEntity_ExtremeIndustrialGreenhouse.GreenHouseSlot(
- EIG,
- stack.copy(),
- true,
- false);
- if (slot.isValid) {
- for (int i = 0; i < imax; i++) {
- int ticks_to_ignore = (int) Math.min(ticks_to_ignore_per_operation, leftOverTicksFromRealRun);
- leftOverTicksFromRealRun -= ticks_to_ignore;
- for (ItemStack ic2Drop : slot.getIC2Drops(
- EIG,
- (5 * SECONDS * (1 << EIG_BALANCE_IC2_ACCELERATOR_TIER)) - (double) ticks_to_ignore)) {
- generated.merge(ic2Drop, ic2Drop.stackSize, Integer::sum);
- }
- }
- }
- }
-
+ EIGDropTable getEIGDrops(GT_MetaTileEntity_ExtremeIndustrialGreenhouse EIG, ItemStack stack) {
+ EIGDropTable generated = new EIGDropTable();
+ EIGIC2Bucket bucket = new EIGIC2Bucket(stack, stack.stackSize, null, false);
+ bucket.revalidate(EIG);
+ bucket.addProgress(EIG_SIMULATION_TIME, generated);
return generated;
}
@Test
void EIGDrops() {
-
myWorld.setBlock(10, 80, 0, Blocks.farmland, 0, 0);
myWorld.setBlock(10, 81, 0, Block.getBlockFromItem(Ic2Items.crop.getItem()), 0, 0);
- CropCard cc = Crops.instance.getCropCard("gregtech", "Indigo");
+ // using stickreed since it has a random stage after harvest.
+ // it's also more preferable to test using faster growing crops since they can be harvested more often.
+ CropCard cc = Crops.instance.getCropCard("IC2", "stickreed");
TileEntityCrop cropTile = (TileEntityCrop) myWorld.getTileEntity(10, 81, 0);
- ItemStack ccStack = cropTile.generateSeeds(cc, (byte) 10, (byte) 10, (byte) 10, (byte) 1);
- for (int i = 0; i < TileEntityCrop.tickRate; i++) {
- cropTile.waterStorage = 200;
- cropTile.updateEntity();
- }
+ ItemStack ccStack = ItemCropSeed.generateItemStackFromValues(cc, (byte) 10, (byte) 10, (byte) 10, (byte) 1);
GT_Item_Machines itemMachines = (GT_Item_Machines) Item.getItemFromBlock(GregTech_API.sBlockMachines);
itemMachines.placeBlockAt(
@@ -241,6 +225,11 @@ public class EIGTests {
GT_MetaTileEntity_ExtremeIndustrialGreenhouse EIG = (GT_MetaTileEntity_ExtremeIndustrialGreenhouse) te
.getMetaTileEntity();
+ // update stats of crop TE to those provided by the EIG
+ cropTile.humidity = EIGIC2Bucket.getHumidity(EIG, false);
+ cropTile.nutrients = EIGIC2Bucket.getNutrients(EIG);
+ cropTile.airQuality = EIGIC2Bucket.getAirQuality(EIG);
+
int[] abc = new int[] { 0, -2, 3 };
int[] xyz = new int[] { 0, 0, 0 };
EIG.getExtendedFacing()
@@ -254,89 +243,35 @@ public class EIGTests {
ItemStack stackToTest = null;
- for (int n = 0; n < 5; n++) {
-
- int[] x = new int[NUMBER_OF_TESTS_TO_DO];
- int[] y = new int[NUMBER_OF_TESTS_TO_DO];
-
- // MinecraftServer.getServer()
- // .addChatMessage(new ChatComponentText("[EIGTest results]"));
-
- for (int i = 0; i < NUMBER_OF_TESTS_TO_DO; i++) {
- leftOverTicksFromRealRun = 0;
- ItemStackMap<Integer> expected = getRealDrops(cropTile, cc, 10, 10, 10);
- ItemStackMap<Integer> generated = getEIGDrops(EIG, ccStack);
-
- // MinecraftServer.getServer()
- // .addChatMessage(new ChatComponentText("[TEST" + i + "]Real crop drops:"));
- // for (Map.Entry<ItemStack, Integer> entry : expected.entrySet()) {
- // MinecraftServer.getServer()
- // .addChatMessage(new ChatComponentText("- " + entry.getKey().getDisplayName() + " x" +
- // entry.getValue()));
- // }
-
- // MinecraftServer.getServer()
- // .addChatMessage(new ChatComponentText("[TEST" + i + "]EIG crop drops:"));
- // for (Map.Entry<ItemStack, Integer> entry : generated.entrySet()) {
- // MinecraftServer.getServer()
- // .addChatMessage(new ChatComponentText("- " + entry.getKey().getDisplayName() + " x" +
- // entry.getValue()));
- // }
-
- // we are only comparing one item from drops
- if (stackToTest == null) {
- stackToTest = expected.entrySet()
- .stream()
- .max(Comparator.comparingInt(Map.Entry::getValue))
- .get()
- .getKey();
- }
+ double realAvg = 0, eigAvg = 0;
- int expectedValue = expected.getOrDefault(stackToTest, 0);
- int generatedValue = generated.getOrDefault(stackToTest, 0);
+ for (int i = 0; i < NUMBER_OF_TESTS_TO_DO; i++) {
+ EIGDropTable expected = getRealDrops(cropTile, cc, 10, 10, 10);
+ EIGDropTable generated = getEIGDrops(EIG, ccStack);
- x[i] = expectedValue;
- y[i] = generatedValue;
+ // we are only comparing one item from drops
+ if (stackToTest == null) {
+ stackToTest = expected.entrySet()
+ .stream()
+ .max(Map.Entry.comparingByValue())
+ .get()
+ .getKey();
}
- double real_average = Arrays.stream(x)
- .average()
- .getAsDouble();
- double eig_average = Arrays.stream(y)
- .average()
- .getAsDouble();
-
- double real_variance = 0d;
- double a = 0d;
- for (int i : x) {
- a += (i - real_average) * (i - real_average);
- }
- a /= NUMBER_OF_TESTS_TO_DO;
- real_variance = a;
-
- double eig_variance = 0d;
- a = 0d;
- for (int i : y) {
- a += (i - eig_average) * (i - eig_average);
- }
- a /= NUMBER_OF_TESTS_TO_DO;
- eig_variance = a;
-
- double u = (real_average - eig_average)
- / Math.sqrt((real_variance / NUMBER_OF_TESTS_TO_DO) + (eig_variance / NUMBER_OF_TESTS_TO_DO));
- MinecraftServer.getServer()
- .addChatMessage(
- new ChatComponentText(
- "real average = " + Math
- .round(real_average) + " eig average = " + Math.round(eig_average) + " u = " + u));
- double test_critical_value = 1.959964d;
- boolean passed = Math.abs(u) < test_critical_value;
- boolean instafail = Math.abs(u) > test_critical_value * 2;
- if (passed) return;
- assertFalse(instafail);
+ realAvg += expected.getItemAmount(stackToTest);
+ // EIG with ic2 crops doesn't actually have variance, it uses very precise approximations that create
+ // accurate growth rate and drop quality approximations.
+ eigAvg += generated.getItemAmount(stackToTest);
}
- fail();
+ realAvg /= NUMBER_OF_TESTS_TO_DO;
+ eigAvg /= NUMBER_OF_TESTS_TO_DO;
+ double accuracy = Math.min(realAvg / eigAvg, eigAvg / realAvg);
+
+ String debugInfo = String.format("realAvg: %.5f | eigAvg : %.5f | accuracy = %.5f", realAvg, eigAvg, accuracy);
+ System.out.println(debugInfo);
+ // We aim for about 99% accuracy over here.
+ assertTrue(accuracy >= 0.99d);
}
}
diff --git a/src/main/java/gregtech/mixin/Mixin.java b/src/main/java/gregtech/mixin/Mixin.java
index 6e2b927afe..2fb3e55350 100644
--- a/src/main/java/gregtech/mixin/Mixin.java
+++ b/src/main/java/gregtech/mixin/Mixin.java
@@ -43,6 +43,11 @@ public enum Mixin {
.setApplyIf(() -> ConfigHandler.enabledPatches[3])
.setPhase(Phase.EARLY)
.setSide(Side.BOTH)),
+ BlockStemMixin(new Builder("Stem Crop Block Accessor").addMixinClasses("minecraft.BlockStemMixin")
+ .addTargetedMod(VANILLA)
+ .setApplyIf(() -> true)
+ .setPhase(Phase.EARLY)
+ .setSide(Side.BOTH)),
// Extra utilities
RemoveLastMilleniumRain(new Builder("Remove rain from the Last Millenium (Extra Utilities)")
.addMixinClasses("xu.WorldProviderEndOfTimeMixin")
@@ -62,7 +67,7 @@ public enum Mixin {
.addTargetedMod(THAUMCRAFT)
.setApplyIf(() -> ConfigHandler.enabledPatches[2])
.setPhase(Phase.LATE)
- .setSide(Side.BOTH)),;
+ .setSide(Side.BOTH));
public static final Logger LOGGER = LogManager.getLogger("GregTech-Mixin");
diff --git a/src/main/java/gregtech/mixin/mixins/early/minecraft/BlockStemMixin.java b/src/main/java/gregtech/mixin/mixins/early/minecraft/BlockStemMixin.java
new file mode 100644
index 0000000000..685e00b2a8
--- /dev/null
+++ b/src/main/java/gregtech/mixin/mixins/early/minecraft/BlockStemMixin.java
@@ -0,0 +1,23 @@
+package gregtech.mixin.mixins.early.minecraft;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockStem;
+
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+
+import kubatech.api.IBlockStemAccesor;
+
+@Mixin(value = BlockStem.class)
+public class BlockStemMixin implements IBlockStemAccesor {
+
+ @Shadow
+ @Final
+ private Block field_149877_a;
+
+ @Override
+ public Block getCropBlock() {
+ return this.field_149877_a;
+ }
+}
diff --git a/src/main/java/kubatech/CommonProxy.java b/src/main/java/kubatech/CommonProxy.java
index 674b87f95d..20a10b2a52 100644
--- a/src/main/java/kubatech/CommonProxy.java
+++ b/src/main/java/kubatech/CommonProxy.java
@@ -39,6 +39,7 @@ import cpw.mods.fml.common.event.FMLServerStoppedEvent;
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
import kubatech.commands.CommandHandler;
import kubatech.config.Config;
+import kubatech.loaders.EIGBucketLoader;
import kubatech.loaders.MTLoader;
import kubatech.loaders.MobHandlerLoader;
import kubatech.loaders.RecipeLoader;
@@ -67,6 +68,7 @@ public class CommonProxy {
public void postInit(FMLPostInitializationEvent event) {
RecipeLoader.addRecipes();
+ EIGBucketLoader.LoadEIGBuckets();
if (Thaumcraft.isModLoaded()) TCLoader.init();
}
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) -> {
+