From 8aa595f083b5c3e43246119fca5f4263f81e851b Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Sat, 25 May 2024 14:42:41 +0100 Subject: Migrate kubatech source code --- .../java/kubatech/test/EIGTests.java | 342 +++++ .../java/kubatech/test/kubatechTestMod.java | 101 ++ src/main/java/kubatech/ClientProxy.java | 75 + src/main/java/kubatech/CommonProxy.java | 87 ++ src/main/java/kubatech/FMLEventHandler.java | 42 + src/main/java/kubatech/Tags.java | 31 + src/main/java/kubatech/api/DynamicInventory.java | 469 ++++++ src/main/java/kubatech/api/LoaderReference.java | 23 + src/main/java/kubatech/api/Variables.java | 63 + src/main/java/kubatech/api/enums/ItemList.java | 226 +++ src/main/java/kubatech/api/helpers/GTHelper.java | 99 ++ .../kubatech/api/helpers/ReflectionHelper.java | 205 +++ src/main/java/kubatech/api/helpers/UUIDFinder.java | 43 + .../implementations/KubaTechGTMultiBlockBase.java | 341 +++++ src/main/java/kubatech/api/tea/TeaNetwork.java | 93 ++ .../tileentity/CustomTileEntityPacketHandler.java | 28 + src/main/java/kubatech/api/utils/ItemUtils.java | 26 + src/main/java/kubatech/api/utils/ModUtils.java | 38 + src/main/java/kubatech/api/utils/StringUtils.java | 52 + .../java/kubatech/client/effect/CropRenderer.java | 92 ++ .../kubatech/client/effect/EntityRenderer.java | 210 +++ .../client/effect/MegaApiaryBeesRenderer.java | 127 ++ src/main/java/kubatech/commands/CommandBees.java | 149 ++ src/main/java/kubatech/commands/CommandConfig.java | 103 ++ .../java/kubatech/commands/CommandHandler.java | 156 ++ src/main/java/kubatech/commands/CommandHelp.java | 86 ++ src/main/java/kubatech/commands/CommandTea.java | 142 ++ src/main/java/kubatech/config/Config.java | 102 ++ src/main/java/kubatech/kubatech.java | 210 +++ src/main/java/kubatech/loaders/BlockLoader.java | 51 + src/main/java/kubatech/loaders/DEFCRecipes.java | 329 +++++ src/main/java/kubatech/loaders/ItemLoader.java | 149 ++ src/main/java/kubatech/loaders/MTLoader.java | 44 + .../java/kubatech/loaders/MobHandlerLoader.java | 306 ++++ src/main/java/kubatech/loaders/RecipeLoader.java | 363 +++++ src/main/java/kubatech/loaders/TCLoader.java | 151 ++ .../loaders/block/defc/DEFCCasingBlock.java | 63 + .../loaders/block/defc/DEFCCasingItemBlock.java | 36 + .../loaders/block/kubablock/BlockProxy.java | 111 ++ .../block/kubablock/IProxyTileEntityProvider.java | 29 + .../loaders/block/kubablock/KubaBlock.java | 198 +++ .../loaders/block/kubablock/KubaItemBlock.java | 73 + .../block/kubablock/blocks/TeaAcceptor.java | 64 + .../loaders/block/kubablock/blocks/TeaStorage.java | 66 + .../java/kubatech/loaders/item/IItemProxyGUI.java | 31 + src/main/java/kubatech/loaders/item/ItemProxy.java | 122 ++ src/main/java/kubatech/loaders/item/KubaItems.java | 144 ++ src/main/java/kubatech/loaders/item/items/Tea.java | 72 + .../kubatech/loaders/item/items/TeaCollection.java | 209 +++ .../kubatech/loaders/item/items/TeaIngredient.java | 41 + .../kubatech/loaders/item/items/TeaUltimate.java | 216 +++ src/main/java/kubatech/mixin/Mixin.java | 50 + src/main/java/kubatech/mixin/MixinPlugin.java | 114 ++ .../java/kubatech/mixin/MixinsVariablesHelper.java | 6 + src/main/java/kubatech/mixin/TargetedMod.java | 43 + .../mixins/minecraft/LanguageRegistryMixin.java | 27 + .../mixin/mixins/minecraft/LocaleMixin.java | 47 + .../mixins/minecraft/StringTranslateMixin.java | 33 + .../mixin/mixins/minecraft/WorldMixin.java | 23 + src/main/java/kubatech/nei/IMCForNEI.java | 45 + src/main/java/kubatech/nei/NEI_Config.java | 69 + .../kubatech/network/CustomTileEntityPacket.java | 155 ++ .../java/kubatech/network/LoadConfigPacket.java | 52 + src/main/java/kubatech/savedata/PlayerData.java | 49 + .../java/kubatech/savedata/PlayerDataManager.java | 116 ++ src/main/java/kubatech/standalone.java | 16 + .../java/kubatech/tileentity/TeaAcceptorTile.java | 223 +++ .../java/kubatech/tileentity/TeaStorageTile.java | 83 ++ .../GT_MetaTileEntity_DEFusionCrafter.java | 281 ++++ .../GT_MetaTileEntity_ExtremeEntityCrusher.java | 822 +++++++++++ ...MetaTileEntity_ExtremeIndustrialGreenhouse.java | 1547 ++++++++++++++++++++ .../GT_MetaTileEntity_MegaIndustrialApiary.java | 1179 +++++++++++++++ src/main/resources/assets/kubatech/lang/de_DE.lang | 2 + src/main/resources/assets/kubatech/lang/en_US.lang | 132 ++ src/main/resources/assets/kubatech/lang/zh_CN.lang | 92 ++ .../assets/kubatech/textures/blocks/blank.png | Bin 0 -> 599 bytes .../kubatech/textures/blocks/casing/defc_0.png | Bin 0 -> 512 bytes .../kubatech/textures/blocks/casing/defc_1.png | Bin 0 -> 372 bytes .../kubatech/textures/blocks/casing/defc_2.png | Bin 0 -> 647 bytes .../kubatech/textures/blocks/casing/defc_3.png | Bin 0 -> 469 bytes .../kubatech/textures/blocks/casing/defc_4.png | Bin 0 -> 694 bytes .../kubatech/textures/blocks/casing/defc_5.png | Bin 0 -> 473 bytes .../kubatech/textures/blocks/tea_acceptor.png | Bin 0 -> 6837 bytes .../kubatech/textures/blocks/tea_storage.png | Bin 0 -> 935 bytes .../assets/kubatech/textures/gui/green_tea.png | Bin 0 -> 6557 bytes .../assets/kubatech/textures/gui/logo.jpg | Bin 0 -> 71447 bytes .../kubatech/textures/gui/logo_13x15_dark.png | Bin 0 -> 10194 bytes .../kubatech/textures/gui/slot/fusion_crafter.png | Bin 0 -> 2885 bytes .../kubatech/textures/gui/slot/gray_spawner.png | Bin 0 -> 3761 bytes .../kubatech/textures/gui/slot/gray_sword.png | Bin 0 -> 645 bytes .../assets/kubatech/textures/items/beeeeee.png | Bin 0 -> 689 bytes .../kubatech/textures/items/defc_schematic_t1.png | Bin 0 -> 2414 bytes .../kubatech/textures/items/defc_schematic_t2.png | Bin 0 -> 2657 bytes .../kubatech/textures/items/defc_schematic_t3.png | Bin 0 -> 2316 bytes .../kubatech/textures/items/defc_schematic_t4.png | Bin 0 -> 1961 bytes .../kubatech/textures/items/research_note.png | Bin 0 -> 9260 bytes .../textures/items/research_note.png.mcmeta | 5 + .../kubatech/textures/items/tea/black_tea.png | Bin 0 -> 7523 bytes .../textures/items/tea/black_tea.png.mcmeta | 5 + .../kubatech/textures/items/tea/butterfly_tea.png | Bin 0 -> 7476 bytes .../textures/items/tea/butterfly_tea.png.mcmeta | 5 + .../kubatech/textures/items/tea/earl_gray_tea.png | Bin 0 -> 7207 bytes .../textures/items/tea/earl_gray_tea.png.mcmeta | 5 + .../kubatech/textures/items/tea/green_tea.png | Bin 0 -> 8192 bytes .../textures/items/tea/green_tea.png.mcmeta | 5 + .../kubatech/textures/items/tea/lemon_tea.png | Bin 0 -> 7296 bytes .../textures/items/tea/lemon_tea.png.mcmeta | 5 + .../kubatech/textures/items/tea/milk_tea.png | Bin 0 -> 7276 bytes .../textures/items/tea/milk_tea.png.mcmeta | 5 + .../kubatech/textures/items/tea/oolong_tea.png | Bin 0 -> 7570 bytes .../textures/items/tea/oolong_tea.png.mcmeta | 5 + .../kubatech/textures/items/tea/peppermint_tea.png | Bin 0 -> 7987 bytes .../textures/items/tea/peppermint_tea.png.mcmeta | 5 + .../kubatech/textures/items/tea/pu-erh_tea.png | Bin 0 -> 7138 bytes .../textures/items/tea/pu-erh_tea.png.mcmeta | 5 + .../assets/kubatech/textures/items/tea/red_tea.png | Bin 0 -> 8237 bytes .../kubatech/textures/items/tea/red_tea.png.mcmeta | 5 + .../kubatech/textures/items/tea/ultimate_tea.png | Bin 0 -> 9523 bytes .../textures/items/tea/ultimate_tea.png.mcmeta | 5 + .../kubatech/textures/items/tea/white_tea.png | Bin 0 -> 7112 bytes .../textures/items/tea/white_tea.png.mcmeta | 5 + .../kubatech/textures/items/tea/yellow_tea.png | Bin 0 -> 7830 bytes .../textures/items/tea/yellow_tea.png.mcmeta | 5 + .../items/teaingredient/black_tea_leaf.png | Bin 0 -> 6821 bytes .../items/teaingredient/bruised_tea_leaf.png | Bin 0 -> 6911 bytes .../items/teaingredient/fermented_tea_leaf.png | Bin 0 -> 6924 bytes .../items/teaingredient/green_tea_leaf.png | Bin 0 -> 6910 bytes .../items/teaingredient/oolong_tea_leaf.png | Bin 0 -> 6773 bytes .../items/teaingredient/oxidized_tea_leaf.png | Bin 0 -> 6905 bytes .../teaingredient/partially_oxidized_tea_leaf.png | Bin 0 -> 6938 bytes .../items/teaingredient/pu-erh_tea_leaf.png | Bin 0 -> 6971 bytes .../items/teaingredient/rolled_tea_leaf.png | Bin 0 -> 6994 bytes .../items/teaingredient/steamed_tea_leaf.png | Bin 0 -> 6888 bytes .../items/teaingredient/tea_leaf_dehydrated.png | Bin 0 -> 6688 bytes .../items/teaingredient/white_tea_leaf.png | Bin 0 -> 6536 bytes .../items/teaingredient/yellow_tea_leaf.png | Bin 0 -> 6725 bytes src/main/resources/mixins.kubatech.json | 12 + 137 files changed, 11917 insertions(+) create mode 100644 src/functionalTest/java/kubatech/test/EIGTests.java create mode 100644 src/functionalTest/java/kubatech/test/kubatechTestMod.java create mode 100644 src/main/java/kubatech/ClientProxy.java create mode 100644 src/main/java/kubatech/CommonProxy.java create mode 100644 src/main/java/kubatech/FMLEventHandler.java create mode 100644 src/main/java/kubatech/Tags.java create mode 100644 src/main/java/kubatech/api/DynamicInventory.java create mode 100644 src/main/java/kubatech/api/LoaderReference.java create mode 100644 src/main/java/kubatech/api/Variables.java create mode 100644 src/main/java/kubatech/api/enums/ItemList.java create mode 100644 src/main/java/kubatech/api/helpers/GTHelper.java create mode 100644 src/main/java/kubatech/api/helpers/ReflectionHelper.java create mode 100644 src/main/java/kubatech/api/helpers/UUIDFinder.java create mode 100644 src/main/java/kubatech/api/implementations/KubaTechGTMultiBlockBase.java create mode 100644 src/main/java/kubatech/api/tea/TeaNetwork.java create mode 100644 src/main/java/kubatech/api/tileentity/CustomTileEntityPacketHandler.java create mode 100644 src/main/java/kubatech/api/utils/ItemUtils.java create mode 100644 src/main/java/kubatech/api/utils/ModUtils.java create mode 100644 src/main/java/kubatech/api/utils/StringUtils.java create mode 100644 src/main/java/kubatech/client/effect/CropRenderer.java create mode 100644 src/main/java/kubatech/client/effect/EntityRenderer.java create mode 100644 src/main/java/kubatech/client/effect/MegaApiaryBeesRenderer.java create mode 100644 src/main/java/kubatech/commands/CommandBees.java create mode 100644 src/main/java/kubatech/commands/CommandConfig.java create mode 100644 src/main/java/kubatech/commands/CommandHandler.java create mode 100644 src/main/java/kubatech/commands/CommandHelp.java create mode 100644 src/main/java/kubatech/commands/CommandTea.java create mode 100644 src/main/java/kubatech/config/Config.java create mode 100644 src/main/java/kubatech/kubatech.java create mode 100644 src/main/java/kubatech/loaders/BlockLoader.java create mode 100644 src/main/java/kubatech/loaders/DEFCRecipes.java create mode 100644 src/main/java/kubatech/loaders/ItemLoader.java create mode 100644 src/main/java/kubatech/loaders/MTLoader.java create mode 100644 src/main/java/kubatech/loaders/MobHandlerLoader.java create mode 100644 src/main/java/kubatech/loaders/RecipeLoader.java create mode 100644 src/main/java/kubatech/loaders/TCLoader.java create mode 100644 src/main/java/kubatech/loaders/block/defc/DEFCCasingBlock.java create mode 100644 src/main/java/kubatech/loaders/block/defc/DEFCCasingItemBlock.java create mode 100644 src/main/java/kubatech/loaders/block/kubablock/BlockProxy.java create mode 100644 src/main/java/kubatech/loaders/block/kubablock/IProxyTileEntityProvider.java create mode 100644 src/main/java/kubatech/loaders/block/kubablock/KubaBlock.java create mode 100644 src/main/java/kubatech/loaders/block/kubablock/KubaItemBlock.java create mode 100644 src/main/java/kubatech/loaders/block/kubablock/blocks/TeaAcceptor.java create mode 100644 src/main/java/kubatech/loaders/block/kubablock/blocks/TeaStorage.java create mode 100644 src/main/java/kubatech/loaders/item/IItemProxyGUI.java create mode 100644 src/main/java/kubatech/loaders/item/ItemProxy.java create mode 100644 src/main/java/kubatech/loaders/item/KubaItems.java create mode 100644 src/main/java/kubatech/loaders/item/items/Tea.java create mode 100644 src/main/java/kubatech/loaders/item/items/TeaCollection.java create mode 100644 src/main/java/kubatech/loaders/item/items/TeaIngredient.java create mode 100644 src/main/java/kubatech/loaders/item/items/TeaUltimate.java create mode 100644 src/main/java/kubatech/mixin/Mixin.java create mode 100644 src/main/java/kubatech/mixin/MixinPlugin.java create mode 100644 src/main/java/kubatech/mixin/MixinsVariablesHelper.java create mode 100644 src/main/java/kubatech/mixin/TargetedMod.java create mode 100644 src/main/java/kubatech/mixin/mixins/minecraft/LanguageRegistryMixin.java create mode 100644 src/main/java/kubatech/mixin/mixins/minecraft/LocaleMixin.java create mode 100644 src/main/java/kubatech/mixin/mixins/minecraft/StringTranslateMixin.java create mode 100644 src/main/java/kubatech/mixin/mixins/minecraft/WorldMixin.java create mode 100644 src/main/java/kubatech/nei/IMCForNEI.java create mode 100644 src/main/java/kubatech/nei/NEI_Config.java create mode 100644 src/main/java/kubatech/network/CustomTileEntityPacket.java create mode 100644 src/main/java/kubatech/network/LoadConfigPacket.java create mode 100644 src/main/java/kubatech/savedata/PlayerData.java create mode 100644 src/main/java/kubatech/savedata/PlayerDataManager.java create mode 100644 src/main/java/kubatech/standalone.java create mode 100644 src/main/java/kubatech/tileentity/TeaAcceptorTile.java create mode 100644 src/main/java/kubatech/tileentity/TeaStorageTile.java create mode 100644 src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_DEFusionCrafter.java create mode 100644 src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_ExtremeEntityCrusher.java create mode 100644 src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_ExtremeIndustrialGreenhouse.java create mode 100644 src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_MegaIndustrialApiary.java create mode 100644 src/main/resources/assets/kubatech/lang/de_DE.lang create mode 100644 src/main/resources/assets/kubatech/lang/en_US.lang create mode 100644 src/main/resources/assets/kubatech/lang/zh_CN.lang create mode 100644 src/main/resources/assets/kubatech/textures/blocks/blank.png create mode 100644 src/main/resources/assets/kubatech/textures/blocks/casing/defc_0.png create mode 100644 src/main/resources/assets/kubatech/textures/blocks/casing/defc_1.png create mode 100644 src/main/resources/assets/kubatech/textures/blocks/casing/defc_2.png create mode 100644 src/main/resources/assets/kubatech/textures/blocks/casing/defc_3.png create mode 100644 src/main/resources/assets/kubatech/textures/blocks/casing/defc_4.png create mode 100644 src/main/resources/assets/kubatech/textures/blocks/casing/defc_5.png create mode 100644 src/main/resources/assets/kubatech/textures/blocks/tea_acceptor.png create mode 100644 src/main/resources/assets/kubatech/textures/blocks/tea_storage.png create mode 100644 src/main/resources/assets/kubatech/textures/gui/green_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/gui/logo.jpg create mode 100644 src/main/resources/assets/kubatech/textures/gui/logo_13x15_dark.png create mode 100644 src/main/resources/assets/kubatech/textures/gui/slot/fusion_crafter.png create mode 100644 src/main/resources/assets/kubatech/textures/gui/slot/gray_spawner.png create mode 100644 src/main/resources/assets/kubatech/textures/gui/slot/gray_sword.png create mode 100644 src/main/resources/assets/kubatech/textures/items/beeeeee.png create mode 100644 src/main/resources/assets/kubatech/textures/items/defc_schematic_t1.png create mode 100644 src/main/resources/assets/kubatech/textures/items/defc_schematic_t2.png create mode 100644 src/main/resources/assets/kubatech/textures/items/defc_schematic_t3.png create mode 100644 src/main/resources/assets/kubatech/textures/items/defc_schematic_t4.png create mode 100644 src/main/resources/assets/kubatech/textures/items/research_note.png create mode 100644 src/main/resources/assets/kubatech/textures/items/research_note.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/black_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/black_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/butterfly_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/butterfly_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/earl_gray_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/earl_gray_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/green_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/green_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/lemon_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/lemon_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/milk_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/milk_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/oolong_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/oolong_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/peppermint_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/peppermint_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/pu-erh_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/pu-erh_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/red_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/red_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/ultimate_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/ultimate_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/white_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/white_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/yellow_tea.png create mode 100644 src/main/resources/assets/kubatech/textures/items/tea/yellow_tea.png.mcmeta create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/black_tea_leaf.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/bruised_tea_leaf.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/fermented_tea_leaf.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/green_tea_leaf.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/oolong_tea_leaf.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/oxidized_tea_leaf.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/partially_oxidized_tea_leaf.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/pu-erh_tea_leaf.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/rolled_tea_leaf.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/steamed_tea_leaf.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/tea_leaf_dehydrated.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/white_tea_leaf.png create mode 100644 src/main/resources/assets/kubatech/textures/items/teaingredient/yellow_tea_leaf.png create mode 100644 src/main/resources/mixins.kubatech.json (limited to 'src') diff --git a/src/functionalTest/java/kubatech/test/EIGTests.java b/src/functionalTest/java/kubatech/test/EIGTests.java new file mode 100644 index 0000000000..1bb88814a4 --- /dev/null +++ b/src/functionalTest/java/kubatech/test/EIGTests.java @@ -0,0 +1,342 @@ +/* + * spotless:off + * KubaTech - Gregtech Addon + * Copyright (C) 2022 - 2024 kuba6000 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * spotless:on + */ + +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 java.io.File; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Map; + +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +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; +import net.minecraft.world.WorldProviderSurface; +import net.minecraft.world.WorldServer; +import net.minecraft.world.WorldSettings; +import net.minecraft.world.WorldType; +import net.minecraft.world.chunk.storage.IChunkLoader; +import net.minecraft.world.storage.IPlayerFileData; +import net.minecraft.world.storage.ISaveHandler; +import net.minecraft.world.storage.WorldInfo; +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; +import ic2.api.crops.CropCard; +import ic2.api.crops.Crops; +import ic2.core.Ic2Items; +import ic2.core.crop.TileEntityCrop; +import kubatech.tileentity.gregtech.multiblock.GT_MetaTileEntity_ExtremeIndustrialGreenhouse; + +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; + + static World myWorld; + + public EIGTests() { + if (!DimensionManager.isDimensionRegistered(256)) { + DimensionManager.registerProviderType(256, WorldProviderSurface.class, false); + DimensionManager.registerDimension(256, 256); + } + if (myWorld == null) { + myWorld = new WorldServer(MinecraftServer.getServer(), new ISaveHandler() { + + @Override + public WorldInfo loadWorldInfo() { + return null; + } + + @Override + public void checkSessionLock() throws MinecraftException { + + } + + @Override + public IChunkLoader getChunkLoader(WorldProvider p_75763_1_) { + return null; + } + + @Override + public void saveWorldInfoWithPlayer(WorldInfo p_75755_1_, NBTTagCompound p_75755_2_) { + + } + + @Override + public void saveWorldInfo(WorldInfo p_75761_1_) { + + } + + @Override + public IPlayerFileData getSaveHandler() { + return null; + } + + @Override + public void flush() { + + } + + @Override + public File getWorldDirectory() { + return null; + } + + @Override + public File getMapFileFromName(String p_75758_1_) { + return null; + } + + @Override + public String getWorldDirectoryName() { + return "dummy"; + } + }, + "DummyTestWorld", + 256, + new WorldSettings(256, WorldSettings.GameType.SURVIVAL, false, false, WorldType.DEFAULT), + MinecraftServer.getServer().theProfiler) { + + @Override + public File getChunkSaveLocation() { + return new File("ignoreme"); + } + + @Override + public int getBlockLightValue(int p_72957_1_, int p_72957_2_, int p_72957_3_) { + return 4; + } + }; + } + } + + private static int leftOverTicksFromRealRun = 0; + + ItemStackMap 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 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); + } + } + } + leftOverTicksFromRealRun += i - lastHarvestedAt; + } + + return expected; + } + + ItemStackMap getEIGDrops(GT_MetaTileEntity_ExtremeIndustrialGreenhouse EIG, ItemStack stack) { + ItemStackMap 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); + } + } + } + } + + 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"); + 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(); + } + + GT_Item_Machines itemMachines = (GT_Item_Machines) Item.getItemFromBlock(GregTech_API.sBlockMachines); + itemMachines.placeBlockAt( + new ItemStack(itemMachines, 1, EIG_CONTROLLER_METADATA), + null, + myWorld, + 0, + 81, + 0, + 2, + 0, + 0, + 0, + EIG_CONTROLLER_METADATA); + IGregTechTileEntity te = (IGregTechTileEntity) myWorld.getTileEntity(0, 81, 0); + GT_MetaTileEntity_ExtremeIndustrialGreenhouse EIG = (GT_MetaTileEntity_ExtremeIndustrialGreenhouse) te + .getMetaTileEntity(); + + int[] abc = new int[] { 0, -2, 3 }; + int[] xyz = new int[] { 0, 0, 0 }; + EIG.getExtendedFacing() + .getWorldOffset(abc, xyz); + xyz[0] += te.getXCoord(); + xyz[1] += te.getYCoord(); + xyz[2] += te.getZCoord(); + + myWorld.setBlock(xyz[0], xyz[1] - 2, xyz[2], GregTech_API.sBlockCasings4, 1, 0); + myWorld.setBlock(xyz[0], xyz[1] - 1, xyz[2], Blocks.farmland, 0, 0); + + 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 expected = getRealDrops(cropTile, cc, 10, 10, 10); + ItemStackMap generated = getEIGDrops(EIG, ccStack); + + // MinecraftServer.getServer() + // .addChatMessage(new ChatComponentText("[TEST" + i + "]Real crop drops:")); + // for (Map.Entry 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 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(); + } + + int expectedValue = expected.getOrDefault(stackToTest, 0); + int generatedValue = generated.getOrDefault(stackToTest, 0); + + x[i] = expectedValue; + y[i] = generatedValue; + } + + 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); + } + fail(); + + } + +} diff --git a/src/functionalTest/java/kubatech/test/kubatechTestMod.java b/src/functionalTest/java/kubatech/test/kubatechTestMod.java new file mode 100644 index 0000000000..bc68d3f203 --- /dev/null +++ b/src/functionalTest/java/kubatech/test/kubatechTestMod.java @@ -0,0 +1,101 @@ +package kubatech.test; + +import java.io.File; +import java.io.PrintWriter; +import java.nio.file.FileSystems; +import java.nio.file.Path; + +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentText; + +import org.apache.commons.io.output.CloseShieldOutputStream; +import org.junit.platform.engine.discovery.DiscoverySelectors; +import org.junit.platform.launcher.Launcher; +import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.LauncherSession; +import org.junit.platform.launcher.TestPlan; +import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; +import org.junit.platform.launcher.core.LauncherFactory; +import org.junit.platform.launcher.listeners.SummaryGeneratingListener; +import org.junit.platform.launcher.listeners.TestExecutionSummary; +import org.junit.platform.reporting.legacy.xml.LegacyXmlReportGeneratingListener; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.Mod; +import cpw.mods.fml.common.Mod.EventHandler; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.event.FMLServerStartedEvent; +import gregtech.GT_Mod; + +@Mod( + modid = "kubatech-tests", + name = "KubaTech Dev Tests", + version = "1.0", + dependencies = "required-after:kubatech;required-after:gregtech;after:berriespp;") +public class kubatechTestMod { + + @EventHandler + public void preInit(FMLPreInitializationEvent ev) { + // Disable GT5u messing with vanilla recipes for unit tests + GT_Mod.gregtechproxy.mNerfedWoodPlank = false; + GT_Mod.gregtechproxy.mNerfedVanillaTools = false; + } + + @EventHandler + public void onServerStarted(FMLServerStartedEvent startedEv) { + MinecraftServer.getServer() + .addChatMessage(new ChatComponentText("Running KT unit tests...")); + runTests(); + MinecraftServer.getServer() + .addChatMessage(new ChatComponentText("Running KT unit tests finished")); + } + + public void runTests() { + // https://junit.org/junit5/docs/current/user-guide/#launcher-api + System.setProperty("junit.platform.reporting.open.xml.enabled", "false"); + final Path testsXmlOutDir = FileSystems.getDefault() + .getPath("./junit-out/") + .toAbsolutePath(); + final File testsXmlOutDirFile = testsXmlOutDir.toFile(); + testsXmlOutDirFile.mkdirs(); + { + File[] fileList = testsXmlOutDirFile.listFiles(); + if (fileList != null) { + for (File child : fileList) { + if (child.isFile() && child.getName() + .endsWith(".xml")) { + child.delete(); + } + } + } + } + final LauncherDiscoveryRequest discovery = LauncherDiscoveryRequestBuilder.request() + .selectors(DiscoverySelectors.selectPackage("kubatech.test")) + .build(); + final SummaryGeneratingListener summaryGenerator = new SummaryGeneratingListener(); + final TestExecutionSummary summary; + try (PrintWriter stderrWriter = new PrintWriter(new CloseShieldOutputStream(System.err), true)) { + final LegacyXmlReportGeneratingListener xmlGenerator = new LegacyXmlReportGeneratingListener( + testsXmlOutDir, + stderrWriter); + try (LauncherSession session = LauncherFactory.openSession()) { + final Launcher launcher = session.getLauncher(); + final TestPlan plan = launcher.discover(discovery); + launcher.registerTestExecutionListeners(summaryGenerator, xmlGenerator); + launcher.execute(plan); + } + summary = summaryGenerator.getSummary(); + + summary.printFailuresTo(stderrWriter, 32); + summary.printTo(stderrWriter); + stderrWriter.flush(); + } + // Throw an exception if running via `runServer` + if (summary.getTotalFailureCount() > 0 && FMLCommonHandler.instance() + .getSide() + .isServer()) { + throw new RuntimeException("Some of the unit tests failed to execute, check the log for details"); + } + } + +} diff --git a/src/main/java/kubatech/ClientProxy.java b/src/main/java/kubatech/ClientProxy.java new file mode 100644 index 0000000000..d9b1f5cf17 --- /dev/null +++ b/src/main/java/kubatech/ClientProxy.java @@ -0,0 +1,75 @@ +/* + * spotless:off + * KubaTech - Gregtech Addon + * Copyright (C) 2022 - 2024 kuba6000 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * spotless:on + */ + +package kubatech; + +import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLLoadCompleteEvent; +import cpw.mods.fml.common.event.FMLPostInitializationEvent; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.event.FMLServerAboutToStartEvent; +import cpw.mods.fml.common.event.FMLServerStartedEvent; +import cpw.mods.fml.common.event.FMLServerStartingEvent; +import cpw.mods.fml.common.event.FMLServerStoppedEvent; +import cpw.mods.fml.common.event.FMLServerStoppingEvent; +import kubatech.api.utils.ModUtils; +import kubatech.nei.IMCForNEI; + +@SuppressWarnings("unused") +public class ClientProxy extends CommonProxy { + + public void preInit(FMLPreInitializationEvent event) { + ModUtils.isClientSided = true; + super.preInit(event); + } + + public void init(FMLInitializationEvent event) { + super.init(event); + IMCForNEI.IMCSender(); + } + + public void postInit(FMLPostInitializationEvent event) { + super.postInit(event); + } + + public void serverAboutToStart(FMLServerAboutToStartEvent event) { + super.serverAboutToStart(event); + } + + public void serverStarting(FMLServerStartingEvent event) { + super.serverStarting(event); + } + + public void serverStarted(FMLServerStartedEvent event) { + super.serverStarted(event); + } + + public void serverStopping(FMLServerStoppingEvent event) { + super.serverStopping(event); + } + + public void serverStopped(FMLServerStoppedEvent event) { + super.serverStopped(event); + } + + public void loadComplete(FMLLoadCompleteEvent event) { + super.loadComplete(event); + } +} diff --git a/src/main/java/kubatech/CommonProxy.java b/src/main/java/kubatech/CommonProxy.java new file mode 100644 index 0000000000..39d6b224d5 --- /dev/null +++ b/src/main/java/kubatech/CommonProxy.java @@ -0,0 +1,87 @@ +/* + * spotless:off + * KubaTech - Gregtech Addon + * Copyright (C) 2022 - 2024 kuba6000 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * spotless:on + */ + +package kubatech; + +import static kubatech.loaders.BlockLoader.registerBlocks; +import static kubatech.loaders.ItemLoader.registerItems; + +import net.minecraftforge.common.MinecraftForge; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLLoadCompleteEvent; +import cpw.mods.fml.common.event.FMLPostInitializationEvent; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.event.FMLServerAboutToStartEvent; +import cpw.mods.fml.common.event.FMLServerStartedEvent; +import cpw.mods.fml.common.event.FMLServerStartingEvent; +import cpw.mods.fml.common.event.FMLServerStoppedEvent; +import cpw.mods.fml.common.event.FMLServerStoppingEvent; +import kubatech.api.LoaderReference; +import kubatech.commands.CommandHandler; +import kubatech.config.Config; +import kubatech.loaders.MTLoader; +import kubatech.loaders.MobHandlerLoader; +import kubatech.loaders.RecipeLoader; +import kubatech.loaders.TCLoader; +import kubatech.savedata.PlayerDataManager; + +public class CommonProxy { + + public void preInit(FMLPreInitializationEvent event) { + kubatech.info("Initializing ! Version: " + Tags.VERSION); + + Config.init(event.getModConfigurationDirectory()); + Config.synchronizeConfiguration(); + FMLCommonHandler.instance() + .bus() + .register(new FMLEventHandler()); + MinecraftForge.EVENT_BUS.register(new PlayerDataManager()); + registerItems(); + registerBlocks(); + MobHandlerLoader.init(); + } + + public void init(FMLInitializationEvent event) { + if (LoaderReference.MineTweaker) MTLoader.init(); + } + + public void postInit(FMLPostInitializationEvent event) { + RecipeLoader.addRecipes(); + if (LoaderReference.Thaumcraft) TCLoader.init(); + } + + public void serverAboutToStart(FMLServerAboutToStartEvent event) {} + + public void serverStarting(FMLServerStartingEvent event) { + RecipeLoader.addRecipesLate(); + CommandHandler cmd = new CommandHandler(); + event.registerServerCommand(cmd); + } + + public void serverStarted(FMLServerStartedEvent event) {} + + public void serverStopping(FMLServerStoppingEvent event) {} + + public void serverStopped(FMLServerStoppedEvent event) {} + + public void loadComplete(FMLLoadCompleteEvent event) {} +} diff --git a/src/main/java/kubatech/FMLEventHandler.java b/src/main/java/kubatech/FMLEventHandler.java new file mode 100644 index 0000000000..02e9bb19a7 --- /dev/null +++ b/src/main/java/kubatech/FMLEventHandler.java @@ -0,0 +1,42 @@ +/* + * spotless:off + * KubaTech - Gregtech Addon + * Copyright (C) 2022 - 2024 kuba6000 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * spotless:on + */ + +package kubatech; + +import net.minecraft.entity.player.EntityPlayerMP; + +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent; +import kubatech.api.helpers.UUIDFinder; +import kubatech.network.LoadConfigPacket; +import kubatech.savedata.PlayerDataManager; + +public class FMLEventHandler { + + // Gets fired only server-sided + @SubscribeEvent + public void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) { + if (!(event.player instanceof EntityPlayerMP)) return; + UUIDFinder.updateMapping(event.player.getCommandSenderName(), event.player.getPersistentID()); + PlayerDataManager.initializePlayer((EntityPlayerMP) event.player); + kubatech.info("Sending config to " + event.player.getDisplayName()); + kubatech.NETWORK.sendTo(LoadConfigPacket.instance, (EntityPlayerMP) event.player); + } +} diff --git a/src/main/java/kubatech/Tags.java b/src/main/java/kubatech/Tags.java new file mode 100644 index 0000000000..0be971ae91 --- /dev/null +++ b/src/main/java/kubatech/Tags.java @@ -0,0 +1,31 @@ +/* + * spotless:off + * KubaTech - Gregtech Addon + * Copyright (C) 2022 - 2024 kuba6000 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * spotless:on + */ + +package kubatech; + +// Use this class for Strings only. Do not import any classes here. It will lead to issues with Mixins if in use! + +public class Tags { + + // GRADLETOKEN_* will be replaced by your configuration values at build time + public static final String MODID = "kubatech"; + public static final String MODNAME = "KubaTech"; + public static final String VERSION = "GRADLETOKEN_VERSION"; +} diff --git a/src/main/java/kubatech/api/DynamicInventory.java b/src/main/java/kubatech/api/DynamicInventory.java new file mode 100644 index 0000000000..ef89c3a341 --- /dev/null +++ b/src/main/java/kubatech/api/DynamicInventory.java @@ -0,0 +1,469 @@ +package kubatech.api; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +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.Text; +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.helpers.GTHelper; +import kubatech.api.utils.ModUtils; + +public class DynamicInventory { + + int width, height; + Supplier slotsGetter; + private int slots = 0; + private int usedSlots = 0; + List inventory; + TInventoryGetter inventoryGetter; + TInventoryInjector inventoryInjector = null; + TInventoryExtractor inventoryExtractor = null; + TInventoryReplacerOrMerger inventoryReplacer = null; + Supplier isEnabledGetter = null; + boolean isEnabled = true; + + public DynamicInventory(int width, int height, Supplier slotsGetter, List inventory, + TInventoryGetter inventoryGetter) { + this.width = width; + this.height = height; + this.slotsGetter = slotsGetter; + this.inventory = inventory; + this.inventoryGetter = inventoryGetter; + } + + public DynamicInventory allowInventoryInjection(TInventoryInjector inventoryInjector) { + this.inventoryInjector = inventoryInjector; + return this; + } + + public DynamicInventory allowInventoryExtraction(TInventoryExtractor inventoryExtractor) { + this.inventoryExtractor = inventoryExtractor; + return this; + } + + public DynamicInventory allowInventoryReplace(TInventoryReplacerOrMerger inventoryReplacer) { + this.inventoryReplacer = inventoryReplacer; + return this; + } + + public DynamicInventory setEnabled(Supplier 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.attachSyncer(new FakeSyncWidget.IntegerSyncer(() -> { + if (slots != slotsGetter.get()) { + slots = slotsGetter.get(); + container.notifyChangeNoSync(); + } + return slots; + }, i -> { + if (slots != i) { + slots = i; + container.notifyChangeNoSync(); + } + }), builder) + .attachSyncer(new FakeSyncWidget.IntegerSyncer(() -> { + if (usedSlots != inventory.size()) { + usedSlots = inventory.size(); + container.notifyChangeNoSync(); + } + return usedSlots; + }, i -> { + if (usedSlots != i) { + usedSlots = i; + container.notifyChangeNoSync(); + } + }), builder) + .attachSyncer(new FakeSyncWidget.ListSyncer<>(() -> { + HashMap itemMap = new HashMap<>(); + HashMap stackMap = new HashMap<>(); + HashMap> realSlotMap = new HashMap<>(); + for (int i = 0, mStorageSize = inventory.size(); i < mStorageSize; i++) { + ItemStack stack = inventoryGetter.get(inventory.get(i)); + ItemID id = ItemID.createNoCopy(stack, false); + itemMap.merge(id, 1, Integer::sum); + stackMap.putIfAbsent(id, stack); + realSlotMap.computeIfAbsent(id, unused -> new ArrayList<>()) + .add(i); + } + List newDrawables = new ArrayList<>(); + for (Map.Entry entry : itemMap.entrySet()) { + newDrawables.add( + new GTHelper.StackableItemSlot( + entry.getValue(), + stackMap.get(entry.getKey()), + realSlotMap.get(entry.getKey()))); + } + 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 drawables = new ArrayList<>(); + + private Widget createWidget(EntityPlayer player) { + Scrollable dynamicInventoryWidget = new Scrollable().setVerticalScroll(); + + ArrayList buttons = new ArrayList<>(); + + if (!ModUtils.isClientThreaded()) { + HashMap itemMap = new HashMap<>(); + HashMap stackMap = new HashMap<>(); + HashMap> realSlotMap = new HashMap<>(); + for (int i = 0, inventorySize = inventory.size(); i < inventorySize; i++) { + ItemStack stack = inventoryGetter.get(inventory.get(i)); + ItemID id = ItemID.createNoCopy(stack, false); + itemMap.merge(id, 1, Integer::sum); + stackMap.putIfAbsent(id, stack); + realSlotMap.computeIfAbsent(id, unused -> new ArrayList<>()) + .add(i); + } + drawables = new ArrayList<>(); + for (Map.Entry entry : itemMap.entrySet()) { + drawables.add( + new GTHelper.StackableItemSlot( + entry.getValue(), + stackMap.get(entry.getKey()), + realSlotMap.get(entry.getKey()))); + } + } + + 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 removed = inventoryExtractor.extract(realID); + if (removed != null) { + ItemStack stack = inventoryGetter.get(removed); + if (player.inventory.addItemStackToInventory(stack)) + player.inventoryContainer.detectAndSendChanges(); + else player.entityDropItem(stack, 0.f); + return; + } + } else { + ItemStack input = player.inventory.getItemStack(); + if (input != null) { + if (drawables.size() > finalID) { + if (inventoryReplacer == null) return; + int realID = drawables.get(finalID).realSlots.get(0); + ItemStack removed = inventoryReplacer.replaceOrMerge(realID, input); + if (removed == null) return; + player.inventory.setItemStack(removed.stackSize == 0 ? null : removed); + } else { + if (inventoryInjector == null) return; + if (clickData.mouseButton == 1) { + ItemStack copy = input.copy(); + copy.stackSize = 1; + ItemStack leftover = inventoryInjector.inject(copy); + if (leftover == null) return; + input.stackSize--; + if (input.stackSize > 0) { + ((EntityPlayerMP) player).isChangingQuantityOnly = true; + ((EntityPlayerMP) player).updateHeldItem(); + return; + } else player.inventory.setItemStack(null); + } else { + ItemStack leftover = inventoryInjector.inject(input); + if (leftover == null) return; + if (input.stackSize > 0) { + ((EntityPlayerMP) player).isChangingQuantityOnly = true; + ((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 removed = inventoryExtractor.extract(realID); + if (removed != null) { + ItemStack stack = inventoryGetter.get(removed); + player.inventory.setItemStack(stack); + ((EntityPlayerMP) player).isChangingQuantityOnly = false; + ((EntityPlayerMP) player).updateHeldItem(); + return; + } + } + } + }) + .setBackground( + () -> new IDrawable[] { getItemSlot(), + new ItemDrawable(drawables.size() > finalID ? drawables.get(finalID).stack : null) + .withFixedSize(16, 16, 1, 1), + new Text( + (drawables.size() > finalID && drawables.get(finalID).count > 1) + ? (drawables.get(finalID).count > 99 ? "+99" + : String.valueOf(drawables.get(finalID).count)) + : "").color(Color.WHITE.normal) + .alignment(Alignment.TopLeft) + .withOffset(1, 1), + new Text( + (drawables.size() > finalID && drawables.get(finalID).stack.stackSize > 1) + ? String.valueOf(drawables.get(finalID).stack.stackSize) + : "").color(Color.WHITE.normal) + .shadow() + .alignment(Alignment.BottomRight) }) + .dynamicTooltip(() -> { + if (drawables.size() > finalID) { + List tip = new ArrayList<>( + Collections.singletonList(drawables.get(finalID).stack.getDisplayName())); + if (drawables.get(finalID).count > 1) tip.add( + EnumChatFormatting.DARK_PURPLE + "There are " + + drawables.get(finalID).count + + " identical slots"); + return tip; + } + return Collections.emptyList(); + }) +