From 77ed2e04876c133c8d09ac42ef8a46922c9bd6a2 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sun, 10 Mar 2024 17:23:35 -0500 Subject: [PATCH 01/25] Fix server crashes with alarms (#2411) --- .../electric/MetaTileEntityAlarm.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAlarm.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAlarm.java index cadf9768286..67751f893e9 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAlarm.java +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAlarm.java @@ -76,15 +76,17 @@ protected ModularUI createUI(EntityPlayer entityPlayer) { return ModularUI.builder(GuiTextures.BACKGROUND, 240, 86) .widget(new LabelWidget(10, 5, getMetaFullName())) .widget(new SelectorWidget(10, 20, 220, 20, - getSounds().stream().map((event) -> event.getSoundName().toString()) + getSounds().stream().map(this::getNameOfSound) .collect(Collectors.toList()), - 0x555555, () -> this.selectedSound.getSoundName().toString(), true).setOnChanged((v) -> { - GregTechAPI.soundManager.stopTileSound(getPos()); + 0x555555, () -> getNameOfSound(this.selectedSound), true).setOnChanged((v) -> { + if (this.getWorld().isRemote) + GregTechAPI.soundManager.stopTileSound(getPos()); SoundEvent newSound = SoundEvent.REGISTRY.getObject(new ResourceLocation(v)); if (this.selectedSound != newSound) { this.selectedSound = SoundEvent.REGISTRY.getObject(new ResourceLocation(v)); this.writeCustomData(GregtechDataCodes.UPDATE_SOUND, - (writer) -> writer.writeResourceLocation(this.selectedSound.getSoundName())); + (writer) -> writer + .writeResourceLocation(getResourceLocationOfSound(this.selectedSound))); } })) .widget(new ImageWidget(10, 54, 220, 20, GuiTextures.DISPLAY)) @@ -168,14 +170,14 @@ public void receiveInitialSyncData(PacketBuffer buf) { public void writeInitialSyncData(PacketBuffer buf) { super.writeInitialSyncData(buf); buf.writeBoolean(this.isActive); - buf.writeResourceLocation(this.selectedSound.getSoundName()); + buf.writeResourceLocation(getResourceLocationOfSound(this.selectedSound)); buf.writeInt(this.radius); } @Override public NBTTagCompound writeToNBT(NBTTagCompound data) { data.setBoolean("isActive", this.isActive); - data.setString("selectedSound", this.selectedSound.getSoundName().toString()); + data.setString("selectedSound", getNameOfSound(this.selectedSound)); data.setInteger("radius", this.radius); return super.writeToNBT(data); } @@ -187,4 +189,12 @@ public void readFromNBT(NBTTagCompound data) { this.radius = data.getInteger("radius"); super.readFromNBT(data); } + + public String getNameOfSound(SoundEvent sound) { + return getResourceLocationOfSound(sound).toString(); + } + + public ResourceLocation getResourceLocationOfSound(SoundEvent sound) { + return SoundEvent.REGISTRY.getNameForObject(sound); + } } From e85169eb34a849d1b56514d4b090cda9080b5bfe Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:21:43 -0400 Subject: [PATCH 02/25] fix pipe capability retrieval logic (#2415) --- .../api/pipenet/tile/TileEntityPipeBase.java | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 84897a022e8..7d4fc9015ef 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -335,24 +335,28 @@ public T getCapabilityInternal(Capability capability, @Nullable EnumFacin @Nullable @Override public final T getCapability(@NotNull Capability capability, @Nullable EnumFacing facing) { - boolean isCoverable = capability == GregtechTileCapabilities.CAPABILITY_COVER_HOLDER; - Cover cover = facing == null ? null : coverableImplementation.getCoverAtSide(facing); - T defaultValue; - if (getPipeBlock() == null) - defaultValue = null; - else - defaultValue = getCapabilityInternal(capability, facing); + T pipeCapability = getPipeBlock() == null ? null : getCapabilityInternal(capability, facing); - if (isCoverable) { - return defaultValue; + if (capability == GregtechTileCapabilities.CAPABILITY_COVER_HOLDER) { + return pipeCapability; } - if (cover == null && facing != null) { - return isConnected(facing) ? defaultValue : null; + + Cover cover = facing == null ? null : coverableImplementation.getCoverAtSide(facing); + if (cover == null) { + if (facing == null || isConnected(facing)) { + return pipeCapability; + } + return null; } - if (cover != null) { - return cover.getCapability(capability, defaultValue); + + T coverCapability = cover.getCapability(capability, pipeCapability); + if (coverCapability == pipeCapability) { + if (isConnected(facing)) { + return pipeCapability; + } + return null; } - return defaultValue; + return coverCapability; } @Override From fea6440e9852c1e44a88332b568981d2d19c3b7b Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:21:58 -0400 Subject: [PATCH 03/25] fix solar panels not outputting to cables (#2416) --- src/main/java/gregtech/common/covers/CoverSolarPanel.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/gregtech/common/covers/CoverSolarPanel.java b/src/main/java/gregtech/common/covers/CoverSolarPanel.java index 7e2e750439a..e972ef560ad 100644 --- a/src/main/java/gregtech/common/covers/CoverSolarPanel.java +++ b/src/main/java/gregtech/common/covers/CoverSolarPanel.java @@ -13,7 +13,6 @@ import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.ITickable; -import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -50,10 +49,9 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra public void update() { CoverableView coverable = getCoverableView(); World world = coverable.getWorld(); - BlockPos blockPos = coverable.getPos(); - if (GTUtility.canSeeSunClearly(world, blockPos)) { + if (GTUtility.canSeeSunClearly(world, coverable.getPos())) { IEnergyContainer energyContainer = coverable.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, - null); + getAttachedSide()); if (energyContainer != null) { energyContainer.acceptEnergyFromNetwork(null, EUt, 1); } From dc389f8f66475dd741ac96138f926e7f94cb0f70 Mon Sep 17 00:00:00 2001 From: brachy84 <45517902+brachy84@users.noreply.github.com> Date: Sun, 17 Mar 2024 17:12:12 +0100 Subject: [PATCH 04/25] Update GroovyScript & improve material API for groovy (#2389) --- dependencies.gradle | 2 +- .../material/properties/BlastProperty.java | 14 +++-- .../material/CTMaterialHelpers.java | 5 +- .../integration/groovy/GroovyExpansions.java | 42 ++++++++++++++ .../GroovyMaterialBuilderExpansion.java | 36 ++++++++---- .../groovy/GroovyRecipeBuilderExpansion.java | 16 ----- .../groovy/GroovyScriptModule.java | 58 ++++++++++++++++++- 7 files changed, 136 insertions(+), 37 deletions(-) create mode 100644 src/main/java/gregtech/integration/groovy/GroovyExpansions.java delete mode 100644 src/main/java/gregtech/integration/groovy/GroovyRecipeBuilderExpansion.java diff --git a/dependencies.gradle b/dependencies.gradle index 7f2d35d408a..445b5e3963b 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -41,7 +41,7 @@ dependencies { // Published dependencies api("codechicken:codechickenlib:3.2.3.358") api("com.cleanroommc:modularui:2.4.1") { transitive = false } - api("com.cleanroommc:groovyscript:0.7.3") { transitive = false } + api("com.cleanroommc:groovyscript:0.8.0") { transitive = false } api("CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.684") api rfg.deobf("curse.maven:ae2-extended-life-570458:4402048") // AE2UEL 0.55.6 api rfg.deobf("curse.maven:ctm-267602:2915363") // CTM 1.0.2.31 diff --git a/src/main/java/gregtech/api/unification/material/properties/BlastProperty.java b/src/main/java/gregtech/api/unification/material/properties/BlastProperty.java index 172e0981ac7..61670ea18f9 100644 --- a/src/main/java/gregtech/api/unification/material/properties/BlastProperty.java +++ b/src/main/java/gregtech/api/unification/material/properties/BlastProperty.java @@ -1,17 +1,18 @@ package gregtech.api.unification.material.properties; +import gregtech.integration.groovy.GroovyScriptModule; + import crafttweaker.CraftTweakerAPI; import org.jetbrains.annotations.NotNull; public class BlastProperty implements IMaterialProperty { /** - * Blast Furnace Temperature of this Material. - * If below 1000K, Primitive Blast Furnace recipes will be also added. + * Blast Furnace Temperature of this Material. If below 1000K, Primitive Blast Furnace recipes will be also added. * If above 1750K, a Hot Ingot and its Vacuum Freezer recipe will be also added. *

- * If a Material with this Property has a Fluid, its temperature - * will be set to this if it is the default Fluid temperature. + * If a Material with this Property has a Fluid, its temperature will be set to this if it is the default Fluid + * temperature. */ private int blastTemperature; @@ -132,7 +133,10 @@ public void verifyProperty(MaterialProperties properties) { public static GasTier validateGasTier(String gasTierName) { if (gasTierName == null) return null; - else if ("LOW".equalsIgnoreCase(gasTierName)) return GasTier.LOW; + if (GroovyScriptModule.isCurrentlyRunning()) { + return GroovyScriptModule.parseAndValidateEnumValue(GasTier.class, gasTierName, "gas tier"); + } + if ("LOW".equalsIgnoreCase(gasTierName)) return GasTier.LOW; else if ("MID".equalsIgnoreCase(gasTierName)) return GasTier.MID; else if ("HIGH".equalsIgnoreCase(gasTierName)) return GasTier.HIGH; else if ("HIGHER".equalsIgnoreCase(gasTierName)) return GasTier.HIGHER; diff --git a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialHelpers.java b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialHelpers.java index ca5d08a1efa..ed66c077a40 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialHelpers.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialHelpers.java @@ -4,6 +4,7 @@ import gregtech.api.fluids.FluidState; import gregtech.api.unification.material.Material; import gregtech.api.unification.stack.MaterialStack; +import gregtech.integration.groovy.GroovyScriptModule; import com.google.common.collect.ImmutableList; import crafttweaker.CraftTweakerAPI; @@ -17,7 +18,9 @@ protected static ImmutableList validateComponentList(MaterialStac protected static FluidState validateFluidState(String fluidTypeName) { if (fluidTypeName == null || fluidTypeName.equals("fluid")) return FluidState.LIQUID; - + if (GroovyScriptModule.isCurrentlyRunning()) { + return GroovyScriptModule.parseAndValidateEnumValue(FluidState.class, fluidTypeName, "fluid type"); + } if (fluidTypeName.equals("liquid")) return FluidState.LIQUID; if (fluidTypeName.equals("gas")) return FluidState.GAS; if (fluidTypeName.equals("plasma")) return FluidState.PLASMA; diff --git a/src/main/java/gregtech/integration/groovy/GroovyExpansions.java b/src/main/java/gregtech/integration/groovy/GroovyExpansions.java new file mode 100644 index 00000000000..8c23fdf270f --- /dev/null +++ b/src/main/java/gregtech/integration/groovy/GroovyExpansions.java @@ -0,0 +1,42 @@ +package gregtech.integration.groovy; + +import gregtech.api.recipes.RecipeBuilder; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.event.MaterialEvent; + +import net.minecraft.util.ResourceLocation; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; + +public class GroovyExpansions { + + public static > RecipeBuilder property(RecipeBuilder builder, String key, + Object value) { + if (!builder.applyProperty(key, value)) { + GroovyLog.get().error("Failed to add property '{}' with '{}' to recipe", key, value); + } + return builder; + } + + public static Material.Builder materialBuilder(MaterialEvent event, int id, ResourceLocation resourceLocation) { + return new Material.Builder(id, resourceLocation); + } + + public static Material.Builder materialBuilder(MaterialEvent event, int id, String domain, String path) { + return materialBuilder(event, id, domain, path); + } + + public static Material.Builder materialBuilder(MaterialEvent event, int id, String s) { + String domain, path; + if (s.contains(":")) { + String[] parts = s.split(":", 2); + domain = parts[0]; + path = parts[1]; + } else { + domain = GroovyScript.getRunConfig().getPackId(); + path = s; + } + return materialBuilder(event, id, new ResourceLocation(domain, path)); + } +} diff --git a/src/main/java/gregtech/integration/groovy/GroovyMaterialBuilderExpansion.java b/src/main/java/gregtech/integration/groovy/GroovyMaterialBuilderExpansion.java index 3f5ea4873f4..f4e30273435 100644 --- a/src/main/java/gregtech/integration/groovy/GroovyMaterialBuilderExpansion.java +++ b/src/main/java/gregtech/integration/groovy/GroovyMaterialBuilderExpansion.java @@ -8,9 +8,13 @@ import gregtech.api.unification.material.info.MaterialFlag; import gregtech.api.unification.material.info.MaterialIconSet; import gregtech.api.unification.material.properties.BlastProperty; +import gregtech.api.unification.stack.MaterialStack; import net.minecraft.util.ResourceLocation; +import com.cleanroommc.groovyscript.api.GroovyLog; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import java.util.ArrayList; import java.util.List; @@ -85,22 +89,30 @@ public static Material.Builder blastTemp(Material.Builder builder, int temp, Str public static Material.Builder blastTemp(Material.Builder builder, int temp, String raw, int eutOverride, int durationOverride, int vacuumEUtOverride, int vacuumDurationOverride) { - BlastProperty.GasTier gasTier = null; - String name = raw.toUpperCase(); - for (BlastProperty.GasTier gasTier1 : BlastProperty.GasTier.VALUES) { - if (gasTier1.name().equals(name)) { - gasTier = gasTier1; - break; - } - } - final BlastProperty.GasTier finalGasTier = gasTier; - if (GroovyScriptModule.validateNonNull(gasTier, () -> "Can't find gas tier for " + name + - " in material builder. Valid values are 'low', 'mid', 'high', 'higher', 'highest'!")) { + BlastProperty.GasTier gasTier = GroovyScriptModule.parseAndValidateEnumValue(BlastProperty.GasTier.class, raw, + "gas tier"); + if (gasTier != null) { return builder.blast(b -> b - .temp(temp, finalGasTier) + .temp(temp, gasTier) .blastStats(eutOverride, durationOverride) .vacuumStats(vacuumEUtOverride, vacuumDurationOverride)); } return builder; } + + public static Material.Builder components(Material.Builder builder, Object... objects) { + ObjectArrayList materialStacks = new ObjectArrayList<>(); + for (Object o : objects) { + if (o instanceof MaterialStack materialStack) { + materialStacks.add(materialStack); + } else if (o instanceof Material material) { + materialStacks.add(new MaterialStack(material, 1)); + } else { + GroovyLog.get() + .error("Material components must be of type Material or MaterialStack, but was of type {}", + o == null ? null : o.getClass()); + } + } + return builder.components(materialStacks.toArray(new MaterialStack[0])); + } } diff --git a/src/main/java/gregtech/integration/groovy/GroovyRecipeBuilderExpansion.java b/src/main/java/gregtech/integration/groovy/GroovyRecipeBuilderExpansion.java deleted file mode 100644 index 90a0dc3753b..00000000000 --- a/src/main/java/gregtech/integration/groovy/GroovyRecipeBuilderExpansion.java +++ /dev/null @@ -1,16 +0,0 @@ -package gregtech.integration.groovy; - -import gregtech.api.recipes.RecipeBuilder; - -import com.cleanroommc.groovyscript.api.GroovyLog; - -public class GroovyRecipeBuilderExpansion { - - public static > RecipeBuilder property(RecipeBuilder builder, String key, - Object value) { - if (!builder.applyProperty(key, value)) { - GroovyLog.get().error("Failed to add property '{}' with '{}' to recipe", key, value); - } - return builder; - } -} diff --git a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java index b6b603bb07e..571261241b2 100644 --- a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java +++ b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java @@ -8,6 +8,8 @@ import gregtech.api.recipes.RecipeBuilder; import gregtech.api.recipes.RecipeMap; import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.event.MaterialEvent; +import gregtech.api.unification.material.event.PostMaterialEvent; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.util.Mods; @@ -35,13 +37,20 @@ import com.cleanroommc.groovyscript.api.GroovyPlugin; import com.cleanroommc.groovyscript.api.IGameObjectHandler; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; +import com.cleanroommc.groovyscript.compat.mods.ModPropertyContainer; +import com.cleanroommc.groovyscript.event.EventBusType; +import com.cleanroommc.groovyscript.event.GroovyEventManager; import com.cleanroommc.groovyscript.gameobjects.GameObjectHandlerManager; +import com.cleanroommc.groovyscript.helper.EnumHelper; +import com.cleanroommc.groovyscript.sandbox.LoadStage; import com.cleanroommc.groovyscript.sandbox.expand.ExpansionHelper; import com.google.common.collect.ImmutableList; +import groovy.lang.Closure; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; @@ -77,6 +86,18 @@ public static boolean isCurrentlyRunning() { GroovyScript.getSandbox().isRunning(); } + public static > T parseAndValidateEnumValue(Class clazz, String raw, String type) { + T t = EnumHelper.valueOfNullable(clazz, raw, false); + if (t == null) { + GroovyLog.get().error("Can't find {} for {} in material builder. Valid values are {};", + type, + raw, + Arrays.toString(clazz.getEnumConstants())); + return null; + } + return t; + } + public static GroovyContainer getInstance() { return modSupportContainer; } @@ -191,10 +212,42 @@ public static void loadMetaItemBracketHandler() { } @Override - public @NotNull String getModName() { + public @NotNull String getContainerName() { return "GregTech"; } + @Override + public @Nullable ModPropertyContainer createModPropertyContainer() { + return new ModPropertyContainer() { + + public void materialEvent(EventPriority priority, Closure eventListener) { + if (isCurrentlyRunning() && GroovyScript.getSandbox().getCurrentLoader() != LoadStage.PRE_INIT) { + GroovyLog.get().error("GregTech's material event can only be used in pre init!"); + return; + } + GroovyEventManager.INSTANCE.listen(priority, EventBusType.FORGE, MaterialEvent.class, + eventListener); + } + + public void materialEvent(Closure eventListener) { + materialEvent(EventPriority.NORMAL, eventListener); + } + + public void lateMaterialEvent(EventPriority priority, Closure eventListener) { + if (isCurrentlyRunning() && GroovyScript.getSandbox().getCurrentLoader() != LoadStage.PRE_INIT) { + GroovyLog.get().error("GregTech's material event can only be used in pre init!"); + return; + } + GroovyEventManager.INSTANCE.listen(priority, EventBusType.FORGE, PostMaterialEvent.class, + eventListener); + } + + public void lateMaterialEvent(Closure eventListener) { + materialEvent(EventPriority.NORMAL, eventListener); + } + }; + } + @Override public void onCompatLoaded(GroovyContainer groovyContainer) { modSupportContainer = groovyContainer; @@ -213,6 +266,7 @@ public void onCompatLoaded(GroovyContainer groovyContainer) { ExpansionHelper.mixinClass(Material.class, MaterialExpansion.class); ExpansionHelper.mixinClass(Material.class, MaterialPropertyExpansion.class); ExpansionHelper.mixinClass(Material.Builder.class, GroovyMaterialBuilderExpansion.class); - ExpansionHelper.mixinClass(RecipeBuilder.class, GroovyRecipeBuilderExpansion.class); + ExpansionHelper.mixinMethod(RecipeBuilder.class, GroovyExpansions.class, "property"); + ExpansionHelper.mixinMethod(MaterialEvent.class, GroovyExpansions.class, "materialBuilder"); } } From c2f681f69f7b61c76e4b113263474133993ad056 Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Sun, 24 Mar 2024 10:41:14 -0400 Subject: [PATCH 05/25] allow SMD diodes in low tier diode block recipes (#2423) --- .../java/gregtech/loaders/recipe/MetaTileEntityLoader.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java b/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java index 9cb0e321a0e..192c35d1d16 100644 --- a/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java @@ -898,7 +898,8 @@ public static void init() { ROTOR); registerMachineRecipe(ArrayUtils.subarray(MetaTileEntities.DIODES, GTValues.ULV, GTValues.HV), "CDC", "DHD", - "PDP", 'H', HULL, 'D', MetaItems.DIODE, 'P', PLATE, 'C', CABLE_QUAD); + "PDP", 'H', HULL, 'D', new UnificationEntry(OrePrefix.component, MarkerMaterials.Component.Diode), 'P', + PLATE, 'C', CABLE_QUAD); registerMachineRecipe(ArrayUtils.subarray(MetaTileEntities.DIODES, GTValues.HV, GTValues.LuV), "CDC", "DHD", "PDP", 'H', HULL, 'D', MetaItems.SMD_DIODE, 'P', PLATE, 'C', CABLE_QUAD); registerMachineRecipe( From ba69a484403b01e3d87703546c582b61bfe0d596 Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Sun, 24 Mar 2024 22:10:19 -0400 Subject: [PATCH 06/25] check for a valid MTE before rendering (#2424) --- .../client/renderer/handler/MetaTileEntityRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gregtech/client/renderer/handler/MetaTileEntityRenderer.java b/src/main/java/gregtech/client/renderer/handler/MetaTileEntityRenderer.java index 846bcc08860..8e0fe1f6962 100644 --- a/src/main/java/gregtech/client/renderer/handler/MetaTileEntityRenderer.java +++ b/src/main/java/gregtech/client/renderer/handler/MetaTileEntityRenderer.java @@ -94,7 +94,7 @@ public void renderItem(ItemStack rawStack, TransformType transformType) { @Override public boolean renderBlock(IBlockAccess world, BlockPos pos, IBlockState state, BufferBuilder buffer) { MetaTileEntity metaTileEntity = GTUtility.getMetaTileEntity(world, pos); - if (metaTileEntity == null) { + if (metaTileEntity == null || !metaTileEntity.isValid()) { return false; } CCRenderState renderState = CCRenderState.instance(); From 20e61ca2cac5bde02d56827e7a019aa21cb69f5a Mon Sep 17 00:00:00 2001 From: froot <66188216+kumquat-ir@users.noreply.github.com> Date: Wed, 27 Mar 2024 00:16:28 -0700 Subject: [PATCH 07/25] Fix link to GT IMPACT in readme (#2427) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5876b6d1b60..8a4fcfa7209 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Anything else? Sure come to [Discord](https://discord.gg/bWSWuYvURP). ## Credited Works Heating Coil Textures, Wooden Forms, World Accelerators, and the Extreme Combustion Engine are from the **[GregTech: New Horizons Modpack](https://www.curseforge.com/minecraft/modpacks/gt-new-horizons)**. -Primitive Water Pump and Super Tank GUI Textures are from the **[IMPACT: GREGTECH EDITION Modpack](https://gtimpact.space/)**. +Primitive Water Pump and Super Tank GUI Textures are from the **[IMPACT: GREGTECH EDITION Modpack](https://gt-impact.github.io/)**. Ender Fluid Link Cover, Auto-Maintenance Hatch, Optical Fiber, and Data Bank Textures are from **[TecTech](https://github.com/Technus/TecTech)**. From ad8275f17f3f735867f65ed40ec5c09b76d4309b Mon Sep 17 00:00:00 2001 From: M_W_K <31022105+M-W-K@users.noreply.github.com> Date: Wed, 27 Mar 2024 01:16:49 -0600 Subject: [PATCH 08/25] Fix fluid drilling rig display units (#2417) --- .../multi/electric/MetaTileEntityFluidDrill.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFluidDrill.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFluidDrill.java index a1501dd6f65..dca07a39e5f 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFluidDrill.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFluidDrill.java @@ -184,7 +184,7 @@ protected void addDisplayText(List textList) { TextFormatting.BLUE, TextFormattingUtil.formatNumbers( minerLogic.getFluidToProduce() * 20L / FluidDrillLogic.MAX_PROGRESS) + - " L/t"); + " L/s"); tl.add(TextComponentUtil.translationWithColor( TextFormatting.GRAY, "gregtech.multiblock.fluid_rig.fluid_amount", From db02d99d491e35d00740e338e1feda5046ca7458 Mon Sep 17 00:00:00 2001 From: iouter <62897714+iouter@users.noreply.github.com> Date: Wed, 27 Mar 2024 15:17:15 +0800 Subject: [PATCH 09/25] Update zh_cn.lang (#2413) --- .../resources/assets/gregtech/lang/zh_cn.lang | 54 ++++++++++++++----- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/src/main/resources/assets/gregtech/lang/zh_cn.lang b/src/main/resources/assets/gregtech/lang/zh_cn.lang index 60613d04a2c..67437657210 100644 --- a/src/main/resources/assets/gregtech/lang/zh_cn.lang +++ b/src/main/resources/assets/gregtech/lang/zh_cn.lang @@ -112,7 +112,7 @@ gregtech.waila.progress_computation=计算进度:%s / %s gregtech.multiblock.title=多方块结构 gregtech.multiblock.primitive_blast_furnace.bronze.description=土高炉是(PBF)是个多方块结构。尽管它不是很快,却能在游戏前期为你的发展提供钢材。 -gregtech.multiblock.coke_oven.description=焦炉是个多方块结构,用于在早期生产焦炭和杂酚油。无需燃料即可工作,内部至多可容纳32桶杂酚油。其存储可通过焦炉仓进行访问。 +gregtech.multiblock.coke_oven.description=焦炉是一种多方块结构,用于在早期生产焦煤和杂酚油,无需燃料即可工作,内部至多可容纳 32 桶杂酚油。其存储可通过焦炉仓进行访问。 gregtech.multiblock.vacuum_freezer.description=真空冷冻机是个多方块结构,主要用于热锭冷却。此外,它还可以冻结水等其他物质。 gregtech.multiblock.implosion_compressor.description=聚爆压缩机是个多方块结构,能够借助炸药将宝石粉转化为相应的宝石。 gregtech.multiblock.pyrolyse_oven.description=热解炉是种用于将原木处理为木炭、杂酚油、灰烬或重油的多方块结构。 @@ -852,7 +852,7 @@ metaitem.cover.item.voiding.advanced.tooltip=作§f覆盖板§7时允许按数 metaitem.cover.storage.name=存储覆盖板 metaitem.cover.storage.tooltip=给零碎的小玩意准备的小型存储空间 metaitem.cover.maintenance.detector.name=维护需求覆盖板 -metaitem.cover.maintenance.detector.tooltip=作§f覆盖板§7时在机器§f需要维护§7输出红石信号。 +metaitem.cover.maintenance.detector.tooltip=作§f覆盖板§7时在机器§f需要维护§7时发出红石信号。 metaitem.cover.facade.name=%s伪装板 metaitem.cover.facade.tooltip=可作为§f覆盖板§7加装装饰性套壳。 @@ -1008,6 +1008,9 @@ item.gt.tool.screwdriver_lv.name=%s螺丝刀(LV) item.gt.tool.screwdriver_lv.tooltip=§8调整覆盖板和机器 item.gt.tool.plunger.name=%s搋子 item.gt.tool.plunger.tooltip=§8从机器中抽除流体 +item.gt.tool.wire_cutter_lv.name=%s剪线钳(LV) +item.gt.tool.wire_cutter_hv.name=%s剪线钳(HV) +item.gt.tool.wire_cutter_iv.name=%s剪线钳(IV) item.gt.tool.tooltip.crafting_uses=§a合成耐久度:%s @@ -2348,6 +2351,17 @@ tile.treated_wood_fence.name=防腐木栅栏 tile.rubber_wood_fence_gate.name=橡胶木栅栏门 tile.treated_wood_fence_gate.name=防腐木栅栏门 +tile.gt_explosive.breaking_tooltip=破坏它会引爆火药,潜行挖掘以重新拾取 +tile.gt_explosive.lighting_tooltip=无法用红石信号引爆 + +tile.powderbarrel.name=火药桶 +tile.powderbarrel.drops_tooltip=爆炸范围略大于TNT,所有被摧毁的方块都会掉落 +entity.Powderbarrel.name=火药桶 + +tile.itnt.name=工业TNT +tile.itnt.drops_tooltip=爆炸范围比TNT大得多,所有被摧毁的方块都会掉落 +entity.ITNT.name=工业TNT + tile.brittle_charcoal.name=脆木炭块 tile.brittle_charcoal.tooltip.1=产自木炭堆点火器。 tile.brittle_charcoal.tooltip.2=采掘可掉落木炭。 @@ -4405,7 +4419,7 @@ gregtech.machine.world_accelerator.zpm.name=精英世界加速器 III gregtech.machine.world_accelerator.zpm.tooltip=“时间之§m瓶§r”§7方块 gregtech.machine.world_accelerator.uv.name=终极世界加速器 gregtech.machine.world_accelerator.uv.tooltip=时间扭曲者 -gregtech.machine.world_accelerator.description=使用§f螺丝刀§7在§f方块实体§r或§f随机刻§7模式中切换。 +gregtech.machine.world_accelerator.description=使用§f螺丝刀§7在§f方块实体§7或§f随机刻§7模式中切换。 gregtech.machine.world_accelerator.power_usage=§7在随机刻模式下最多使用§f%dA,§7在方块实体模式下最多使用§f%dA 。 gregtech.machine.world_accelerator.acceleration=§d加速倍率: §f%dx gregtech.machine.world_accelerator.working_area=§b作用范围: @@ -5243,15 +5257,27 @@ gregtech.machine.laser_hatch.tooltip2=§c激光传导线缆必须直线摆放! gregtech.machine.fluid_tank.max_multiblock=多方块结构最大尺寸:%,dx%,dx%,d gregtech.machine.fluid_tank.fluid=含有%s mB%s -gregtech.machine.me_export_fluid_hatch.name=ME输出仓 +# ME Parts +gregtech.machine.me_import_item_bus.name=ME输入总线 +gregtech.machine.me.item_import.tooltip=从ME网络提取指定物品 +gregtech.machine.me_stocking_item_bus.name=ME库存输入总线 +gregtech.machine.me.stocking_item.tooltip=直接从ME网络抽取物品 +gregtech.machine.me.stocking_item.tooltip.2=ME自动拉取模式将自动标记ME网络中的前16种物品,每5秒更新一次。 +gregtech.machine.me_import_item_hatch.configs.tooltip=可标记16种物品 +gregtech.machine.me_import_fluid_hatch.name=ME输入仓 +gregtech.machine.me.fluid_import.tooltip=从ME网络提取指定流体 +gregtech.machine.me_stocking_fluid_hatch.name=ME库存输入仓 +gregtech.machine.me.stocking_fluid.tooltip=直接从ME网络抽取流体 +gregtech.machine.me.stocking_fluid.tooltip.2=ME自动拉取模式将自动标记ME网络中的前16种流体,每5秒更新一次。 +gregtech.machine.me_import_fluid_hatch.configs.tooltip=可标记16种流体 gregtech.machine.me_export_item_bus.name=ME输出总线 -gregtech.machine.me_import_fluid_hatch.name=ME库存输入仓 -gregtech.machine.me_import_item_bus.name=ME库存输入总线 -gregtech.machine.me.fluid_export.tooltip=将流体直接存储到ME网络中。 -gregtech.machine.me.item_export.tooltip=将物品直接存储到ME网络中。 -gregtech.machine.me.fluid_import.tooltip=自动从ME网络获取流体。 -gregtech.machine.me.item_import.tooltip=自动从ME网络获取物品。 -gregtech.machine.me.export.tooltip=在连接到ME网络之前,它具有无限容量。 +gregtech.machine.me.item_export.tooltip=将物品直接存储到ME网络中 +gregtech.machine.me.item_export.tooltip.2=可以缓存无限数量的物品 +gregtech.machine.me_export_fluid_hatch.name=ME输出仓 +gregtech.machine.me.fluid_export.tooltip=将流体直接存储到ME网络中 +gregtech.machine.me.fluid_export.tooltip.2=可以缓存无限数量的流体 +gregtech.machine.me.stocking_auto_pull_enabled=ME自动拉取已启用 +gregtech.machine.me.stocking_auto_pull_disabled=ME自动拉取已禁用 # Universal tooltips gregtech.universal.tooltip.voltage_in=§a输入电压:§f%,d EU/t(%s§f) @@ -5274,7 +5300,7 @@ gregtech.universal.tooltip.item_stored=§d内含物品:§f%2$,d + %3$,d 个%1$ gregtech.universal.tooltip.item_transfer_rate=§b传输速率:§f%,d件物品/s gregtech.universal.tooltip.item_transfer_rate_stacks=§b传输速率:§f%,d组物品/s gregtech.universal.tooltip.fluid_storage_capacity=§9流体容量:§f%,d L -gregtech.universal.tooltip.fluid_storage_capacity_mult=§9流体容量:§r共§f%d§7个流体槽,每个§f%dL§7 +gregtech.universal.tooltip.fluid_storage_capacity_mult=§9流体容量:§7共§f%d§7个流体槽,每个§f%dL§7 gregtech.universal.tooltip.fluid_stored=§d内含流体:§f%2$,d L %1$s gregtech.universal.tooltip.fluid_transfer_rate=§b传输速率:§f%,d L/t gregtech.universal.tooltip.parallel=§d最大并行:§f%d @@ -5392,8 +5418,12 @@ gregtech.gui.me_network.offline=网络状态:§4离线§r gregtech.gui.waiting_list=发送队列: gregtech.gui.config_slot=§f配置槽位§r gregtech.gui.config_slot.set=§7点击§b设置/选择§7配置槽位。§r +gregtech.gui.config_slot.set_only=§7点击§b设置§7配置槽位。§r gregtech.gui.config_slot.scroll=§7使用滚轮§a切换§7配置数。§r gregtech.gui.config_slot.remove=§7右击§4清除§7配置槽位。§r +gregtech.gui.config_slot.auto_pull_managed=§4禁用:§7由ME自动拉取管理 +gregtech.gui.me_bus.extra_slot=额外槽位/n§7在这里放置配方的额外物品,例如模具或透镜 +gregtech.gui.me_bus.auto_pull_button=单击以切换ME自动拉取模式 gregtech.gui.alarm.radius=半径: From bf9ce4d91b60643f2579b698e3414c119ecdc7a4 Mon Sep 17 00:00:00 2001 From: M_W_K <31022105+M-W-K@users.noreply.github.com> Date: Wed, 27 Mar 2024 20:08:03 -0600 Subject: [PATCH 10/25] Generify DimensionProperty (#2414) --- .../capability/impl/AbstractRecipeLogic.java | 9 +- .../gregtech/api/recipes/RecipeBuilder.java | 50 ++++++++++- .../java/gregtech/api/recipes/RecipeMaps.java | 5 +- .../builders/GasCollectorRecipeBuilder.java | 82 ----------------- .../recipeproperties/DimensionProperty.java | 87 +++++++++++++++++++ .../GasCollectorDimensionProperty.java | 48 ---------- .../electric/MetaTileEntityGasCollector.java | 31 +------ .../resources/assets/gregtech/lang/en_us.lang | 1 + 8 files changed, 148 insertions(+), 165 deletions(-) delete mode 100644 src/main/java/gregtech/api/recipes/builders/GasCollectorRecipeBuilder.java create mode 100644 src/main/java/gregtech/api/recipes/recipeproperties/DimensionProperty.java delete mode 100644 src/main/java/gregtech/api/recipes/recipeproperties/GasCollectorDimensionProperty.java diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index ce4eab33ac9..6d8877ff1dc 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -16,6 +16,7 @@ import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.logic.IParallelableRecipeLogic; import gregtech.api.recipes.recipeproperties.CleanroomProperty; +import gregtech.api.recipes.recipeproperties.DimensionProperty; import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.GTUtility; @@ -407,7 +408,7 @@ protected boolean checkPreviousRecipe() { * @return true if the recipe is allowed to be used, else false */ public boolean checkRecipe(@NotNull Recipe recipe) { - return checkCleanroomRequirement(recipe); + return checkCleanroomRequirement(recipe) && checkDimensionRequirement(recipe); } /** @@ -431,6 +432,12 @@ protected boolean checkCleanroomRequirement(@NotNull Recipe recipe) { return false; } + protected boolean checkDimensionRequirement(@NotNull Recipe recipe) { + if (!recipe.hasProperty(DimensionProperty.getInstance())) return true; + return recipe.getProperty(DimensionProperty.getInstance(), DimensionProperty.DimensionPropertyList.EMPTY_LIST) + .checkDimension(this.getMetaTileEntity().getWorld().provider.getDimension()); + } + /** * Prepares the recipe to be run. *

    diff --git a/src/main/java/gregtech/api/recipes/RecipeBuilder.java b/src/main/java/gregtech/api/recipes/RecipeBuilder.java index 87175224c5d..1b59129381a 100644 --- a/src/main/java/gregtech/api/recipes/RecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeBuilder.java @@ -13,6 +13,7 @@ import gregtech.api.recipes.ingredients.nbtmatch.NBTCondition; import gregtech.api.recipes.ingredients.nbtmatch.NBTMatcher; import gregtech.api.recipes.recipeproperties.CleanroomProperty; +import gregtech.api.recipes.recipeproperties.DimensionProperty; import gregtech.api.recipes.recipeproperties.IRecipePropertyStorage; import gregtech.api.recipes.recipeproperties.RecipeProperty; import gregtech.api.recipes.recipeproperties.RecipePropertyStorage; @@ -39,6 +40,8 @@ import com.cleanroommc.groovyscript.api.IIngredient; import com.cleanroommc.groovyscript.helper.ingredient.OreDictIngredient; import crafttweaker.CraftTweakerAPI; +import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.ints.IntLists; import org.apache.commons.lang3.builder.ToStringBuilder; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -137,8 +140,51 @@ public R cleanroom(@Nullable CleanroomType cleanroom) { return (R) this; } + public R dimension(int dimensionID) { + return dimension(dimensionID, false); + } + + public R dimension(int dimensionID, boolean toBlackList) { + DimensionProperty.DimensionPropertyList dimensionIDs = getCompleteDimensionIDs(); + if (dimensionIDs == DimensionProperty.DimensionPropertyList.EMPTY_LIST) { + dimensionIDs = new DimensionProperty.DimensionPropertyList(); + this.applyProperty(DimensionProperty.getInstance(), dimensionIDs); + } + dimensionIDs.add(dimensionID, toBlackList); + return (R) this; + } + + public DimensionProperty.DimensionPropertyList getCompleteDimensionIDs() { + return this.recipePropertyStorage == null ? DimensionProperty.DimensionPropertyList.EMPTY_LIST : + this.recipePropertyStorage.getRecipePropertyValue(DimensionProperty.getInstance(), + DimensionProperty.DimensionPropertyList.EMPTY_LIST); + } + + public IntList getDimensionIDs() { + return this.recipePropertyStorage == null ? IntLists.EMPTY_LIST : + this.recipePropertyStorage.getRecipePropertyValue(DimensionProperty.getInstance(), + DimensionProperty.DimensionPropertyList.EMPTY_LIST).whiteListDimensions; + } + + public IntList getBlockedDimensionIDs() { + return this.recipePropertyStorage == null ? IntLists.EMPTY_LIST : + this.recipePropertyStorage.getRecipePropertyValue(DimensionProperty.getInstance(), + DimensionProperty.DimensionPropertyList.EMPTY_LIST).whiteListDimensions; + } + public boolean applyProperty(@NotNull String key, @Nullable Object value) { - if (key.equals(CleanroomProperty.KEY)) { + if (key.equals(DimensionProperty.KEY)) { + if (value instanceof DimensionProperty.DimensionPropertyList list) { + DimensionProperty.DimensionPropertyList dimensionIDs = getCompleteDimensionIDs(); + if (dimensionIDs == DimensionProperty.DimensionPropertyList.EMPTY_LIST) { + dimensionIDs = new DimensionProperty.DimensionPropertyList(); + this.applyProperty(DimensionProperty.getInstance(), dimensionIDs); + } + dimensionIDs.merge(list); + return true; + } + return false; + } else if (key.equals(CleanroomProperty.KEY)) { if (value instanceof CleanroomType) { this.cleanroom((CleanroomType) value); } else if (value instanceof String) { @@ -976,6 +1022,8 @@ public String toString() { .append("EUt", EUt) .append("hidden", hidden) .append("cleanroom", getCleanroom()) + .append("dimensions", getDimensionIDs().toString()) + .append("dimensions_blocked", getBlockedDimensionIDs().toString()) .append("recipeStatus", recipeStatus) .toString(); } diff --git a/src/main/java/gregtech/api/recipes/RecipeMaps.java b/src/main/java/gregtech/api/recipes/RecipeMaps.java index e61261ddd09..9cd9547457f 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMaps.java +++ b/src/main/java/gregtech/api/recipes/RecipeMaps.java @@ -11,7 +11,6 @@ import gregtech.api.recipes.builders.ComputationRecipeBuilder; import gregtech.api.recipes.builders.FuelRecipeBuilder; import gregtech.api.recipes.builders.FusionRecipeBuilder; -import gregtech.api.recipes.builders.GasCollectorRecipeBuilder; import gregtech.api.recipes.builders.ImplosionRecipeBuilder; import gregtech.api.recipes.builders.PrimitiveRecipeBuilder; import gregtech.api.recipes.builders.SimpleRecipeBuilder; @@ -982,8 +981,8 @@ public final class RecipeMaps { .build(); @ZenProperty - public static final RecipeMap GAS_COLLECTOR_RECIPES = new RecipeMapBuilder<>( - "gas_collector", new GasCollectorRecipeBuilder()) + public static final RecipeMap GAS_COLLECTOR_RECIPES = new RecipeMapBuilder<>( + "gas_collector", new SimpleRecipeBuilder()) .itemInputs(1) .fluidOutputs(1) .itemSlotOverlay(GuiTextures.INT_CIRCUIT_OVERLAY, false, true) diff --git a/src/main/java/gregtech/api/recipes/builders/GasCollectorRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/GasCollectorRecipeBuilder.java deleted file mode 100644 index fe3bb345305..00000000000 --- a/src/main/java/gregtech/api/recipes/builders/GasCollectorRecipeBuilder.java +++ /dev/null @@ -1,82 +0,0 @@ -package gregtech.api.recipes.builders; - -import gregtech.api.recipes.Recipe; -import gregtech.api.recipes.RecipeBuilder; -import gregtech.api.recipes.RecipeMap; -import gregtech.api.recipes.recipeproperties.GasCollectorDimensionProperty; - -import crafttweaker.CraftTweakerAPI; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import it.unimi.dsi.fastutil.ints.IntLists; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -public class GasCollectorRecipeBuilder extends RecipeBuilder { - - public GasCollectorRecipeBuilder() {} - - public GasCollectorRecipeBuilder(Recipe recipe, RecipeMap recipeMap) { - super(recipe, recipeMap); - } - - public GasCollectorRecipeBuilder(RecipeBuilder recipeBuilder) { - super(recipeBuilder); - } - - @Override - public GasCollectorRecipeBuilder copy() { - return new GasCollectorRecipeBuilder(this); - } - - @Override - public boolean applyProperty(@NotNull String key, Object value) { - if (key.equals(GasCollectorDimensionProperty.KEY)) { - if (value instanceof Integer) { - this.dimension((Integer) value); - } else if (value instanceof List && !((List) value).isEmpty() && - ((List) value).get(0) instanceof Integer) { - IntList dimensionIDs = getDimensionIDs(); - if (dimensionIDs == IntLists.EMPTY_LIST) { - dimensionIDs = new IntArrayList(); - this.applyProperty(GasCollectorDimensionProperty.getInstance(), dimensionIDs); - } - dimensionIDs.addAll((List) value); - } else { - if (isCTRecipe) { - CraftTweakerAPI.logError("Dimension for Gas Collector needs to be a Integer"); - return false; - } - throw new IllegalArgumentException("Invalid Dimension Property Type!"); - } - return true; - } - return super.applyProperty(key, value); - } - - public GasCollectorRecipeBuilder dimension(int dimensionID) { - IntList dimensionIDs = getDimensionIDs(); - if (dimensionIDs == IntLists.EMPTY_LIST) { - dimensionIDs = new IntArrayList(); - this.applyProperty(GasCollectorDimensionProperty.getInstance(), dimensionIDs); - } - dimensionIDs.add(dimensionID); - return this; - } - - public IntList getDimensionIDs() { - return this.recipePropertyStorage == null ? IntLists.EMPTY_LIST : - this.recipePropertyStorage.getRecipePropertyValue(GasCollectorDimensionProperty.getInstance(), - IntLists.EMPTY_LIST); - } - - @Override - public String toString() { - return new ToStringBuilder(this) - .appendSuper(super.toString()) - .append(GasCollectorDimensionProperty.getInstance().getKey(), getDimensionIDs().toString()) - .toString(); - } -} diff --git a/src/main/java/gregtech/api/recipes/recipeproperties/DimensionProperty.java b/src/main/java/gregtech/api/recipes/recipeproperties/DimensionProperty.java new file mode 100644 index 00000000000..f233e7cd7f3 --- /dev/null +++ b/src/main/java/gregtech/api/recipes/recipeproperties/DimensionProperty.java @@ -0,0 +1,87 @@ +package gregtech.api.recipes.recipeproperties; + +import gregtech.api.worldgen.config.WorldGenRegistry; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.I18n; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; + +public class DimensionProperty extends RecipeProperty { + + public static final String KEY = "dimension"; + + private static DimensionProperty INSTANCE; + + private DimensionProperty() { + super(KEY, DimensionPropertyList.class); + } + + public static DimensionProperty getInstance() { + if (INSTANCE == null) + INSTANCE = new DimensionProperty(); + return INSTANCE; + } + + @Override + public void drawInfo(Minecraft minecraft, int x, int y, int color, Object value) { + DimensionPropertyList list = castValue(value); + + if (list.whiteListDimensions.size() > 0) + minecraft.fontRenderer.drawString(I18n.format("gregtech.recipe.dimensions", + getDimensionsForRecipe(castValue(value).whiteListDimensions)), x, y, color); + if (list.blackListDimensions.size() > 0) + minecraft.fontRenderer.drawString(I18n.format("gregtech.recipe.dimensions_blocked", + getDimensionsForRecipe(castValue(value).blackListDimensions)), x, y, color); + } + + private static String getDimensionsForRecipe(IntList value) { + Int2ObjectMap dimNames = WorldGenRegistry.getNamedDimensions(); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < value.size(); i++) { + builder.append(dimNames.getOrDefault(value.getInt(i), String.valueOf(value.getInt(i)))); + if (i != value.size() - 1) + builder.append(", "); + } + String str = builder.toString(); + + if (str.length() >= 13) { + str = str.substring(0, 10) + ".."; + } + return str; + } + + // It would've been better to have one list and swap between blacklist and whitelist, but that would've been + // a bit awkward to apply to the property in practice. + public static class DimensionPropertyList { + + public static DimensionPropertyList EMPTY_LIST = new DimensionPropertyList(); + + public IntList whiteListDimensions = new IntArrayList(); + public IntList blackListDimensions = new IntArrayList(); + + public void add(int key, boolean toBlacklist) { + if (toBlacklist) { + blackListDimensions.add(key); + whiteListDimensions.rem(key); + } else { + whiteListDimensions.add(key); + blackListDimensions.rem(key); + } + } + + public void merge(DimensionPropertyList list) { + this.whiteListDimensions.addAll(list.whiteListDimensions); + this.blackListDimensions.addAll(list.blackListDimensions); + } + + public boolean checkDimension(int dim) { + boolean valid = true; + if (this.blackListDimensions.size() > 0) valid = !this.blackListDimensions.contains(dim); + if (this.whiteListDimensions.size() > 0) valid = this.whiteListDimensions.contains(dim); + return valid; + } + } +} diff --git a/src/main/java/gregtech/api/recipes/recipeproperties/GasCollectorDimensionProperty.java b/src/main/java/gregtech/api/recipes/recipeproperties/GasCollectorDimensionProperty.java deleted file mode 100644 index 94bb810e3b1..00000000000 --- a/src/main/java/gregtech/api/recipes/recipeproperties/GasCollectorDimensionProperty.java +++ /dev/null @@ -1,48 +0,0 @@ -package gregtech.api.recipes.recipeproperties; - -import gregtech.api.worldgen.config.WorldGenRegistry; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.IntList; - -public class GasCollectorDimensionProperty extends RecipeProperty { - - public static final String KEY = "dimension"; - - private static GasCollectorDimensionProperty INSTANCE; - - private GasCollectorDimensionProperty() { - super(KEY, IntList.class); - } - - public static GasCollectorDimensionProperty getInstance() { - if (INSTANCE == null) - INSTANCE = new GasCollectorDimensionProperty(); - return INSTANCE; - } - - @Override - public void drawInfo(Minecraft minecraft, int x, int y, int color, Object value) { - minecraft.fontRenderer.drawString(I18n.format("gregtech.recipe.dimensions", - getDimensionsForRecipe(castValue(value))), x, y, color); - } - - private static String getDimensionsForRecipe(IntList value) { - Int2ObjectMap dimNames = WorldGenRegistry.getNamedDimensions(); - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < value.size(); i++) { - builder.append(dimNames.getOrDefault(value.getInt(i), String.valueOf(value.getInt(i)))); - if (i != value.size() - 1) - builder.append(", "); - } - String str = builder.toString(); - - if (str.length() >= 13) { - str = str.substring(0, 10) + ".."; - } - return str; - } -} diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityGasCollector.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityGasCollector.java index 77bdd3b0485..8300d2b5fc9 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityGasCollector.java +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityGasCollector.java @@ -1,24 +1,17 @@ package gregtech.common.metatileentities.electric; -import gregtech.api.capability.IEnergyContainer; import gregtech.api.capability.impl.RecipeLogicEnergy; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.SimpleMachineMetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.RecipeMaps; -import gregtech.api.recipes.recipeproperties.GasCollectorDimensionProperty; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import net.minecraft.util.ResourceLocation; -import it.unimi.dsi.fastutil.ints.IntLists; -import org.jetbrains.annotations.NotNull; - import java.util.function.Function; -import java.util.function.Supplier; public class MetaTileEntityGasCollector extends SimpleMachineMetaTileEntity { @@ -36,28 +29,6 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { @Override protected RecipeLogicEnergy createWorkable(RecipeMap recipeMap) { - return new GasCollectorRecipeLogic(this, recipeMap, () -> energyContainer); - } - - protected boolean checkRecipe(@NotNull Recipe recipe) { - for (int dimension : recipe.getProperty(GasCollectorDimensionProperty.getInstance(), IntLists.EMPTY_LIST)) { - if (dimension == this.getWorld().provider.getDimension()) { - return true; - } - } - return false; - } - - private static class GasCollectorRecipeLogic extends RecipeLogicEnergy { - - public GasCollectorRecipeLogic(MetaTileEntity metaTileEntity, RecipeMap recipeMap, - Supplier energyContainer) { - super(metaTileEntity, recipeMap, energyContainer); - } - - @Override - public boolean checkRecipe(@NotNull Recipe recipe) { - return ((MetaTileEntityGasCollector) metaTileEntity).checkRecipe(recipe) && super.checkRecipe(recipe); - } + return new RecipeLogicEnergy(this, recipeMap, () -> energyContainer); } } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 6fc2ebe2f39..42c4c0ac26c 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -5337,6 +5337,7 @@ gregtech.recipe.temperature=Temperature: %,dK (%s) gregtech.recipe.explosive=Explosive: %s gregtech.recipe.eu_to_start=Energy To Start: %sEU gregtech.recipe.dimensions=Dimensions: %s +gregtech.recipe.dimensions_blocked=Blocked Dimensions: %s gregtech.recipe.cleanroom=Requires %s gregtech.recipe.cleanroom.display_name=Cleanroom gregtech.recipe.cleanroom_sterile.display_name=Sterile Cleanroom From 111326a1222de0cd03b18f1cd8a73163110f88cc Mon Sep 17 00:00:00 2001 From: Serenibyss <10861407+serenibyss@users.noreply.github.com> Date: Wed, 27 Mar 2024 21:08:12 -0500 Subject: [PATCH 11/25] Allow Data Stick to copy-paste ME bus settings (#2419) --- .../api/capability/IDataStickIntractable.java | 11 ++++ .../api/metatileentity/MetaTileEntity.java | 17 ++++- .../appeng/MetaTileEntityMEInputBus.java | 65 ++++++++++++++++++- .../appeng/MetaTileEntityMEInputHatch.java | 58 ++++++++++++++++- .../appeng/MetaTileEntityMEStockingBus.java | 28 ++++++++ .../appeng/MetaTileEntityMEStockingHatch.java | 26 ++++++++ .../resources/assets/gregtech/lang/en_us.lang | 5 ++ 7 files changed, 205 insertions(+), 5 deletions(-) create mode 100644 src/main/java/gregtech/api/capability/IDataStickIntractable.java diff --git a/src/main/java/gregtech/api/capability/IDataStickIntractable.java b/src/main/java/gregtech/api/capability/IDataStickIntractable.java new file mode 100644 index 00000000000..4b9d36ee6ff --- /dev/null +++ b/src/main/java/gregtech/api/capability/IDataStickIntractable.java @@ -0,0 +1,11 @@ +package gregtech.api.capability; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +public interface IDataStickIntractable { + + void onDataStickLeftClick(EntityPlayer player, ItemStack dataStick); + + boolean onDataStickRightClick(EntityPlayer player, ItemStack dataStick); +} diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index e1da60cdfbe..a1ca10b2af0 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -6,6 +6,7 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; +import gregtech.api.capability.IDataStickIntractable; import gregtech.api.capability.IEnergyContainer; import gregtech.api.capability.impl.AbstractRecipeLogic; import gregtech.api.capability.impl.FluidHandlerProxy; @@ -35,6 +36,7 @@ import gregtech.client.utils.BloomEffectUtil; import gregtech.common.ConfigHolder; import gregtech.common.creativetab.GTCreativeTabs; +import gregtech.common.items.MetaItems; import net.minecraft.block.Block; import net.minecraft.block.state.BlockFaceShape; @@ -487,6 +489,12 @@ public final void onCoverLeftClick(EntityPlayer playerIn, CuboidRayTraceResult r public boolean onRightClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { ItemStack heldStack = playerIn.getHeldItem(hand); + if (this instanceof IDataStickIntractable dsi) { + if (MetaItems.TOOL_DATA_STICK.isItemEqual(heldStack) && dsi.onDataStickRightClick(playerIn, heldStack)) { + return true; + } + } + if (!playerIn.isSneaking() && openGUIOnRightClick()) { if (getWorld() != null && !getWorld().isRemote) { if (usesMui2()) { @@ -642,7 +650,14 @@ public boolean onHardHammerClick(EntityPlayer playerIn, EnumHand hand, EnumFacin return true; } - public void onLeftClick(EntityPlayer player, EnumFacing facing, CuboidRayTraceResult hitResult) {} + public void onLeftClick(EntityPlayer player, EnumFacing facing, CuboidRayTraceResult hitResult) { + if (this instanceof IDataStickIntractable dsi) { + ItemStack stack = player.getHeldItemMainhand(); + if (MetaItems.TOOL_DATA_STICK.isItemEqual(stack)) { + dsi.onDataStickLeftClick(player, stack); + } + } + } /** * @return true if the player must sneak to rotate this metatileentity, otherwise false diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEInputBus.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEInputBus.java index 1076de705e9..3d4fea9abc0 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEInputBus.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEInputBus.java @@ -3,6 +3,7 @@ import gregtech.api.GTValues; import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.capability.IDataStickIntractable; import gregtech.api.capability.IGhostSlotConfigurable; import gregtech.api.capability.INotifiableHandler; import gregtech.api.capability.impl.GhostCircuitItemStackHandler; @@ -54,15 +55,15 @@ public class MetaTileEntityMEInputBus extends MetaTileEntityAEHostablePart implements IMultiblockAbilityPart, - IGhostSlotConfigurable { + IGhostSlotConfigurable, IDataStickIntractable { public final static String ITEM_BUFFER_TAG = "ItemSlots"; public final static String WORKING_TAG = "WorkingEnabled"; private final static int CONFIG_SIZE = 16; private boolean workingEnabled = true; protected ExportOnlyAEItemList aeItemHandler; - private GhostCircuitItemStackHandler circuitInventory; - private NotifiableItemStackHandler extraSlotInventory; + protected GhostCircuitItemStackHandler circuitInventory; + protected NotifiableItemStackHandler extraSlotInventory; private ItemHandlerList actualImportItems; public MetaTileEntityMEInputBus(ResourceLocation metaTileEntityId) { @@ -318,6 +319,7 @@ public void addInformation(ItemStack stack, @Nullable World player, @NotNull Lis tooltip.add(I18n.format("gregtech.machine.item_bus.import.tooltip")); tooltip.add(I18n.format("gregtech.machine.me.item_import.tooltip")); tooltip.add(I18n.format("gregtech.machine.me_import_item_hatch.configs.tooltip")); + tooltip.add(I18n.format("gregtech.machine.me.copy_paste.tooltip")); tooltip.add(I18n.format("gregtech.universal.enabled")); } @@ -346,4 +348,61 @@ public void setGhostCircuitConfig(int config) { markDirty(); } } + + @Override + public final void onDataStickLeftClick(EntityPlayer player, ItemStack dataStick) { + NBTTagCompound tag = new NBTTagCompound(); + tag.setTag("MEInputBus", writeConfigToTag()); + dataStick.setTagCompound(tag); + dataStick.setTranslatableName("gregtech.machine.me.item_import.data_stick.name"); + player.sendStatusMessage(new TextComponentTranslation("gregtech.machine.me.import_copy_settings"), true); + } + + protected NBTTagCompound writeConfigToTag() { + NBTTagCompound tag = new NBTTagCompound(); + NBTTagCompound configStacks = new NBTTagCompound(); + tag.setTag("ConfigStacks", configStacks); + for (int i = 0; i < CONFIG_SIZE; i++) { + var slot = this.aeItemHandler.getInventory()[i]; + IAEItemStack config = slot.getConfig(); + if (config == null) { + continue; + } + NBTTagCompound stackNbt = new NBTTagCompound(); + config.getDefinition().writeToNBT(stackNbt); + configStacks.setTag(Integer.toString(i), stackNbt); + } + tag.setByte("GhostCircuit", (byte) this.circuitInventory.getCircuitValue()); + return tag; + } + + @Override + public final boolean onDataStickRightClick(EntityPlayer player, ItemStack dataStick) { + NBTTagCompound tag = dataStick.getTagCompound(); + if (tag == null || !tag.hasKey("MEInputBus")) { + return false; + } + readConfigFromTag(tag.getCompoundTag("MEInputBus")); + syncME(); + player.sendStatusMessage(new TextComponentTranslation("gregtech.machine.me.import_paste_settings"), true); + return true; + } + + protected void readConfigFromTag(NBTTagCompound tag) { + if (tag.hasKey("ConfigStacks")) { + NBTTagCompound configStacks = tag.getCompoundTag("ConfigStacks"); + for (int i = 0; i < CONFIG_SIZE; i++) { + String key = Integer.toString(i); + if (configStacks.hasKey(key)) { + NBTTagCompound configTag = configStacks.getCompoundTag(key); + this.aeItemHandler.getInventory()[i].setConfig(WrappedItemStack.fromNBT(configTag)); + } else { + this.aeItemHandler.getInventory()[i].setConfig(null); + } + } + } + if (tag.hasKey("GhostCircuit")) { + this.setGhostCircuitConfig(tag.getByte("GhostCircuit")); + } + } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEInputHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEInputHatch.java index c864cecff64..4e510077787 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEInputHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEInputHatch.java @@ -3,6 +3,7 @@ import gregtech.api.GTValues; import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.capability.IDataStickIntractable; import gregtech.api.capability.impl.FluidTankList; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; @@ -26,6 +27,7 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.IFluidTank; @@ -44,7 +46,7 @@ import java.util.List; public class MetaTileEntityMEInputHatch extends MetaTileEntityAEHostablePart - implements IMultiblockAbilityPart { + implements IMultiblockAbilityPart, IDataStickIntractable { public final static String FLUID_BUFFER_TAG = "FluidTanks"; public final static String WORKING_TAG = "WorkingEnabled"; @@ -257,6 +259,7 @@ public void addInformation(ItemStack stack, @Nullable World player, @NotNull Lis tooltip.add(I18n.format("gregtech.machine.fluid_hatch.import.tooltip")); tooltip.add(I18n.format("gregtech.machine.me.fluid_import.tooltip")); tooltip.add(I18n.format("gregtech.machine.me_import_fluid_hatch.configs.tooltip")); + tooltip.add(I18n.format("gregtech.machine.me.copy_paste.tooltip")); tooltip.add(I18n.format("gregtech.universal.enabled")); } @@ -269,4 +272,57 @@ public MultiblockAbility getAbility() { public void registerAbilities(List list) { list.addAll(Arrays.asList(this.getAEFluidHandler().getInventory())); } + + @Override + public final void onDataStickLeftClick(EntityPlayer player, ItemStack dataStick) { + NBTTagCompound tag = new NBTTagCompound(); + tag.setTag("MEInputHatch", writeConfigToTag()); + dataStick.setTagCompound(tag); + dataStick.setTranslatableName("gregtech.machine.me.fluid_import.data_stick.name"); + player.sendStatusMessage(new TextComponentTranslation("gregtech.machine.me.import_copy_settings"), true); + } + + protected NBTTagCompound writeConfigToTag() { + NBTTagCompound tag = new NBTTagCompound(); + NBTTagCompound configStacks = new NBTTagCompound(); + tag.setTag("ConfigStacks", configStacks); + for (int i = 0; i < CONFIG_SIZE; i++) { + var slot = this.aeFluidHandler.getInventory()[i]; + IAEFluidStack config = slot.getConfig(); + if (config == null) { + continue; + } + NBTTagCompound stackNbt = new NBTTagCompound(); + config.writeToNBT(stackNbt); + configStacks.setTag(Integer.toString(i), stackNbt); + } + return tag; + } + + @Override + public final boolean onDataStickRightClick(EntityPlayer player, ItemStack dataStick) { + NBTTagCompound tag = dataStick.getTagCompound(); + if (tag == null || !tag.hasKey("MEInputHatch")) { + return false; + } + readConfigFromTag(tag.getCompoundTag("MEInputHatch")); + syncME(); + player.sendStatusMessage(new TextComponentTranslation("gregtech.machine.me.import_paste_settings"), true); + return true; + } + + protected void readConfigFromTag(NBTTagCompound tag) { + if (tag.hasKey("ConfigStacks")) { + NBTTagCompound configStacks = tag.getCompoundTag("ConfigStacks"); + for (int i = 0; i < CONFIG_SIZE; i++) { + String key = Integer.toString(i); + if (configStacks.hasKey(key)) { + NBTTagCompound configTag = configStacks.getCompoundTag(key); + this.aeFluidHandler.getInventory()[i].setConfig(WrappedFluidStack.fromNBT(configTag)); + } else { + this.aeFluidHandler.getInventory()[i].setConfig(null); + } + } + } + } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEStockingBus.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEStockingBus.java index 99928574f82..f8bd7a5850a 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEStockingBus.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEStockingBus.java @@ -358,10 +358,38 @@ public void addInformation(ItemStack stack, @Nullable World player, @NotNull Lis tooltip.add(I18n.format("gregtech.machine.item_bus.import.tooltip")); tooltip.add(I18n.format("gregtech.machine.me.stocking_item.tooltip")); tooltip.add(I18n.format("gregtech.machine.me_import_item_hatch.configs.tooltip")); + tooltip.add(I18n.format("gregtech.machine.me.copy_paste.tooltip")); tooltip.add(I18n.format("gregtech.machine.me.stocking_item.tooltip.2")); tooltip.add(I18n.format("gregtech.universal.enabled")); } + @Override + protected NBTTagCompound writeConfigToTag() { + if (!autoPull) { + NBTTagCompound tag = super.writeConfigToTag(); + tag.setBoolean("AutoPull", false); + return tag; + } + // if in auto-pull, no need to write actual configured slots, but still need to write the ghost circuit + NBTTagCompound tag = new NBTTagCompound(); + tag.setBoolean("AutoPull", true); + tag.setByte("GhostCircuit", (byte) this.circuitInventory.getCircuitValue()); + return tag; + } + + @Override + protected void readConfigFromTag(NBTTagCompound tag) { + if (tag.getBoolean("AutoPull")) { + // if being set to auto-pull, no need to read the configured slots + this.setAutoPull(true); + this.setGhostCircuitConfig(tag.getByte("GhostCircuit")); + return; + } + // set auto pull first to avoid issues with clearing the config after reading from the data stick + this.setAutoPull(false); + super.readConfigFromTag(tag); + } + private static class ExportOnlyAEStockingItemList extends ExportOnlyAEItemList { private final MetaTileEntityMEStockingBus holder; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEStockingHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEStockingHatch.java index 1693ece229b..fcc9e1e7d12 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEStockingHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/appeng/MetaTileEntityMEStockingHatch.java @@ -263,10 +263,36 @@ public void addInformation(ItemStack stack, @Nullable World player, @NotNull Lis tooltip.add(I18n.format("gregtech.machine.fluid_hatch.import.tooltip")); tooltip.add(I18n.format("gregtech.machine.me.stocking_fluid.tooltip")); tooltip.add(I18n.format("gregtech.machine.me_import_fluid_hatch.configs.tooltip")); + tooltip.add(I18n.format("gregtech.machine.me.copy_paste.tooltip")); tooltip.add(I18n.format("gregtech.machine.me.stocking_fluid.tooltip.2")); tooltip.add(I18n.format("gregtech.universal.enabled")); } + @Override + protected NBTTagCompound writeConfigToTag() { + if (!autoPull) { + NBTTagCompound tag = super.writeConfigToTag(); + tag.setBoolean("AutoPull", false); + return tag; + } + // if in auto-pull, no need to write actual configured slots, but still need to write the ghost circuit + NBTTagCompound tag = new NBTTagCompound(); + tag.setBoolean("AutoPull", true); + return tag; + } + + @Override + protected void readConfigFromTag(NBTTagCompound tag) { + if (tag.getBoolean("AutoPull")) { + // if being set to auto-pull, no need to read the configured slots + this.setAutoPull(true); + return; + } + // set auto pull first to avoid issues with clearing the config after reading from the data stick + this.setAutoPull(false); + super.readConfigFromTag(tag); + } + private static class ExportOnlyAEStockingFluidSlot extends ExportOnlyAEFluidSlot { public ExportOnlyAEStockingFluidSlot(MetaTileEntityMEStockingHatch holder, IAEFluidStack config, diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 42c4c0ac26c..5d1adf35389 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -5278,6 +5278,11 @@ gregtech.machine.me.fluid_export.tooltip=Stores fluids directly into the ME netw gregtech.machine.me.fluid_export.tooltip.2=Can cache an infinite amount of fluid gregtech.machine.me.stocking_auto_pull_enabled=Auto-Pull Enabled gregtech.machine.me.stocking_auto_pull_disabled=Auto-Pull Disabled +gregtech.machine.me.copy_paste.tooltip=Left-click with Data Stick to copy settings, right-click to apply +gregtech.machine.me.import_copy_settings=Saved settings to Data Stick +gregtech.machine.me.import_paste_settings=Applied settings from Data Stick +gregtech.machine.me.item_import.data_stick.name=§oME Input Bus Configuration Data +gregtech.machine.me.fluid_import.data_stick.name=§oME Input Hatch Configuration Data # Universal tooltips gregtech.universal.tooltip.voltage_in=§aVoltage IN: §f%,d EU/t (%s§f) From aff043cfaa43f8dd44c45fb5de602fa2d3b56282 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Wed, 27 Mar 2024 19:09:13 -0700 Subject: [PATCH 12/25] Fix LCE/ECE from parallelizing too much (#2426) --- .../api/capability/impl/MultiblockFuelRecipeLogic.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/gregtech/api/capability/impl/MultiblockFuelRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/MultiblockFuelRecipeLogic.java index 9f93440025c..168ed40c67c 100644 --- a/src/main/java/gregtech/api/capability/impl/MultiblockFuelRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/MultiblockFuelRecipeLogic.java @@ -78,6 +78,11 @@ public int getParallelLimit() { return Integer.MAX_VALUE; } + @Override + protected long getMaxParallelVoltage() { + return getMaxVoltage(); + } + /** * Boost the energy production. * Should not change the state of the workable logic. Only read current values. From edbdaf4871412c59c30bf9fdb9daf6a7c1b438eb Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Wed, 27 Mar 2024 22:47:23 -0400 Subject: [PATCH 13/25] allow multiple build actions per recipemap (#2278) --- .../api/recipes/RecipeBuildAction.java | 17 +++++ .../gregtech/api/recipes/RecipeBuilder.java | 46 ++++++++----- .../java/gregtech/api/recipes/RecipeMap.java | 55 +++++++++++++--- .../api/recipes/RecipeMapBuilder.java | 26 ++++++++ .../java/gregtech/api/recipes/RecipeMaps.java | 66 +++++++++---------- 5 files changed, 150 insertions(+), 60 deletions(-) create mode 100644 src/main/java/gregtech/api/recipes/RecipeBuildAction.java diff --git a/src/main/java/gregtech/api/recipes/RecipeBuildAction.java b/src/main/java/gregtech/api/recipes/RecipeBuildAction.java new file mode 100644 index 00000000000..f7310129276 --- /dev/null +++ b/src/main/java/gregtech/api/recipes/RecipeBuildAction.java @@ -0,0 +1,17 @@ +package gregtech.api.recipes; + +import org.jetbrains.annotations.NotNull; + +@FunctionalInterface +public interface RecipeBuildAction> { + + /** + * Process a RecipeBuilder to perform an action with. + *

    + * Do not call {@link RecipeBuilder#buildAndRegister()} on the passed builder. + * It is safe to do so only on other builders, i.e. created through {@link RecipeBuilder#copy()}. + * + * @param builder the builder to utilize + */ + void accept(@NotNull R builder); +} diff --git a/src/main/java/gregtech/api/recipes/RecipeBuilder.java b/src/main/java/gregtech/api/recipes/RecipeBuilder.java index 1b59129381a..3ff85e2ce99 100644 --- a/src/main/java/gregtech/api/recipes/RecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeBuilder.java @@ -9,7 +9,11 @@ import gregtech.api.recipes.chance.output.ChancedOutputLogic; import gregtech.api.recipes.chance.output.impl.ChancedFluidOutput; import gregtech.api.recipes.chance.output.impl.ChancedItemOutput; -import gregtech.api.recipes.ingredients.*; +import gregtech.api.recipes.ingredients.GTRecipeFluidInput; +import gregtech.api.recipes.ingredients.GTRecipeInput; +import gregtech.api.recipes.ingredients.GTRecipeItemInput; +import gregtech.api.recipes.ingredients.GTRecipeOreInput; +import gregtech.api.recipes.ingredients.IntCircuitIngredient; import gregtech.api.recipes.ingredients.nbtmatch.NBTCondition; import gregtech.api.recipes.ingredients.nbtmatch.NBTMatcher; import gregtech.api.recipes.recipeproperties.CleanroomProperty; @@ -43,11 +47,17 @@ import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntLists; import org.apache.commons.lang3.builder.ToStringBuilder; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; -import java.util.function.Consumer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; /** * @see Recipe @@ -74,9 +84,8 @@ public class RecipeBuilder> { protected GTRecipeCategory category; protected boolean isCTRecipe = false; protected int parallel = 0; - protected Consumer onBuildAction = null; protected EnumValidationResult recipeStatus = EnumValidationResult.VALID; - protected IRecipePropertyStorage recipePropertyStorage = null; + protected @Nullable IRecipePropertyStorage recipePropertyStorage = null; protected boolean recipePropertyStorageErrored = false; protected RecipeBuilder() { @@ -125,8 +134,8 @@ protected RecipeBuilder(RecipeBuilder recipeBuilder) { this.EUt = recipeBuilder.EUt; this.hidden = recipeBuilder.hidden; this.category = recipeBuilder.category; - this.onBuildAction = recipeBuilder.onBuildAction; - this.recipePropertyStorage = recipeBuilder.recipePropertyStorage; + this.recipePropertyStorage = recipeBuilder.recipePropertyStorage == null ? null : + recipeBuilder.recipePropertyStorage.copy(); if (this.recipePropertyStorage != null) { this.recipePropertyStorage = this.recipePropertyStorage.copy(); } @@ -933,19 +942,26 @@ protected static String getRequiredString(int max, int actual, @NotNull String t return out; } - protected R onBuild(Consumer consumer) { - this.onBuildAction = consumer; - return (R) this; - } - + /** + * @deprecated Obsolete. Does not need calling. + */ + @ApiStatus.Obsolete + @ApiStatus.ScheduledForRemoval(inVersion = "2.9") + @Deprecated protected R invalidateOnBuildAction() { - this.onBuildAction = null; return (R) this; } + /** + * Build and register the recipe, if valid. + * Do not call outside of the + * {@link net.minecraftforge.event.RegistryEvent.Register} event for recipes. + * + */ + @MustBeInvokedByOverriders public void buildAndRegister() { - if (onBuildAction != null) { - onBuildAction.accept((R) this); + for (RecipeBuildAction action : recipeMap.getBuildActions()) { + action.accept((R) this); } ValidationResult validationResult = build(); recipeMap.addRecipe(validationResult); diff --git a/src/main/java/gregtech/api/recipes/RecipeMap.java b/src/main/java/gregtech/api/recipes/RecipeMap.java index 1103deef462..218489f1c1d 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMap.java +++ b/src/main/java/gregtech/api/recipes/RecipeMap.java @@ -39,6 +39,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.Optional.Method; @@ -59,6 +60,7 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; import stanhebben.zenscript.annotations.Optional; import stanhebben.zenscript.annotations.ZenClass; import stanhebben.zenscript.annotations.ZenGetter; @@ -75,9 +77,7 @@ import java.util.Map; import java.util.Set; import java.util.WeakHashMap; -import java.util.function.Consumer; import java.util.function.DoubleSupplier; -import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -124,9 +124,9 @@ public class RecipeMap> { private final Map> recipeByCategory = new Object2ObjectOpenHashMap<>(); - private Consumer onRecipeBuildAction; - protected SoundEvent sound; - private RecipeMap smallRecipeMap; + private final Map> recipeBuildActions = new Object2ObjectOpenHashMap<>(); + protected @Nullable SoundEvent sound; + private @Nullable RecipeMap smallRecipeMap; /** * Create and register new instance of RecipeMap with specified properties. All @@ -140,7 +140,7 @@ public class RecipeMap> { * @param defaultRecipeBuilder the default RecipeBuilder for the RecipeMap * @param isHidden if the RecipeMap should have a category in JEI * - * @deprecated {@link #RecipeMap(String, RecipeBuilder, Function, int, int, int, int)} + * @deprecated {@link RecipeMap#RecipeMap(String, R, RecipeMapUIFunction, int, int, int, int)} */ @ApiStatus.ScheduledForRemoval(inVersion = "2.9") @Deprecated @@ -169,7 +169,7 @@ public RecipeMap(@NotNull String unlocalizedName, * @param defaultRecipeBuilder the default RecipeBuilder for the RecipeMap * @param isHidden if the RecipeMap should have a category in JEI * - * @deprecated {@link #RecipeMap(String, RecipeBuilder, Function, int, int, int, int)} + * @deprecated {@link RecipeMap#RecipeMap(String, R, RecipeMapUIFunction, int, int, int, int)} */ @ApiStatus.ScheduledForRemoval(inVersion = "2.9") @Deprecated @@ -311,11 +311,46 @@ public RecipeMap setChanceFunction(@NotNull ChanceBoostFunction function) { return this; } - public RecipeMap onRecipeBuild(Consumer consumer) { - onRecipeBuildAction = consumer; + /** + * Add a recipe build action to be performed upon this RecipeMap's builder's recipe registration. + * + * @param name the unique name of the action + * @param action the action to perform + * @return this + */ + public RecipeMap onRecipeBuild(@NotNull ResourceLocation name, @NotNull RecipeBuildAction action) { + if (recipeBuildActions.containsKey(name)) { + throw new IllegalArgumentException("Cannot register RecipeBuildAction with duplicate name: " + name); + } + recipeBuildActions.put(name, action); return this; } + /** + * @param name the name of the build action to remove + */ + public void removeBuildAction(@NotNull ResourceLocation name) { + recipeBuildActions.remove(name); + } + + /** + * Add a recipe build action to be performed upon this RecipeMap's builder's recipe registration. + * + * @param actions the actions to perform + */ + @ApiStatus.Internal + protected void onRecipeBuild(@NotNull Map> actions) { + recipeBuildActions.putAll(actions); + } + + /** + * @return the build actions for this RecipeMap's default RecipeBuilder + */ + @ApiStatus.Internal + protected @UnmodifiableView @NotNull Collection<@NotNull RecipeBuildAction> getBuildActions() { + return this.recipeBuildActions.values(); + } + public RecipeMap allowEmptyOutput() { this.allowEmptyOutput = true; return this; @@ -1326,7 +1361,7 @@ public String getUnlocalizedName() { } public R recipeBuilder() { - return recipeBuilderSample.copy().onBuild(onRecipeBuildAction); + return recipeBuilderSample.copy(); } /** diff --git a/src/main/java/gregtech/api/recipes/RecipeMapBuilder.java b/src/main/java/gregtech/api/recipes/RecipeMapBuilder.java index 2d6e810cac8..8995cf529aa 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMapBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeMapBuilder.java @@ -5,13 +5,17 @@ import gregtech.api.recipes.ui.RecipeMapUI; import gregtech.api.recipes.ui.RecipeMapUIFunction; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import it.unimi.dsi.fastutil.bytes.Byte2ObjectArrayMap; import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Map; + import static gregtech.api.recipes.ui.RecipeMapUI.computeOverlayKey; public class RecipeMapBuilder> { @@ -41,6 +45,8 @@ public class RecipeMapBuilder> { private SoundEvent sound; private boolean allowEmptyOutputs; + private @Nullable Map> buildActions; + /** * @param unlocalizedName the name of the recipemap * @param defaultRecipeBuilder the default recipe builder of the recipemap @@ -247,6 +253,23 @@ public RecipeMapBuilder(@NotNull String unlocalizedName, @NotNull B defaultRecip return this; } + /** + * Add a recipe build action to be performed upon this RecipeMap's builder's recipe registration. + * + * @param name the unique name of the action + * @param action the action to perform + * @return this + */ + public @NotNull RecipeMapBuilder onBuild(@NotNull ResourceLocation name, @NotNull RecipeBuildAction action) { + if (buildActions == null) { + buildActions = new Object2ObjectOpenHashMap<>(); + } else if (buildActions.containsKey(name)) { + throw new IllegalArgumentException("Cannot register RecipeBuildAction with duplicate name: " + name); + } + buildActions.put(name, action); + return this; + } + /** * Do not call this twice. RecipeMapBuilders are not re-usable. * @@ -260,6 +283,9 @@ public RecipeMapBuilder(@NotNull String unlocalizedName, @NotNull B defaultRecip if (allowEmptyOutputs) { recipeMap.allowEmptyOutput(); } + if (buildActions != null) { + recipeMap.onRecipeBuild(buildActions); + } return recipeMap; } } diff --git a/src/main/java/gregtech/api/recipes/RecipeMaps.java b/src/main/java/gregtech/api/recipes/RecipeMaps.java index 9cd9547457f..b5bdde0fa94 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMaps.java +++ b/src/main/java/gregtech/api/recipes/RecipeMaps.java @@ -43,6 +43,7 @@ import stanhebben.zenscript.annotations.ZenProperty; import static gregtech.api.GTValues.*; +import static gregtech.api.util.GTUtility.gregtechId; /** * Notes: @@ -122,13 +123,12 @@ public final class RecipeMaps { .fluidOutputs(1) .progressBar(GuiTextures.PROGRESS_BAR_ARC_FURNACE) .sound(GTSoundEvents.ARC) - .build() - .onRecipeBuild(recipeBuilder -> { - recipeBuilder.invalidateOnBuildAction(); + .onBuild(gregtechId("arc_furnace_oxygen"), recipeBuilder -> { if (recipeBuilder.getFluidInputs().isEmpty()) { recipeBuilder.fluidInputs(Materials.Oxygen.getFluid(recipeBuilder.getDuration())); } - }); + }) + .build(); /** * Example: @@ -151,9 +151,7 @@ public final class RecipeMaps { .itemSlotOverlay(GuiTextures.CIRCUIT_OVERLAY, false) .progressBar(GuiTextures.PROGRESS_BAR_CIRCUIT) .sound(GTSoundEvents.ASSEMBLER) - .build() - .onRecipeBuild(recipeBuilder -> { - recipeBuilder.invalidateOnBuildAction(); + .onBuild(gregtechId("assembler_solder"), recipeBuilder -> { var fluidInputs = recipeBuilder.getFluidInputs(); if (fluidInputs.size() == 1 && fluidInputs.get(0).getInputFluidStack().getFluid() == Materials.SolderingAlloy.getFluid()) { @@ -162,7 +160,8 @@ public final class RecipeMaps { recipeBuilder.copy().clearFluidInputs().fluidInputs(Materials.Tin.getFluid(amount * 2)) .buildAndRegister(); } - + }) + .onBuild(gregtechId("assembler_recycling"), recipeBuilder -> { if (recipeBuilder.isWithRecycling()) { // ignore input fluids for recycling ItemStack outputStack = recipeBuilder.getOutputs().get(0); @@ -172,7 +171,8 @@ public final class RecipeMaps { OreDictUnifier.registerOre(outputStack, info); } } - }); + }) + .build(); /** * Example: @@ -191,12 +191,14 @@ public final class RecipeMaps { * .duration(600).EUt(6000).buildAndRegister(); * * - * The Assembly Line Recipe Builder has no special properties/build actions yet, but will in the future + * The Assembly Line Recipe Builder creates additional Research Recipes for its outputs in the Scanner or Research + * Station when specified. */ @ZenProperty public static final RecipeMap ASSEMBLY_LINE_RECIPES = new RecipeMapAssemblyLine<>( "assembly_line", new AssemblyLineRecipeBuilder(), AssemblyLineUI::new) - .onRecipeBuild(AssemblyLineManager::createDefaultResearchRecipe); + .onRecipeBuild(gregtechId("default_research_recipe"), + AssemblyLineManager::createDefaultResearchRecipe); /** * Example: @@ -436,21 +438,18 @@ public final class RecipeMaps { .fluidSlotOverlay(GuiTextures.VIAL_OVERLAY_2, true) .progressBar(GuiTextures.PROGRESS_BAR_ARROW_MULTIPLE) .sound(GTValues.FOOLS.get() ? GTSoundEvents.SCIENCE : GTSoundEvents.CHEMICAL_REACTOR) - .build() - .onRecipeBuild(recipeBuilder -> { - recipeBuilder.invalidateOnBuildAction(); - RecipeMaps.LARGE_CHEMICAL_RECIPES.recipeBuilder() - .inputs(recipeBuilder.getInputs().toArray(new GTRecipeInput[0])) - .fluidInputs(recipeBuilder.getFluidInputs()) - .outputs(recipeBuilder.getOutputs()) - .chancedOutputs(recipeBuilder.getChancedOutputs()) - .fluidOutputs(recipeBuilder.getFluidOutputs()) - .chancedFluidOutputs(recipeBuilder.getChancedFluidOutputs()) - .cleanroom(recipeBuilder.getCleanroom()) - .duration(recipeBuilder.getDuration()) - .EUt(recipeBuilder.getEUt()) - .buildAndRegister(); - }); + .onBuild(gregtechId("lcr_copy"), recipeBuilder -> RecipeMaps.LARGE_CHEMICAL_RECIPES.recipeBuilder() + .inputs(recipeBuilder.getInputs().toArray(new GTRecipeInput[0])) + .fluidInputs(recipeBuilder.getFluidInputs()) + .outputs(recipeBuilder.getOutputs()) + .chancedOutputs(recipeBuilder.getChancedOutputs()) + .fluidOutputs(recipeBuilder.getFluidOutputs()) + .chancedFluidOutputs(recipeBuilder.getChancedFluidOutputs()) + .cleanroom(recipeBuilder.getCleanroom()) + .duration(recipeBuilder.getDuration()) + .EUt(recipeBuilder.getEUt()) + .buildAndRegister()) + .build(); /** * Example: @@ -488,9 +487,7 @@ public final class RecipeMaps { .itemSlotOverlay(GuiTextures.CIRCUIT_OVERLAY, false) .progressBar(GuiTextures.PROGRESS_BAR_CIRCUIT_ASSEMBLER) .sound(GTSoundEvents.ASSEMBLER) - .build() - .onRecipeBuild(recipeBuilder -> { - recipeBuilder.invalidateOnBuildAction(); + .onBuild(gregtechId("circuit_assembler_solder"), recipeBuilder -> { if (recipeBuilder.getFluidInputs().isEmpty()) { recipeBuilder.copy() .fluidInputs(Materials.SolderingAlloy.getFluid(Math.max(1, @@ -503,7 +500,8 @@ public final class RecipeMaps { recipeBuilder.fluidInputs(Materials.Tin.getFluid(Math.max(1, GTValues.L * recipeBuilder.getSolderMultiplier()))); } - }); + }) + .build(); /** * Example: @@ -611,11 +609,8 @@ public final class RecipeMaps { .itemSlotOverlay(GuiTextures.DUST_OVERLAY, true, true) .progressBar(GuiTextures.PROGRESS_BAR_SLICE) .sound(GTSoundEvents.CUT) - .build() - .onRecipeBuild(recipeBuilder -> { - recipeBuilder.invalidateOnBuildAction(); + .onBuild(gregtechId("cutter_fluid"), recipeBuilder -> { if (recipeBuilder.getFluidInputs().isEmpty()) { - int duration = recipeBuilder.getDuration(); int eut = recipeBuilder.getEUt(); recipeBuilder @@ -641,7 +636,8 @@ public final class RecipeMaps { .duration(Math.max(1, duration)); } - }); + }) + .build(); /** * Examples: From e6cc4930ca204be09d0721198b274f344c0add4e Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Thu, 28 Mar 2024 18:00:13 -0400 Subject: [PATCH 14/25] add ItemStack inputNBT method (#2431) --- .../gregtech/api/recipes/RecipeBuilder.java | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/RecipeBuilder.java b/src/main/java/gregtech/api/recipes/RecipeBuilder.java index 3ff85e2ce99..7f73f62f32f 100644 --- a/src/main/java/gregtech/api/recipes/RecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeBuilder.java @@ -331,20 +331,20 @@ public R inputNBT(OrePrefix orePrefix, Material material, int count, NBTMatcher } public R inputNBT(Item item, NBTMatcher matcher, NBTCondition condition) { - return inputNBT(new GTRecipeItemInput(new ItemStack(item)), matcher, condition); + return inputNBT(new ItemStack(item), matcher, condition); } public R inputNBT(Item item, int count, NBTMatcher matcher, NBTCondition condition) { - return inputNBT(new GTRecipeItemInput(new ItemStack(item), count), matcher, condition); + return inputNBT(new ItemStack(item, count), matcher, condition); } public R inputNBT(Item item, int count, int meta, NBTMatcher matcher, NBTCondition condition) { - return inputNBT(new GTRecipeItemInput(new ItemStack(item, count, meta)), matcher, condition); + return inputNBT(new ItemStack(item, count, meta), matcher, condition); } public R inputNBT(Item item, int count, @SuppressWarnings("unused") boolean wild, NBTMatcher matcher, NBTCondition condition) { - return inputNBT(new GTRecipeItemInput(new ItemStack(item, count, GTValues.W)), matcher, condition); + return inputNBT(new ItemStack(item, count, GTValues.W), matcher, condition); } public R inputNBT(Block block, NBTMatcher matcher, NBTCondition condition) { @@ -352,28 +352,40 @@ public R inputNBT(Block block, NBTMatcher matcher, NBTCondition condition) { } public R inputNBT(Block block, int count, NBTMatcher matcher, NBTCondition condition) { - return inputNBT(new GTRecipeItemInput(new ItemStack(block, count)), matcher, condition); + return inputNBT(new ItemStack(block, count), matcher, condition); } public R inputNBT(Block block, int count, @SuppressWarnings("unused") boolean wild, NBTMatcher matcher, NBTCondition condition) { - return inputNBT(new GTRecipeItemInput(new ItemStack(block, count, GTValues.W)), matcher, condition); + return inputNBT(new ItemStack(block, count, GTValues.W), matcher, condition); } public R inputNBT(MetaItem.MetaValueItem item, int count, NBTMatcher matcher, NBTCondition condition) { - return inputNBT(new GTRecipeItemInput(item.getStackForm(count)), matcher, condition); + return inputNBT(item.getStackForm(count), matcher, condition); } public R inputNBT(MetaItem.MetaValueItem item, NBTMatcher matcher, NBTCondition condition) { - return inputNBT(new GTRecipeItemInput(item.getStackForm()), matcher, condition); + return inputNBT(item.getStackForm(), matcher, condition); } public R inputNBT(MetaTileEntity mte, NBTMatcher matcher, NBTCondition condition) { - return inputNBT(new GTRecipeItemInput(mte.getStackForm()), matcher, condition); + return inputNBT(mte.getStackForm(), matcher, condition); } public R inputNBT(MetaTileEntity mte, int amount, NBTMatcher matcher, NBTCondition condition) { - return inputNBT(new GTRecipeItemInput(mte.getStackForm(amount)), matcher, condition); + return inputNBT(mte.getStackForm(amount), matcher, condition); + } + + /** + * NBT tags are stripped from the input stack and are not automatically checked. + * + * @param stack the itemstack to input. + * @param matcher the matcher for the stack's nbt + * @param condition the condition for the stack's nbt + * @return this + */ + public R inputNBT(@NotNull ItemStack stack, NBTMatcher matcher, NBTCondition condition) { + return inputNBT(new GTRecipeItemInput(stack), matcher, condition); } public R inputs(ItemStack... inputs) { From 456c1aed15f41d05beb5d05423713880c00ea946 Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Sun, 31 Mar 2024 13:01:26 -0400 Subject: [PATCH 15/25] Reduce allocations in RecipeBuilder (#2434) --- .../gregtech/api/recipes/RecipeBuilder.java | 57 +++++++++++++++++-- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/RecipeBuilder.java b/src/main/java/gregtech/api/recipes/RecipeBuilder.java index 7f73f62f32f..74357bd8130 100644 --- a/src/main/java/gregtech/api/recipes/RecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeBuilder.java @@ -57,7 +57,6 @@ import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Objects; /** * @see Recipe @@ -388,10 +387,21 @@ public R inputNBT(@NotNull ItemStack stack, NBTMatcher matcher, NBTCondition con return inputNBT(new GTRecipeItemInput(stack), matcher, condition); } + public R inputs(ItemStack input) { + if (input == null || input.isEmpty()) { + GTLog.logger.error("Input cannot be null or empty. Input: {}", input); + GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + recipeStatus = EnumValidationResult.INVALID; + } else { + this.inputs.add(new GTRecipeItemInput(input)); + } + return (R) this; + } + public R inputs(ItemStack... inputs) { for (ItemStack input : inputs) { if (input == null || input.isEmpty()) { - GTLog.logger.error("Input cannot contain null or empty ItemStacks. Inputs: {}", input); + GTLog.logger.error("Inputs cannot contain null or empty ItemStacks. Inputs: {}", input); GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); recipeStatus = EnumValidationResult.INVALID; continue; @@ -414,10 +424,21 @@ public R inputStacks(Collection inputs) { return (R) this; } + public R inputs(GTRecipeInput input) { + if (input.getAmount() < 0) { + GTLog.logger.error("Input count cannot be less than 0. Actual: {}.", input.getAmount()); + GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + recipeStatus = EnumValidationResult.INVALID; + } else { + this.inputs.add(input); + } + return (R) this; + } + public R inputs(GTRecipeInput... inputs) { for (GTRecipeInput input : inputs) { if (input.getAmount() < 0) { - GTLog.logger.error("Count cannot be less than 0. Actual: {}.", input.getAmount()); + GTLog.logger.error("Input count cannot be less than 0. Actual: {}.", input.getAmount()); GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); recipeStatus = EnumValidationResult.INVALID; continue; @@ -532,6 +553,13 @@ public R output(MetaTileEntity mte, int amount) { return outputs(mte.getStackForm(amount)); } + public R outputs(ItemStack output) { + if (output != null && !output.isEmpty()) { + this.outputs.add(output); + } + return (R) this; + } + public R outputs(ItemStack... outputs) { return outputs(Arrays.asList(outputs)); } @@ -558,13 +586,25 @@ public R fluidInputs(GTRecipeInput fluidIngredient) { return (R) this; } + public R fluidInputs(FluidStack input) { + if (input != null && input.amount > 0) { + this.fluidInputs.add(new GTRecipeFluidInput(input)); + } else if (input != null) { + GTLog.logger.error("Fluid Input count cannot be less than 0. Actual: {}.", input.amount); + GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + } else { + GTLog.logger.error("FluidStack cannot be null."); + } + return (R) this; + } + public R fluidInputs(FluidStack... fluidStacks) { ArrayList fluidIngredients = new ArrayList<>(); for (FluidStack fluidStack : fluidStacks) { if (fluidStack != null && fluidStack.amount > 0) { fluidIngredients.add(new GTRecipeFluidInput(fluidStack)); } else if (fluidStack != null) { - GTLog.logger.error("Count cannot be less than 0. Actual: {}.", fluidStack.amount); + GTLog.logger.error("Fluid Input count cannot be less than 0. Actual: {}.", fluidStack.amount); GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); } else { GTLog.logger.error("FluidStack cannot be null."); @@ -579,13 +619,20 @@ public R clearFluidInputs() { return (R) this; } + public R fluidOutputs(FluidStack output) { + if (output != null && output.amount > 0) { + this.fluidOutputs.add(output); + } + return (R) this; + } + public R fluidOutputs(FluidStack... outputs) { return fluidOutputs(Arrays.asList(outputs)); } public R fluidOutputs(Collection outputs) { outputs = new ArrayList<>(outputs); - outputs.removeIf(Objects::isNull); + outputs.removeIf(o -> o == null || o.amount <= 0); this.fluidOutputs.addAll(outputs); return (R) this; } From 069c586bd40237fa4bfd0ec757588552a3c70d12 Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Tue, 2 Apr 2024 17:03:21 -0400 Subject: [PATCH 16/25] cleanup stacktrace logging for recipe errors (#2438) --- .../java/gregtech/api/recipes/ModHandler.java | 9 ++- .../gregtech/api/recipes/RecipeBuilder.java | 64 ++++++++----------- .../java/gregtech/api/recipes/RecipeMap.java | 43 +++++-------- .../builders/AssemblyLineRecipeBuilder.java | 4 +- .../recipes/builders/BlastRecipeBuilder.java | 2 +- .../CircuitAssemblerRecipeBuilder.java | 4 +- .../builders/ComputationRecipeBuilder.java | 4 +- .../recipes/builders/FusionRecipeBuilder.java | 2 +- .../builders/ImplosionRecipeBuilder.java | 4 +- .../nbtmatch/ListNBTCondition.java | 3 +- .../ingredients/nbtmatch/NBTCondition.java | 3 +- .../IRecipePropertyStorage.java | 2 - .../RecipePropertyStorage.java | 7 +- 13 files changed, 65 insertions(+), 86 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/ModHandler.java b/src/main/java/gregtech/api/recipes/ModHandler.java index 1fe7ce05f07..10e55ea68b1 100644 --- a/src/main/java/gregtech/api/recipes/ModHandler.java +++ b/src/main/java/gregtech/api/recipes/ModHandler.java @@ -49,7 +49,12 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Objects; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -752,6 +757,6 @@ public static boolean setErroredInvalidRecipe(@NotNull String message) throws Il } public static void logInvalidRecipe(@NotNull String message) { - GTLog.logger.warn("Invalid Recipe Found", new IllegalArgumentException(message)); + GTLog.logger.warn("Invalid Recipe Found: {}", message, new Throwable()); } } diff --git a/src/main/java/gregtech/api/recipes/RecipeBuilder.java b/src/main/java/gregtech/api/recipes/RecipeBuilder.java index 74357bd8130..2658ecca049 100644 --- a/src/main/java/gregtech/api/recipes/RecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeBuilder.java @@ -225,8 +225,7 @@ public boolean applyProperty(@NotNull RecipeProperty property, @Nullable Obje public R input(GTRecipeInput input) { if (input.getAmount() < 0) { - GTLog.logger.error("Count cannot be less than 0. Actual: {}.", input.getAmount()); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("Count cannot be less than 0. Actual: {}.", input.getAmount(), new Throwable()); } else { this.inputs.add(input); } @@ -295,18 +294,15 @@ public R input(MetaTileEntity mte, int amount) { public R inputNBT(GTRecipeInput input, NBTMatcher matcher, NBTCondition condition) { if (input.getAmount() < 0) { - GTLog.logger.error("Count cannot be less than 0. Actual: {}.", input.getAmount()); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("Count cannot be less than 0. Actual: {}.", input.getAmount(), new Throwable()); return (R) this; } if (matcher == null) { - GTLog.logger.error("NBTMatcher must not be null"); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("NBTMatcher must not be null", new Throwable()); return (R) this; } if (condition == null) { - GTLog.logger.error("NBTCondition must not be null"); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("NBTCondition must not be null", new Throwable()); return (R) this; } this.inputs.add(input.setNBTMatchingCondition(matcher, condition)); @@ -389,8 +385,7 @@ public R inputNBT(@NotNull ItemStack stack, NBTMatcher matcher, NBTCondition con public R inputs(ItemStack input) { if (input == null || input.isEmpty()) { - GTLog.logger.error("Input cannot be null or empty. Input: {}", input); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("Input cannot be null or empty. Input: {}", input, new Throwable()); recipeStatus = EnumValidationResult.INVALID; } else { this.inputs.add(new GTRecipeItemInput(input)); @@ -401,8 +396,8 @@ public R inputs(ItemStack input) { public R inputs(ItemStack... inputs) { for (ItemStack input : inputs) { if (input == null || input.isEmpty()) { - GTLog.logger.error("Inputs cannot contain null or empty ItemStacks. Inputs: {}", input); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("Inputs cannot contain null or empty ItemStacks. Inputs: {}", input, + new Throwable()); recipeStatus = EnumValidationResult.INVALID; continue; } @@ -414,8 +409,7 @@ public R inputs(ItemStack... inputs) { public R inputStacks(Collection inputs) { for (ItemStack input : inputs) { if (input == null || input.isEmpty()) { - GTLog.logger.error("Input cannot contain null or empty ItemStacks. Inputs: {}", input); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("Input cannot contain null or empty ItemStacks. Inputs: {}", input, new Throwable()); recipeStatus = EnumValidationResult.INVALID; continue; } @@ -426,8 +420,7 @@ public R inputStacks(Collection inputs) { public R inputs(GTRecipeInput input) { if (input.getAmount() < 0) { - GTLog.logger.error("Input count cannot be less than 0. Actual: {}.", input.getAmount()); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("Input count cannot be less than 0. Actual: {}.", input.getAmount(), new Throwable()); recipeStatus = EnumValidationResult.INVALID; } else { this.inputs.add(input); @@ -438,8 +431,8 @@ public R inputs(GTRecipeInput input) { public R inputs(GTRecipeInput... inputs) { for (GTRecipeInput input : inputs) { if (input.getAmount() < 0) { - GTLog.logger.error("Input count cannot be less than 0. Actual: {}.", input.getAmount()); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("Input count cannot be less than 0. Actual: {}.", input.getAmount(), + new Throwable()); recipeStatus = EnumValidationResult.INVALID; continue; } @@ -451,8 +444,7 @@ public R inputs(GTRecipeInput... inputs) { public R inputIngredients(Collection inputs) { for (GTRecipeInput input : inputs) { if (input.getAmount() < 0) { - GTLog.logger.error("Count cannot be less than 0. Actual: {}.", input.getAmount()); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("Count cannot be less than 0. Actual: {}.", input.getAmount(), new Throwable()); recipeStatus = EnumValidationResult.INVALID; continue; } @@ -501,8 +493,7 @@ public R notConsumable(FluidStack fluidStack) { public R circuitMeta(int circuitNumber) { if (IntCircuitIngredient.CIRCUIT_MIN > circuitNumber || circuitNumber > IntCircuitIngredient.CIRCUIT_MAX) { GTLog.logger.error("Integrated Circuit Number cannot be less than {} and more than {}", - IntCircuitIngredient.CIRCUIT_MIN, IntCircuitIngredient.CIRCUIT_MAX); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException("Invalid Integrated Circuit Number")); + IntCircuitIngredient.CIRCUIT_MIN, IntCircuitIngredient.CIRCUIT_MAX, new Throwable()); recipeStatus = EnumValidationResult.INVALID; return (R) this; } @@ -590,8 +581,7 @@ public R fluidInputs(FluidStack input) { if (input != null && input.amount > 0) { this.fluidInputs.add(new GTRecipeFluidInput(input)); } else if (input != null) { - GTLog.logger.error("Fluid Input count cannot be less than 0. Actual: {}.", input.amount); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("Fluid Input count cannot be less than 0. Actual: {}.", input.amount, new Throwable()); } else { GTLog.logger.error("FluidStack cannot be null."); } @@ -604,8 +594,8 @@ public R fluidInputs(FluidStack... fluidStacks) { if (fluidStack != null && fluidStack.amount > 0) { fluidIngredients.add(new GTRecipeFluidInput(fluidStack)); } else if (fluidStack != null) { - GTLog.logger.error("Fluid Input count cannot be less than 0. Actual: {}.", fluidStack.amount); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("Fluid Input count cannot be less than 0. Actual: {}.", fluidStack.amount, + new Throwable()); } else { GTLog.logger.error("FluidStack cannot be null."); } @@ -648,8 +638,7 @@ public R chancedOutput(ItemStack stack, int chance, int tierChanceBoost) { } if (0 >= chance || chance > ChancedOutputLogic.getMaxChancedValue()) { GTLog.logger.error("Chance cannot be less or equal to 0 or more than {}. Actual: {}.", - ChancedOutputLogic.getMaxChancedValue(), chance); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + ChancedOutputLogic.getMaxChancedValue(), chance, new Throwable()); recipeStatus = EnumValidationResult.INVALID; return (R) this; } @@ -696,8 +685,7 @@ public R chancedFluidOutput(FluidStack stack, int chance, int tierChanceBoost) { } if (0 >= chance || chance > ChancedOutputLogic.getMaxChancedValue()) { GTLog.logger.error("Chance cannot be less or equal to 0 or more than {}. Actual: {}.", - ChancedOutputLogic.getMaxChancedValue(), chance); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + ChancedOutputLogic.getMaxChancedValue(), chance, new Throwable()); recipeStatus = EnumValidationResult.INVALID; return (R) this; } @@ -934,31 +922,31 @@ protected EnumValidationResult validate() { return msg.postIfNotEmpty() ? EnumValidationResult.SKIP : EnumValidationResult.VALID; } if (EUt == 0) { - GTLog.logger.error("EU/t cannot be equal to 0", new IllegalArgumentException()); + GTLog.logger.error("EU/t cannot be equal to 0", new Throwable()); if (isCTRecipe) { - CraftTweakerAPI.logError("EU/t cannot be equal to 0", new IllegalArgumentException()); + CraftTweakerAPI.logError("EU/t cannot be equal to 0", new Throwable()); } recipeStatus = EnumValidationResult.INVALID; } if (duration <= 0) { - GTLog.logger.error("Duration cannot be less or equal to 0", new IllegalArgumentException()); + GTLog.logger.error("Duration cannot be less or equal to 0", new Throwable()); if (isCTRecipe) { - CraftTweakerAPI.logError("Duration cannot be less or equal to 0", new IllegalArgumentException()); + CraftTweakerAPI.logError("Duration cannot be less or equal to 0", new Throwable()); } recipeStatus = EnumValidationResult.INVALID; } if (recipeMap != null) { // recipeMap can be null in tests if (category == null) { - GTLog.logger.error("Recipes must have a category", new IllegalArgumentException()); + GTLog.logger.error("Recipes must have a category", new Throwable()); if (isCTRecipe) { - CraftTweakerAPI.logError("Recipes must have a category", new IllegalArgumentException()); + CraftTweakerAPI.logError("Recipes must have a category", new Throwable()); } recipeStatus = EnumValidationResult.INVALID; } else if (category.getRecipeMap() != this.recipeMap) { - GTLog.logger.error("Cannot apply Category with incompatible RecipeMap", new IllegalArgumentException()); + GTLog.logger.error("Cannot apply Category with incompatible RecipeMap", new Throwable()); if (isCTRecipe) { CraftTweakerAPI.logError("Cannot apply Category with incompatible RecipeMap", - new IllegalArgumentException()); + new Throwable()); } recipeStatus = EnumValidationResult.INVALID; } diff --git a/src/main/java/gregtech/api/recipes/RecipeMap.java b/src/main/java/gregtech/api/recipes/RecipeMap.java index 218489f1c1d..9743c549ae5 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMap.java +++ b/src/main/java/gregtech/api/recipes/RecipeMap.java @@ -462,11 +462,9 @@ protected ValidationResult postValidateRecipe(@NotNull ValidationResult< boolean emptyInputs = recipe.getInputs().isEmpty() && recipe.getFluidInputs().isEmpty(); if (emptyInputs) { - GTLog.logger.error("Invalid amount of recipe inputs. Recipe inputs are empty."); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException("Invalid number of Inputs")); + GTLog.logger.error("Invalid amount of recipe inputs. Recipe inputs are empty.", new Throwable()); if (recipe.getIsCTRecipe()) { - CraftTweakerAPI.logError("Invalid amount of recipe inputs. Recipe inputs are empty."); - CraftTweakerAPI.logError("Stacktrace:", new IllegalArgumentException("Invalid number of Inputs")); + CraftTweakerAPI.logError("Invalid amount of recipe inputs. Recipe inputs are empty.", new Throwable()); } recipeStatus = EnumValidationResult.INVALID; } @@ -474,11 +472,10 @@ protected ValidationResult postValidateRecipe(@NotNull ValidationResult< recipe.getFluidOutputs().isEmpty() && recipe.getChancedOutputs().getChancedEntries().isEmpty() && recipe.getChancedFluidOutputs().getChancedEntries().isEmpty(); if (emptyOutputs) { - GTLog.logger.error("Invalid amount of recipe outputs. Recipe outputs are empty."); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException("Invalid number of Outputs")); + GTLog.logger.error("Invalid amount of recipe outputs. Recipe outputs are empty.", new Throwable()); if (recipe.getIsCTRecipe()) { - CraftTweakerAPI.logError("Invalid amount of outputs inputs. Recipe outputs are empty."); - CraftTweakerAPI.logError("Stacktrace:", new IllegalArgumentException("Invalid number of Outputs")); + CraftTweakerAPI.logError("Invalid amount of outputs inputs. Recipe outputs are empty.", + new Throwable()); } recipeStatus = EnumValidationResult.INVALID; } @@ -486,12 +483,11 @@ protected ValidationResult postValidateRecipe(@NotNull ValidationResult< int amount = recipe.getInputs().size(); if (amount > getMaxInputs()) { GTLog.logger.error("Invalid amount of recipe inputs. Actual: {}. Should be at most {}.", amount, - getMaxInputs()); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException("Invalid number of Inputs")); + getMaxInputs(), new Throwable()); if (recipe.getIsCTRecipe()) { CraftTweakerAPI.logError(String.format( - "Invalid amount of recipe inputs. Actual: %s. Should be at most %s.", amount, getMaxInputs())); - CraftTweakerAPI.logError("Stacktrace:", new IllegalArgumentException("Invalid number of Inputs")); + "Invalid amount of recipe inputs. Actual: %s. Should be at most %s.", amount, getMaxInputs()), + new Throwable()); } recipeStatus = EnumValidationResult.INVALID; } @@ -499,13 +495,11 @@ protected ValidationResult postValidateRecipe(@NotNull ValidationResult< amount = recipe.getOutputs().size() + recipe.getChancedOutputs().getChancedEntries().size(); if (amount > getMaxOutputs()) { GTLog.logger.error("Invalid amount of recipe outputs. Actual: {}. Should be at most {}.", amount, - getMaxOutputs()); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException("Invalid number of Outputs")); + getMaxOutputs(), new Throwable()); if (recipe.getIsCTRecipe()) { CraftTweakerAPI .logError(String.format("Invalid amount of recipe outputs. Actual: %s. Should be at most %s.", - amount, getMaxOutputs())); - CraftTweakerAPI.logError("Stacktrace:", new IllegalArgumentException("Invalid number of Outputs")); + amount, getMaxOutputs()), new Throwable()); } recipeStatus = EnumValidationResult.INVALID; } @@ -513,13 +507,12 @@ protected ValidationResult postValidateRecipe(@NotNull ValidationResult< amount = recipe.getFluidInputs().size(); if (amount > getMaxFluidInputs()) { GTLog.logger.error("Invalid amount of recipe fluid inputs. Actual: {}. Should be at most {}.", amount, - getMaxFluidInputs()); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException("Invalid number of Fluid Inputs")); + getMaxFluidInputs(), new Throwable()); if (recipe.getIsCTRecipe()) { CraftTweakerAPI.logError( String.format("Invalid amount of recipe fluid inputs. Actual: %s. Should be at most %s.", - amount, getMaxFluidInputs())); - CraftTweakerAPI.logError("Stacktrace:", new IllegalArgumentException("Invalid number of Fluid Inputs")); + amount, getMaxFluidInputs()), + new Throwable()); } recipeStatus = EnumValidationResult.INVALID; } @@ -527,14 +520,12 @@ protected ValidationResult postValidateRecipe(@NotNull ValidationResult< amount = recipe.getFluidOutputs().size() + recipe.getChancedFluidOutputs().getChancedEntries().size(); if (amount > getMaxFluidOutputs()) { GTLog.logger.error("Invalid amount of recipe fluid outputs. Actual: {}. Should be at most {}.", amount, - getMaxFluidOutputs()); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException("Invalid number of Fluid Outputs")); + getMaxFluidOutputs(), new Throwable()); if (recipe.getIsCTRecipe()) { CraftTweakerAPI.logError( String.format("Invalid amount of recipe fluid outputs. Actual: %s. Should be at most %s.", - amount, getMaxFluidOutputs())); - CraftTweakerAPI.logError("Stacktrace:", - new IllegalArgumentException("Invalid number of Fluid Outputs")); + amount, getMaxFluidOutputs()), + new Throwable()); } recipeStatus = EnumValidationResult.INVALID; } @@ -1008,7 +999,7 @@ private boolean recurseIngredientTreeAdd(@NotNull Recipe recipe, @NotNull Branch branchMap, int index, int count) { if (count >= ingredients.size()) return true; if (index >= ingredients.size()) { - throw new RuntimeException("Index out of bounds for recurseItemTreeAdd, should not happen"); + throw new IllegalStateException("Index out of bounds for recurseItemTreeAdd, should not happen"); } // Loop through NUMBER_OF_INGREDIENTS times. diff --git a/src/main/java/gregtech/api/recipes/builders/AssemblyLineRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/AssemblyLineRecipeBuilder.java index 9ddc9d6851b..40a23a261ff 100644 --- a/src/main/java/gregtech/api/recipes/builders/AssemblyLineRecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/builders/AssemblyLineRecipeBuilder.java @@ -58,14 +58,14 @@ public boolean applyProperty(@NotNull String key, @Nullable Object value) { private boolean applyResearchProperty(ResearchPropertyData.ResearchEntry researchEntry) { if (!ConfigHolder.machines.enableResearch) return false; if (researchEntry == null) { - GTLog.logger.error("Assembly Line Research Entry cannot be empty.", new IllegalArgumentException()); + GTLog.logger.error("Assembly Line Research Entry cannot be empty.", new Throwable()); recipeStatus = EnumValidationResult.INVALID; return false; } if (!generatingRecipes) { GTLog.logger.error("Cannot generate recipes when using researchWithoutRecipe()", - new IllegalArgumentException()); + new Throwable()); recipeStatus = EnumValidationResult.INVALID; return false; } diff --git a/src/main/java/gregtech/api/recipes/builders/BlastRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/BlastRecipeBuilder.java index 3e309d76d4b..8aa2bd236cc 100644 --- a/src/main/java/gregtech/api/recipes/builders/BlastRecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/builders/BlastRecipeBuilder.java @@ -39,7 +39,7 @@ public boolean applyProperty(@NotNull String key, Object value) { public BlastRecipeBuilder blastFurnaceTemp(int blastFurnaceTemp) { if (blastFurnaceTemp <= 0) { GTLog.logger.error("Blast Furnace Temperature cannot be less than or equal to 0", - new IllegalArgumentException()); + new Throwable()); recipeStatus = EnumValidationResult.INVALID; } this.applyProperty(TemperatureProperty.getInstance(), blastFurnaceTemp); diff --git a/src/main/java/gregtech/api/recipes/builders/CircuitAssemblerRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/CircuitAssemblerRecipeBuilder.java index a6a4cda94d0..20d4652ddb9 100644 --- a/src/main/java/gregtech/api/recipes/builders/CircuitAssemblerRecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/builders/CircuitAssemblerRecipeBuilder.java @@ -31,8 +31,8 @@ public CircuitAssemblerRecipeBuilder copy() { public CircuitAssemblerRecipeBuilder solderMultiplier(int multiplier) { if (1 > GTValues.L * multiplier || GTValues.L * multiplier > 64000) { - GTLog.logger.error("Fluid multiplier cannot exceed 64000mb total. Multiplier: {}", multiplier); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("Fluid multiplier cannot exceed 64000mb total. Multiplier: {}", multiplier, + new Throwable()); recipeStatus = EnumValidationResult.INVALID; } this.solderMultiplier = multiplier; diff --git a/src/main/java/gregtech/api/recipes/builders/ComputationRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/ComputationRecipeBuilder.java index d6cadabc988..2da0309972a 100644 --- a/src/main/java/gregtech/api/recipes/builders/ComputationRecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/builders/ComputationRecipeBuilder.java @@ -42,7 +42,7 @@ public boolean applyProperty(@NotNull String key, Object value) { public ComputationRecipeBuilder CWUt(int cwut) { if (cwut < 0) { - GTLog.logger.error("CWU/t cannot be less than 0", new IllegalArgumentException()); + GTLog.logger.error("CWU/t cannot be less than 0", new Throwable()); recipeStatus = EnumValidationResult.INVALID; } this.applyProperty(ComputationProperty.getInstance(), cwut); @@ -54,7 +54,7 @@ public ComputationRecipeBuilder CWUt(int cwut) { */ public ComputationRecipeBuilder totalCWU(int totalCWU) { if (totalCWU < 0) { - GTLog.logger.error("Total CWU cannot be less than 0", new IllegalArgumentException()); + GTLog.logger.error("Total CWU cannot be less than 0", new Throwable()); recipeStatus = EnumValidationResult.INVALID; } this.applyProperty(TotalComputationProperty.getInstance(), totalCWU); diff --git a/src/main/java/gregtech/api/recipes/builders/FusionRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/FusionRecipeBuilder.java index e3da67a3114..a6f56e1420a 100644 --- a/src/main/java/gregtech/api/recipes/builders/FusionRecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/builders/FusionRecipeBuilder.java @@ -38,7 +38,7 @@ public boolean applyProperty(@NotNull String key, Object value) { public FusionRecipeBuilder EUToStart(long EUToStart) { if (EUToStart <= 0) { - GTLog.logger.error("EU to start cannot be less than or equal to 0", new IllegalArgumentException()); + GTLog.logger.error("EU to start cannot be less than or equal to 0", new Throwable()); recipeStatus = EnumValidationResult.INVALID; } this.applyProperty(FusionEUToStartProperty.getInstance(), EUToStart); diff --git a/src/main/java/gregtech/api/recipes/builders/ImplosionRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/ImplosionRecipeBuilder.java index b44771e8a31..3ada0e83415 100644 --- a/src/main/java/gregtech/api/recipes/builders/ImplosionRecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/builders/ImplosionRecipeBuilder.java @@ -49,7 +49,7 @@ public boolean applyProperty(@NotNull String key, Object value) { @ZenMethod public ImplosionRecipeBuilder explosivesAmount(int explosivesAmount) { if (1 > explosivesAmount || explosivesAmount > 64) { - GTLog.logger.error("Amount of explosives should be from 1 to 64 inclusive", new IllegalArgumentException()); + GTLog.logger.error("Amount of explosives should be from 1 to 64 inclusive", new Throwable()); recipeStatus = EnumValidationResult.INVALID; } this.applyProperty(ImplosionExplosiveProperty.getInstance(), new ItemStack(Blocks.TNT, explosivesAmount)); @@ -59,7 +59,7 @@ public ImplosionRecipeBuilder explosivesAmount(int explosivesAmount) { @ZenMethod public ImplosionRecipeBuilder explosivesType(ItemStack explosivesType) { if (1 > explosivesType.getCount() || explosivesType.getCount() > 64) { - GTLog.logger.error("Amount of explosives should be from 1 to 64 inclusive", new IllegalArgumentException()); + GTLog.logger.error("Amount of explosives should be from 1 to 64 inclusive", new Throwable()); recipeStatus = EnumValidationResult.INVALID; } this.applyProperty(ImplosionExplosiveProperty.getInstance(), explosivesType); diff --git a/src/main/java/gregtech/api/recipes/ingredients/nbtmatch/ListNBTCondition.java b/src/main/java/gregtech/api/recipes/ingredients/nbtmatch/ListNBTCondition.java index ee8b61833a8..e7d3d744ffa 100644 --- a/src/main/java/gregtech/api/recipes/ingredients/nbtmatch/ListNBTCondition.java +++ b/src/main/java/gregtech/api/recipes/ingredients/nbtmatch/ListNBTCondition.java @@ -19,8 +19,7 @@ protected ListNBTCondition(NBTTagType listTagType, String nbtKey, Object value) super(NBTTagType.LIST, nbtKey, value); this.listTagType = listTagType; if (listTagType == null) { - GTLog.logger.error("ListNBTCondition must not have null parameters."); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("ListNBTCondition must not have null parameters.", new Throwable()); } } diff --git a/src/main/java/gregtech/api/recipes/ingredients/nbtmatch/NBTCondition.java b/src/main/java/gregtech/api/recipes/ingredients/nbtmatch/NBTCondition.java index 06298ae22ad..ebf380d753b 100644 --- a/src/main/java/gregtech/api/recipes/ingredients/nbtmatch/NBTCondition.java +++ b/src/main/java/gregtech/api/recipes/ingredients/nbtmatch/NBTCondition.java @@ -37,8 +37,7 @@ protected NBTCondition(NBTTagType tagType, String nbtKey, Object value) { this.nbtKey = nbtKey; this.value = value; if (tagType == null || nbtKey == null || value == null) { - GTLog.logger.error("NBTCondition must not have null parameters."); - GTLog.logger.error("Stacktrace:", new IllegalArgumentException()); + GTLog.logger.error("NBTCondition must not have null parameters.", new Throwable()); } } diff --git a/src/main/java/gregtech/api/recipes/recipeproperties/IRecipePropertyStorage.java b/src/main/java/gregtech/api/recipes/recipeproperties/IRecipePropertyStorage.java index 234434bf003..9781e2484ce 100644 --- a/src/main/java/gregtech/api/recipes/recipeproperties/IRecipePropertyStorage.java +++ b/src/main/java/gregtech/api/recipes/recipeproperties/IRecipePropertyStorage.java @@ -5,8 +5,6 @@ public interface IRecipePropertyStorage { - String STACKTRACE = "Stacktrace:"; - /** * Stores new {@link RecipeProperty} with value * diff --git a/src/main/java/gregtech/api/recipes/recipeproperties/RecipePropertyStorage.java b/src/main/java/gregtech/api/recipes/recipeproperties/RecipePropertyStorage.java index a74ba78da6d..cf38c40ef3e 100644 --- a/src/main/java/gregtech/api/recipes/recipeproperties/RecipePropertyStorage.java +++ b/src/main/java/gregtech/api/recipes/recipeproperties/RecipePropertyStorage.java @@ -45,16 +45,15 @@ public boolean store(RecipeProperty recipeProperty, Object value) { try { recipeProperty.castValue(value); - } catch (ClassCastException ex) { - GTLog.logger.warn("Provided incorrect value for RecipeProperty with key {}", key); - GTLog.logger.warn("Full exception:", ex); + } catch (ClassCastException e) { + GTLog.logger.warn("Provided incorrect value for RecipeProperty with key {}", key, e); success = false; } if (success) { recipeProperties.put(recipeProperty, value); } else { - GTLog.logger.warn(STACKTRACE, new IllegalArgumentException()); + GTLog.logger.warn("RecipePropertyStorage error found", new Throwable()); } return success; From 323d93a91c390fd12d11bf2971acb6255fcca120 Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Thu, 4 Apr 2024 17:40:03 -0400 Subject: [PATCH 17/25] fix MTE block opacity (#2440) --- .../java/gregtech/api/block/machines/BlockMachine.java | 2 +- .../gregtech/api/block/machines/MachineItemBlock.java | 2 +- .../metatileentities/storage/MetaTileEntityCrate.java | 6 ------ .../metatileentities/storage/MetaTileEntityDrum.java | 10 ---------- 4 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/main/java/gregtech/api/block/machines/BlockMachine.java b/src/main/java/gregtech/api/block/machines/BlockMachine.java index d45dfdf1e1d..181c670d540 100644 --- a/src/main/java/gregtech/api/block/machines/BlockMachine.java +++ b/src/main/java/gregtech/api/block/machines/BlockMachine.java @@ -482,7 +482,7 @@ public int getLightValue(@NotNull IBlockState state, @NotNull IBlockAccess world public int getLightOpacity(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos) { // since it is called on neighbor blocks MetaTileEntity metaTileEntity = getMetaTileEntity(world, pos); - return metaTileEntity == null ? 0 : metaTileEntity.getLightOpacity(); + return metaTileEntity == null ? 255 : metaTileEntity.getLightOpacity(); } @Override diff --git a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java index ca0cd6417dd..d8fb09dcc19 100644 --- a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java +++ b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java @@ -92,7 +92,7 @@ public boolean placeBlockAt(@NotNull ItemStack stack, @NotNull EntityPlayer play // prevent rendering glitch before meta tile entity sync to client, but after block placement // set opaque property on the placing on block, instead during set of meta tile entity boolean superVal = super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, - newState.withProperty(BlockMachine.OPAQUE, metaTileEntity != null && metaTileEntity.isOpaqueCube())); + newState.withProperty(BlockMachine.OPAQUE, metaTileEntity == null || metaTileEntity.isOpaqueCube())); if (superVal && !world.isRemote) { BlockPos possiblePipe = pos.offset(side.getOpposite()); Block block = world.getBlockState(possiblePipe).getBlock(); diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java index 44859246953..ccd9a9de8fc 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java @@ -46,7 +46,6 @@ import java.util.List; import static gregtech.api.capability.GregtechDataCodes.IS_TAPED; -import static gregtech.api.capability.GregtechDataCodes.TAG_KEY_PAINTING_COLOR; public class MetaTileEntityCrate extends MetaTileEntity { @@ -75,11 +74,6 @@ public boolean hasFrontFacing() { return false; } - @Override - public int getLightOpacity() { - return 1; - } - @Override public String getHarvestTool() { return ModHandler.isMaterialWood(material) ? ToolClasses.AXE : ToolClasses.WRENCH; diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java index 321012fcf8f..7a5ef5b4d38 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java @@ -71,16 +71,6 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { return new MetaTileEntityDrum(metaTileEntityId, material, tankSize); } - @Override - public int getLightOpacity() { - return 1; - } - - @Override - public boolean isOpaqueCube() { - return false; - } - @Override public String getHarvestTool() { return ModHandler.isMaterialWood(material) ? ToolClasses.AXE : ToolClasses.WRENCH; From 1e98892e6ec28b81d5930fa6a9c0bc62b2ff41cf Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Thu, 4 Apr 2024 17:40:16 -0400 Subject: [PATCH 18/25] minor allocation optimization for GTUtility#canSeeSunClearly (#2441) --- src/main/java/gregtech/api/util/GTUtility.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 2b95a31fe0f..553279c72f4 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -707,15 +707,19 @@ public static MetaTileEntity getMetaTileEntity(ItemStack stack) { return GregTechAPI.MTE_REGISTRY.getObjectById(stack.getItemDamage()); } - public static boolean canSeeSunClearly(World world, BlockPos blockPos) { - if (!world.canSeeSky(blockPos.up())) { + /** + * @param world the world containing the block + * @param blockPos the position of the block to check + * @return if the block can see the sun clearly + */ + public static boolean canSeeSunClearly(@NotNull World world, @NotNull BlockPos blockPos) { + BlockPos up = blockPos.up(); + if (!world.canSeeSky(up)) { return false; } - Biome biome = world.getBiome(blockPos.up()); - if (world.isRaining()) { - if (biome.canRain() || biome.getEnableSnow()) { - return false; - } + Biome biome = world.getBiome(up); + if (world.isRaining() && (biome.canRain() || biome.getEnableSnow())) { + return false; } Set biomeTypes = BiomeDictionary.getTypes(biome); if (biomeTypes.contains(BiomeDictionary.Type.END)) { From 1e4ca34ea0b1ed2fc38f9a05c05b5f97d0bd4f5c Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 4 Apr 2024 14:40:58 -0700 Subject: [PATCH 19/25] Fix potential MetaTileEntity NPE when calling a server side method on client (#2437) --- src/main/java/gregtech/api/metatileentity/MetaTileEntity.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index a1ca10b2af0..fd0f404e2dc 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -826,18 +826,20 @@ private void updateLightValue() { } public void update() { - if (!allowTickAcceleration()) { + if (!getWorld().isRemote && !allowTickAcceleration()) { int currentTick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); if (currentTick == lastTick) { return; } lastTick = currentTick; } + for (MTETrait mteTrait : this.mteTraits.values()) { if (shouldUpdate(mteTrait)) { mteTrait.update(); } } + if (!getWorld().isRemote) { updateCovers(); } else { From a27b30bb375376c88b62625094cd1e6c43d9eb38 Mon Sep 17 00:00:00 2001 From: tier940 Date: Fri, 5 Apr 2024 06:42:36 +0900 Subject: [PATCH 20/25] Add stairsRecipeName (#2435) --- .../java/gregtech/loaders/WoodTypeEntry.java | 36 +++++++++++-------- .../loaders/recipe/WoodRecipeLoader.java | 20 ++++++----- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/main/java/gregtech/loaders/WoodTypeEntry.java b/src/main/java/gregtech/loaders/WoodTypeEntry.java index 7a086b1b55e..dd75a07cdb7 100644 --- a/src/main/java/gregtech/loaders/WoodTypeEntry.java +++ b/src/main/java/gregtech/loaders/WoodTypeEntry.java @@ -52,6 +52,8 @@ public final class WoodTypeEntry { public final String fenceGateRecipeName; @NotNull public final ItemStack stairs; + @Nullable + public final String stairsRecipeName; public final boolean addStairsCraftingRecipe; @NotNull public final ItemStack boat; @@ -83,13 +85,14 @@ private WoodTypeEntry(@NotNull String modid, @NotNull String woodName, @NotNull @NotNull ItemStack slab, @Nullable String slabRecipeName, boolean addSlabCraftingRecipe, @NotNull ItemStack fence, @Nullable String fenceRecipeName, @NotNull ItemStack fenceGate, @Nullable String fenceGateRecipeName, @NotNull ItemStack stairs, - boolean addStairsCraftingRecipe, @NotNull ItemStack boat, @Nullable String boatRecipeName, - @Nullable Material material, boolean addLogOreDict, boolean addPlanksOreDict, - boolean addDoorsOreDict, boolean addSlabsOreDict, boolean addFencesOreDict, - boolean addFenceGatesOreDict, boolean addStairsOreDict, boolean addPlanksUnificationInfo, - boolean addDoorsUnificationInfo, boolean addSlabsUnificationInfo, - boolean addFencesUnificationInfo, boolean addFenceGatesUnificationInfo, - boolean addStairsUnificationInfo, boolean addBoatsUnificationInfo) { + @Nullable String stairsRecipeName, boolean addStairsCraftingRecipe, @NotNull ItemStack boat, + @Nullable String boatRecipeName, @Nullable Material material, boolean addLogOreDict, + boolean addPlanksOreDict, boolean addDoorsOreDict, boolean addSlabsOreDict, + boolean addFencesOreDict, boolean addFenceGatesOreDict, boolean addStairsOreDict, + boolean addPlanksUnificationInfo, boolean addDoorsUnificationInfo, + boolean addSlabsUnificationInfo, boolean addFencesUnificationInfo, + boolean addFenceGatesUnificationInfo, boolean addStairsUnificationInfo, + boolean addBoatsUnificationInfo) { this.modid = modid; this.woodName = woodName; this.log = log; @@ -107,6 +110,7 @@ private WoodTypeEntry(@NotNull String modid, @NotNull String woodName, @NotNull this.fenceGate = fenceGate; this.fenceGateRecipeName = fenceGateRecipeName; this.stairs = stairs; + this.stairsRecipeName = stairsRecipeName; this.addStairsCraftingRecipe = addStairsCraftingRecipe; this.boat = boat; this.boatRecipeName = boatRecipeName; @@ -153,6 +157,7 @@ public static class Builder { private ItemStack fenceGate = ItemStack.EMPTY; private String fenceGateRecipeName; private ItemStack stairs = ItemStack.EMPTY; + private String stairsRecipeName; private boolean addStairsCraftingRecipe; private ItemStack boat = ItemStack.EMPTY; private String boatRecipeName; @@ -294,11 +299,13 @@ public Builder fenceGate(@NotNull ItemStack fenceGate, @Nullable String fenceGat /** * Add an entry for stairs * - * @param stairs the stairs to add + * @param stairs the stairs to add + * @param stairsRecipeName the recipe name for crafting the stairs * @return this */ - public Builder stairs(@NotNull ItemStack stairs) { + public Builder stairs(@NotNull ItemStack stairs, @Nullable String stairsRecipeName) { this.stairs = stairs; + this.stairsRecipeName = stairsRecipeName; return this; } @@ -410,12 +417,11 @@ public WoodTypeEntry build() { Preconditions.checkArgument(!planks.isEmpty(), "Planks cannot be empty."); return new WoodTypeEntry(modid, woodName, log, removeCharcoalRecipe, addCharcoalRecipe, planks, planksRecipeName, door, doorRecipeName, slab, slabRecipeName, addSlabsCraftingRecipe, fence, - fenceRecipeName, - fenceGate, fenceGateRecipeName, stairs, addStairsCraftingRecipe, boat, boatRecipeName, material, - addLogOreDict, addPlanksOreDict, addDoorsOreDict, addSlabsOreDict, addFencesOreDict, - addFenceGatesOreDict, addStairsOreDict, addPlanksUnificationInfo, addDoorsUnificationInfo, - addSlabsUnificationInfo, addFencesUnificationInfo, addFenceGatesUnificationInfo, - addStairsUnificationInfo, addBoatsUnificationInfo); + fenceRecipeName, fenceGate, fenceGateRecipeName, stairs, stairsRecipeName, addStairsCraftingRecipe, + boat, boatRecipeName, material, addLogOreDict, addPlanksOreDict, addDoorsOreDict, addSlabsOreDict, + addFencesOreDict, addFenceGatesOreDict, addStairsOreDict, addPlanksUnificationInfo, + addDoorsUnificationInfo, addSlabsUnificationInfo, addFencesUnificationInfo, + addFenceGatesUnificationInfo, addStairsUnificationInfo, addBoatsUnificationInfo); } } } diff --git a/src/main/java/gregtech/loaders/recipe/WoodRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/WoodRecipeLoader.java index c790b6c809d..953649972d8 100644 --- a/src/main/java/gregtech/loaders/recipe/WoodRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/WoodRecipeLoader.java @@ -49,7 +49,7 @@ private static List getDefaultEntries() { .slab(new ItemStack(Blocks.WOODEN_SLAB), "oak_wooden_slab") .fence(new ItemStack(Blocks.OAK_FENCE), "fence") .fenceGate(new ItemStack(Blocks.OAK_FENCE_GATE), "fence_gate") - .stairs(new ItemStack(Blocks.OAK_STAIRS)) + .stairs(new ItemStack(Blocks.OAK_STAIRS), "oak_stairs") .boat(new ItemStack(Items.BOAT), "boat") .registerAllUnificationInfo() .build(), @@ -60,7 +60,7 @@ private static List getDefaultEntries() { .slab(new ItemStack(Blocks.WOODEN_SLAB, 1, 1), "spruce_wooden_slab") .fence(new ItemStack(Blocks.SPRUCE_FENCE), "spruce_fence") .fenceGate(new ItemStack(Blocks.SPRUCE_FENCE_GATE), "spruce_fence_gate") - .stairs(new ItemStack(Blocks.SPRUCE_STAIRS)) + .stairs(new ItemStack(Blocks.SPRUCE_STAIRS), "spruce_stairs") .boat(new ItemStack(Items.SPRUCE_BOAT), "spruce_boat") .registerAllUnificationInfo() .build(), @@ -71,7 +71,7 @@ private static List getDefaultEntries() { .slab(new ItemStack(Blocks.WOODEN_SLAB, 1, 2), "birch_wooden_slab") .fence(new ItemStack(Blocks.BIRCH_FENCE), "birch_fence") .fenceGate(new ItemStack(Blocks.BIRCH_FENCE_GATE), "birch_fence_gate") - .stairs(new ItemStack(Blocks.BIRCH_STAIRS)) + .stairs(new ItemStack(Blocks.BIRCH_STAIRS), "birch_stairs") .boat(new ItemStack(Items.BIRCH_BOAT), "birch_boat") .registerAllUnificationInfo() .build(), @@ -82,7 +82,7 @@ private static List getDefaultEntries() { .slab(new ItemStack(Blocks.WOODEN_SLAB, 1, 3), "jungle_wooden_slab") .fence(new ItemStack(Blocks.JUNGLE_FENCE), "jungle_fence") .fenceGate(new ItemStack(Blocks.JUNGLE_FENCE_GATE), "jungle_fence_gate") - .stairs(new ItemStack(Blocks.JUNGLE_STAIRS)) + .stairs(new ItemStack(Blocks.JUNGLE_STAIRS), "jungle_stairs") .boat(new ItemStack(Items.JUNGLE_BOAT), "jungle_boat") .registerAllUnificationInfo() .build(), @@ -93,7 +93,7 @@ private static List getDefaultEntries() { .slab(new ItemStack(Blocks.WOODEN_SLAB, 1, 4), "acacia_wooden_slab") .fence(new ItemStack(Blocks.ACACIA_FENCE), "acacia_fence") .fenceGate(new ItemStack(Blocks.ACACIA_FENCE_GATE), "acacia_fence_gate") - .stairs(new ItemStack(Blocks.ACACIA_STAIRS)) + .stairs(new ItemStack(Blocks.ACACIA_STAIRS), "acacia_stairs") .boat(new ItemStack(Items.ACACIA_BOAT), "acacia_boat") .registerAllUnificationInfo() .build(), @@ -104,7 +104,7 @@ private static List getDefaultEntries() { .slab(new ItemStack(Blocks.WOODEN_SLAB, 1, 5), "dark_oak_wooden_slab") .fence(new ItemStack(Blocks.DARK_OAK_FENCE), "dark_oak_fence") .fenceGate(new ItemStack(Blocks.DARK_OAK_FENCE_GATE), "dark_oak_fence_gate") - .stairs(new ItemStack(Blocks.DARK_OAK_STAIRS)) + .stairs(new ItemStack(Blocks.DARK_OAK_STAIRS), "dark_oak_stairs") .boat(new ItemStack(Items.DARK_OAK_BOAT), "dark_oak_boat") .registerAllUnificationInfo() .build(), @@ -115,7 +115,7 @@ private static List getDefaultEntries() { .slab(new ItemStack(MetaBlocks.WOOD_SLAB), null).addSlabRecipe() .fence(new ItemStack(MetaBlocks.RUBBER_WOOD_FENCE), null) .fenceGate(new ItemStack(MetaBlocks.RUBBER_WOOD_FENCE_GATE), null) - .stairs(new ItemStack(MetaBlocks.RUBBER_WOOD_STAIRS)).addStairsRecipe() + .stairs(new ItemStack(MetaBlocks.RUBBER_WOOD_STAIRS), null).addStairsRecipe() .boat(MetaItems.RUBBER_WOOD_BOAT.getStackForm(), null) .registerAllOres() .registerAllUnificationInfo() @@ -126,7 +126,7 @@ private static List getDefaultEntries() { .slab(new ItemStack(MetaBlocks.WOOD_SLAB, 1, 1), null).addSlabRecipe() .fence(new ItemStack(MetaBlocks.TREATED_WOOD_FENCE), null) .fenceGate(new ItemStack(MetaBlocks.TREATED_WOOD_FENCE_GATE), null) - .stairs(new ItemStack(MetaBlocks.TREATED_WOOD_STAIRS)).addStairsRecipe() + .stairs(new ItemStack(MetaBlocks.TREATED_WOOD_STAIRS), null).addStairsRecipe() .boat(MetaItems.TREATED_WOOD_BOAT.getStackForm(), null) .material(TreatedWood) .registerAllOres() @@ -326,8 +326,10 @@ public static void registerWoodTypeRecipe(@NotNull WoodTypeEntry entry) { // stairs if (!entry.stairs.isEmpty()) { + final boolean hasStairRecipe = entry.stairsRecipeName != null; if (entry.addStairsCraftingRecipe) { - ModHandler.addShapedRecipe(name + "_stairs", GTUtility.copy(4, entry.stairs), + ModHandler.addShapedRecipe(hasStairRecipe ? entry.stairsRecipeName : name + "_stairs", + GTUtility.copy(4, entry.stairs), "P ", "PP ", "PPP", 'P', entry.planks.copy()); } From 06938f05be5bccf67e54e0bb5c9d7b7384c4c75e Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 4 Apr 2024 14:58:19 -0700 Subject: [PATCH 21/25] Improve the Quantum Storage Renderer (#2318) --- .../api/gui/resources/TextTexture.java | 29 ++++- .../renderer/handler/MetaTileEntityTESR.java | 4 +- .../custom/QuantumStorageRenderer.java | 121 +++++++++++++----- .../java/gregtech/common/ConfigHolder.java | 6 +- .../storage/MetaTileEntityCreativeChest.java | 2 +- .../storage/MetaTileEntityCreativeTank.java | 2 +- .../storage/MetaTileEntityQuantumChest.java | 2 +- .../storage/MetaTileEntityQuantumTank.java | 18 ++- 8 files changed, 134 insertions(+), 50 deletions(-) diff --git a/src/main/java/gregtech/api/gui/resources/TextTexture.java b/src/main/java/gregtech/api/gui/resources/TextTexture.java index 19928d07c8b..2750890d749 100644 --- a/src/main/java/gregtech/api/gui/resources/TextTexture.java +++ b/src/main/java/gregtech/api/gui/resources/TextTexture.java @@ -20,16 +20,26 @@ public class TextTexture implements IGuiTexture { public TextType type; @SideOnly(Side.CLIENT) private List texts; + private final boolean isClient = FMLCommonHandler.instance().getSide().isClient(); public TextTexture(String text, int color) { this.color = color; this.type = TextType.NORMAL; - if (FMLCommonHandler.instance().getSide().isClient()) { + if (isClient) { this.text = I18n.format(text); texts = Collections.singletonList(this.text); } } + public TextTexture() { + this.color = 0xFFFFFF; + this.type = TextType.NORMAL; + this.text = ""; + + if (isClient) + this.texts = Collections.singletonList(this.text); + } + public TextTexture setColor(int color) { this.color = color; return this; @@ -42,11 +52,18 @@ public TextTexture setDropShadow(boolean dropShadow) { public TextTexture setWidth(int width) { this.width = width; - if (FMLCommonHandler.instance().getSide().isClient()) { - if (this.width > 0) { - texts = Minecraft.getMinecraft().fontRenderer.listFormattedStringToWidth(text, width); - } else { - texts = Collections.singletonList(text); + return this; + } + + public TextTexture setText(String text) { + if (!this.text.equals(text)) { + this.text = text; + if (isClient) { + if (this.width > 0) { + texts = Minecraft.getMinecraft().fontRenderer.listFormattedStringToWidth(text, width); + } else { + texts = Collections.singletonList(text); + } } } return this; diff --git a/src/main/java/gregtech/client/renderer/handler/MetaTileEntityTESR.java b/src/main/java/gregtech/client/renderer/handler/MetaTileEntityTESR.java index c22b454748a..04f29382669 100644 --- a/src/main/java/gregtech/client/renderer/handler/MetaTileEntityTESR.java +++ b/src/main/java/gregtech/client/renderer/handler/MetaTileEntityTESR.java @@ -46,12 +46,12 @@ public void render(@NotNull MetaTileEntityHolder te, double x, double y, double buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); MetaTileEntity metaTileEntity = te.getMetaTileEntity(); - if (metaTileEntity instanceof IFastRenderMetaTileEntity) { + if (metaTileEntity instanceof IFastRenderMetaTileEntity fastRender) { CCRenderState renderState = CCRenderState.instance(); renderState.reset(); renderState.bind(buffer); renderState.setBrightness(te.getWorld(), te.getPos()); - ((IFastRenderMetaTileEntity) metaTileEntity).renderMetaTileEntityFast(renderState, + fastRender.renderMetaTileEntityFast(renderState, new Matrix4().translate(x, y, z), partialTicks); } if (metaTileEntity != null) { diff --git a/src/main/java/gregtech/client/renderer/texture/custom/QuantumStorageRenderer.java b/src/main/java/gregtech/client/renderer/texture/custom/QuantumStorageRenderer.java index 7e6485a155d..c5379c4e3af 100644 --- a/src/main/java/gregtech/client/renderer/texture/custom/QuantumStorageRenderer.java +++ b/src/main/java/gregtech/client/renderer/texture/custom/QuantumStorageRenderer.java @@ -1,10 +1,13 @@ package gregtech.client.renderer.texture.custom; import gregtech.api.gui.resources.TextTexture; +import gregtech.api.metatileentity.ITieredMetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.util.TextFormattingUtil; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer.RenderSide; import gregtech.client.utils.RenderUtil; +import gregtech.common.ConfigHolder; import gregtech.common.metatileentities.storage.MetaTileEntityQuantumChest; import net.minecraft.client.Minecraft; @@ -19,6 +22,7 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; @@ -40,6 +44,8 @@ public class QuantumStorageRenderer implements TextureUtils.IIconRegister { private static final EnumMap boxFacingMap = new EnumMap<>(EnumFacing.class); + private static final TextTexture textRenderer = new TextTexture().setWidth(32); + @SideOnly(Side.CLIENT) private TextureAtlasSprite glassTexture; @@ -62,30 +68,48 @@ public void registerIcons(TextureMap textureMap) { .registerSprite(new ResourceLocation("gregtech:blocks/overlay/machine/overlay_screen_glass")); } - public void renderMachine(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline, - EnumFacing frontFacing, int tier) { + public void renderMachine(CCRenderState renderState, + Matrix4 translation, + IVertexOperation[] pipeline, + T mte) { + EnumFacing frontFacing = mte.getFrontFacing(); + int tier = mte.getTier(); Textures.renderFace(renderState, translation, pipeline, frontFacing, glassBox, glassTexture, BlockRenderLayer.CUTOUT_MIPPED); TextureAtlasSprite hullTexture = Textures.VOLTAGE_CASINGS[tier] .getSpriteOnSide(RenderSide.bySide(EnumFacing.NORTH)); - boxFacingMap.keySet().forEach(facing -> { - for (EnumFacing box : EnumFacing.VALUES) { - if ((facing != frontFacing || box != frontFacing) && - (facing != EnumFacing.DOWN || box.getAxis().isVertical())) { // Don't render the front facing - // box from the front, nor allow - // Z-fighting to occur on the - // bottom - Textures.renderFace(renderState, translation, pipeline, facing, boxFacingMap.get(box), hullTexture, - BlockRenderLayer.CUTOUT_MIPPED); - } - } - }); + + for (var facing : boxFacingMap.keySet()) { + // do not render the box at the front face when "facing" is "frontFacing" + if (facing == frontFacing) continue; + + // render when the box face matches facing + Textures.renderFace(renderState, translation, pipeline, facing, boxFacingMap.get(facing), + hullTexture, BlockRenderLayer.CUTOUT_MIPPED); + + // render when the box face is opposite of facing + Textures.renderFace(renderState, translation, pipeline, facing.getOpposite(), boxFacingMap.get(facing), + hullTexture, BlockRenderLayer.CUTOUT_MIPPED); + } + + // render the sides of the box that face the front face + if (frontFacing.getAxis() == EnumFacing.Axis.Y) return; + Textures.renderFace(renderState, translation, pipeline, frontFacing, boxFacingMap.get(EnumFacing.DOWN), + hullTexture, BlockRenderLayer.CUTOUT_MIPPED); + Textures.renderFace(renderState, translation, pipeline, frontFacing, boxFacingMap.get(EnumFacing.UP), + hullTexture, BlockRenderLayer.CUTOUT_MIPPED); + + EnumFacing facing = frontFacing.rotateYCCW(); + Textures.renderFace(renderState, translation, pipeline, frontFacing, boxFacingMap.get(facing), + hullTexture, BlockRenderLayer.CUTOUT_MIPPED); + Textures.renderFace(renderState, translation, pipeline, frontFacing, boxFacingMap.get(facing.getOpposite()), + hullTexture, BlockRenderLayer.CUTOUT_MIPPED); } public static void renderChestStack(double x, double y, double z, MetaTileEntityQuantumChest machine, ItemStack stack, long count, float partialTicks) { - if (stack.isEmpty() || count == 0) + if (!ConfigHolder.client.enableFancyChestRender || stack.isEmpty() || count == 0) return; float lastBrightnessX = OpenGlHelper.lastBrightnessX; @@ -93,15 +117,19 @@ public static void renderChestStack(double x, double y, double z, MetaTileEntity World world = machine.getWorld(); setLightingCorrectly(world, machine.getPos()); EnumFacing frontFacing = machine.getFrontFacing(); - RenderItem itemRenderer = Minecraft.getMinecraft().getRenderItem(); - float tick = world.getWorldTime() + partialTicks; - GlStateManager.pushMatrix(); - GlStateManager.translate(x, y, z); - GlStateManager.translate(0.5D, 0.5D, 0.5D); - GlStateManager.rotate(tick * (float) Math.PI * 2 / 40, 0, 1, 0); - GlStateManager.scale(0.6f, 0.6f, 0.6f); - itemRenderer.renderItem(stack, ItemCameraTransforms.TransformType.FIXED); - GlStateManager.popMatrix(); + + if (canRender(x, y, z, 8 * + MathHelper.clamp((double) Minecraft.getMinecraft().gameSettings.renderDistanceChunks / 8, 1.0, 2.5))) { + RenderItem itemRenderer = Minecraft.getMinecraft().getRenderItem(); + float tick = world.getWorldTime() + partialTicks; + GlStateManager.pushMatrix(); + GlStateManager.translate(x, y, z); + GlStateManager.translate(0.5D, 0.5D, 0.5D); + GlStateManager.rotate(tick * (float) Math.PI * 2 / 40, 0, 1, 0); + GlStateManager.scale(0.6f, 0.6f, 0.6f); + itemRenderer.renderItem(stack, ItemCameraTransforms.TransformType.FIXED); + GlStateManager.popMatrix(); + } OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240); renderAmountText(x, y, z, count, frontFacing); @@ -110,20 +138,20 @@ public static void renderChestStack(double x, double y, double z, MetaTileEntity public static void renderTankFluid(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline, FluidTank tank, IBlockAccess world, BlockPos pos, EnumFacing frontFacing) { - float lastBrightnessX = OpenGlHelper.lastBrightnessX; - float lastBrightnessY = OpenGlHelper.lastBrightnessY; + FluidStack stack = tank.getFluid(); + if (stack == null || stack.amount == 0 || !ConfigHolder.client.enableFancyChestRender) + return; + if (world != null) { renderState.setBrightness(world, pos); } - FluidStack stack = tank.getFluid(); - if (stack == null || stack.amount == 0) - return; Cuboid6 partialFluidBox = new Cuboid6(1.0625 / 16.0, 2.0625 / 16.0, 1.0625 / 16.0, 14.9375 / 16.0, 14.9375 / 16.0, 14.9375 / 16.0); double fillFraction = (double) stack.amount / tank.getCapacity(); - if (tank.getFluid().getFluid().isGaseous()) { + boolean gas = stack.getFluid().isGaseous(); + if (gas) { partialFluidBox.min.y = Math.max(13.9375 - (11.875 * fillFraction), 2.0) / 16.0; } else { partialFluidBox.max.y = Math.min((11.875 * fillFraction) + 2.0625, 14.0) / 16.0; @@ -133,15 +161,34 @@ public static void renderTankFluid(CCRenderState renderState, Matrix4 translatio ResourceLocation fluidStill = stack.getFluid().getStill(stack); TextureAtlasSprite fluidStillSprite = Minecraft.getMinecraft().getTextureMapBlocks() .getAtlasSprite(fluidStill.toString()); - for (EnumFacing facing : EnumFacing.VALUES) { - Textures.renderFace(renderState, translation, pipeline, facing, partialFluidBox, fluidStillSprite, - BlockRenderLayer.CUTOUT_MIPPED); - } + + Textures.renderFace(renderState, translation, pipeline, frontFacing, partialFluidBox, fluidStillSprite, + BlockRenderLayer.CUTOUT_MIPPED); + + Textures.renderFace(renderState, translation, pipeline, gas ? EnumFacing.DOWN : EnumFacing.UP, partialFluidBox, + fluidStillSprite, + BlockRenderLayer.CUTOUT_MIPPED); + GlStateManager.resetColor(); renderState.reset(); } + /** + * Takes in the difference in x, y, and z from the camera to the rendering TE and + * calculates the squared distance and checks if it's within the range squared + * + * @param x the difference in x from entity to this rendering TE + * @param y the difference in y from entity to this rendering TE + * @param z the difference in z from entity to this rendering TE + * @param range distance needed to be rendered + * @return true if the camera is within the given range, otherwise false + */ + public static boolean canRender(double x, double y, double z, double range) { + double distance = (x * x) + (y * y) + (z * z); + return distance < range * range; + } + public static void renderTankAmount(double x, double y, double z, EnumFacing frontFacing, long amount) { float lastBrightnessX = OpenGlHelper.lastBrightnessX; float lastBrightnessY = OpenGlHelper.lastBrightnessY; @@ -153,6 +200,9 @@ public static void renderTankAmount(double x, double y, double z, EnumFacing fro } public static void renderAmountText(double x, double y, double z, long amount, EnumFacing frontFacing) { + if (!ConfigHolder.client.enableFancyChestRender || !canRender(x, y, z, 64)) + return; + GlStateManager.pushMatrix(); GlStateManager.translate(x, y, z); GlStateManager.translate(frontFacing.getXOffset() * -1 / 16f, frontFacing.getYOffset() * -1 / 16f, @@ -167,7 +217,8 @@ public static void renderAmountText(double x, double y, double z, long amount, E GlStateManager.scale(1f / 64, 1f / 64, 0); GlStateManager.translate(-32, -32, 0); GlStateManager.disableLighting(); - new TextTexture(amountText, 0xFFFFFF).draw(0, 24, 64, 28); + textRenderer.setText(amountText); + textRenderer.draw(0, 24, 64, 28); GlStateManager.enableLighting(); GlStateManager.popMatrix(); } diff --git a/src/main/java/gregtech/common/ConfigHolder.java b/src/main/java/gregtech/common/ConfigHolder.java index 290fb9f7d64..caf04defc48 100644 --- a/src/main/java/gregtech/common/ConfigHolder.java +++ b/src/main/java/gregtech/common/ConfigHolder.java @@ -404,7 +404,7 @@ public static class ClientOptions { @Config.Comment({ "Whether or not to enable Emissive Textures for Electric Blast Furnace Coils when the multiblock is working.", - "Default: false" }) + "Default: true" }) public boolean coilsActiveEmissiveTextures = true; @Config.Comment({ "Whether or not sounds should be played when using tools outside of crafting.", @@ -456,6 +456,10 @@ public static class ClientOptions { @Config.Comment({ "Prevent optical and laser cables from animating when active.", "Default: false" }) public boolean preventAnimatedCables = false; + @Config.Comment({ "Enable the fancy rendering for Super/Quantum Chests/Tanks.", + "Default: true" }) + public boolean enableFancyChestRender = true; + public static class GuiConfig { @Config.Comment({ "The scrolling speed of widgets", "Default: 13" }) diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeChest.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeChest.java index 50dd8dc5cbe..e34f104d679 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeChest.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeChest.java @@ -69,7 +69,7 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, Textures.QUANTUM_STORAGE_RENDERER.renderMachine(renderState, translation, ArrayUtils.add(pipeline, new ColourMultiplier(GTUtility.convertRGBtoOpaqueRGBA_CL(getPaintingColorForRendering()))), - this.getFrontFacing(), this.getTier()); + this); Textures.CREATIVE_CONTAINER_OVERLAY.renderSided(EnumFacing.UP, renderState, translation, pipeline); Textures.PIPE_OUT_OVERLAY.renderSided(this.getOutputFacing(), renderState, translation, pipeline); Textures.ITEM_OUTPUT_OVERLAY.renderSided(this.getOutputFacing(), renderState, translation, pipeline); diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeTank.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeTank.java index 1f35630af35..3e93c1bcbd5 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeTank.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeTank.java @@ -52,7 +52,7 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, Textures.QUANTUM_STORAGE_RENDERER.renderMachine(renderState, translation, ArrayUtils.add(pipeline, new ColourMultiplier(GTUtility.convertRGBtoOpaqueRGBA_CL(getPaintingColorForRendering()))), - this.getFrontFacing(), this.getTier()); + this); Textures.CREATIVE_CONTAINER_OVERLAY.renderSided(EnumFacing.UP, renderState, translation, pipeline); if (this.getOutputFacing() != null) { Textures.PIPE_OUT_OVERLAY.renderSided(this.getOutputFacing(), renderState, translation, pipeline); diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumChest.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumChest.java index be6c63f5dec..bd6dca83fb8 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumChest.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumChest.java @@ -102,7 +102,7 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, Textures.QUANTUM_STORAGE_RENDERER.renderMachine(renderState, translation, ArrayUtils.add(pipeline, new ColourMultiplier(GTUtility.convertRGBtoOpaqueRGBA_CL(getPaintingColorForRendering()))), - this.getFrontFacing(), this.tier); + this); Textures.QUANTUM_CHEST_OVERLAY.renderSided(EnumFacing.UP, renderState, translation, pipeline); if (outputFacing != null) { Textures.PIPE_OUT_OVERLAY.renderSided(outputFacing, renderState, translation, pipeline); diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumTank.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumTank.java index d6624d95823..7e5d244f556 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumTank.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumTank.java @@ -40,6 +40,7 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentTranslation; @@ -134,9 +135,17 @@ public void update() { updatePreviousFluid(null); } else if (previousFluid.getFluid().equals(currentFluid.getFluid()) && previousFluid.amount != currentFluid.amount) { + int currentFill = MathHelper + .floor(16 * ((float) currentFluid.amount) / fluidTank.getCapacity()); + int previousFill = MathHelper + .floor(16 * ((float) previousFluid.amount) / fluidTank.getCapacity()); // tank has fluid with changed amount previousFluid.amount = currentFluid.amount; - writeCustomData(UPDATE_FLUID_AMOUNT, buf -> buf.writeInt(currentFluid.amount)); + writeCustomData(UPDATE_FLUID_AMOUNT, buf -> { + buf.writeInt(currentFluid.amount); + buf.writeBoolean(currentFill != previousFill); + }); + } else if (!previousFluid.equals(currentFluid)) { // tank has a different fluid from before @@ -266,7 +275,7 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, Textures.QUANTUM_STORAGE_RENDERER.renderMachine(renderState, translation, ArrayUtils.add(pipeline, new ColourMultiplier(GTUtility.convertRGBtoOpaqueRGBA_CL(getPaintingColorForRendering()))), - this.getFrontFacing(), this.tier); + this); Textures.QUANTUM_TANK_OVERLAY.renderSided(EnumFacing.UP, renderState, translation, pipeline); if (outputFacing != null) { Textures.PIPE_OUT_OVERLAY.renderSided(outputFacing, renderState, translation, pipeline); @@ -282,6 +291,7 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, public void renderMetaTileEntity(double x, double y, double z, float partialTicks) { if (this.fluidTank.getFluid() == null || this.fluidTank.getFluid().amount == 0) return; + QuantumStorageRenderer.renderTankAmount(x, y, z, this.getFrontFacing(), this.fluidTank.getFluid().amount); } @@ -457,10 +467,12 @@ public void receiveCustomData(int dataId, PacketBuffer buf) { } else if (dataId == UPDATE_FLUID_AMOUNT) { // amount must always be read even if it cannot be used to ensure the reader index advances int amount = buf.readInt(); + boolean updateRendering = buf.readBoolean(); FluidStack stack = fluidTank.getFluid(); if (stack != null) { stack.amount = Math.min(amount, fluidTank.getCapacity()); - scheduleRenderUpdate(); + if (updateRendering) + scheduleRenderUpdate(); } } else if (dataId == UPDATE_IS_VOIDING) { setVoiding(buf.readBoolean()); From f33da7fc687314e3a866369ec6bfaa567ecc1ca7 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Thu, 4 Apr 2024 16:03:07 -0700 Subject: [PATCH 22/25] Port Filters and some Covers to MUI + Filter Rework (#2345) --- dependencies.gradle | 2 +- .../api/capability/GregtechDataCodes.java | 3 + .../java/gregtech/api/cover/CoverWithUI.java | 122 +++++- .../api/gui/widgets/PhantomFluidWidget.java | 6 +- .../gregtech/api/items/metaitem/MetaItem.java | 14 +- .../java/gregtech/api/mui/GTGuiTextures.java | 83 +++- .../api/mui/sync/FixedFluidSlotSH.java | 150 +++++++ .../common/covers/CoverBehaviors.java | 12 +- .../gregtech/common/covers/CoverConveyor.java | 279 ++++++++---- .../common/covers/CoverEnderFluidLink.java | 143 ++++-- .../common/covers/CoverFluidFilter.java | 138 ++++-- .../common/covers/CoverFluidRegulator.java | 198 ++++----- .../common/covers/CoverFluidVoiding.java | 70 +-- .../covers/CoverFluidVoidingAdvanced.java | 191 +++----- .../common/covers/CoverItemFilter.java | 134 ++++-- .../common/covers/CoverItemVoiding.java | 70 +-- .../covers/CoverItemVoidingAdvanced.java | 142 +++--- .../common/covers/CoverMachineController.java | 2 +- .../gregtech/common/covers/CoverPump.java | 264 ++++++----- .../common/covers/CoverRoboticArm.java | 147 ++++--- .../common/covers/DistributionMode.java | 1 + .../common/covers/FluidFilterMode.java | 5 +- .../gregtech/common/covers/IFilterMode.java | 6 - .../common/covers/ItemFilterMode.java | 5 +- .../common/covers/ManualImportExportMode.java | 1 + .../gregtech/common/covers/TransferMode.java | 3 +- .../gregtech/common/covers/VoidingMode.java | 3 +- .../detector/CoverDetectorFluidAdvanced.java | 4 +- .../detector/CoverDetectorItemAdvanced.java | 4 +- .../common/covers/filter/BaseFilter.java | 183 ++++++++ .../covers/filter/BaseFilterContainer.java | 273 ++++++++++++ .../covers/filter/FilterTypeRegistry.java | 103 ----- .../common/covers/filter/FluidFilter.java | 41 -- .../covers/filter/FluidFilterContainer.java | 142 ++---- .../covers/filter/FluidFilterWrapper.java | 98 ----- .../common/covers/filter/IFilter.java | 77 ++++ .../common/covers/filter/ItemFilter.java | 50 --- .../covers/filter/ItemFilterContainer.java | 172 ++------ .../covers/filter/ItemFilterWrapper.java | 132 ------ .../common/covers/filter/MatchResult.java | 46 ++ .../filter/OreDictionaryItemFilter.java | 413 ++++++++++-------- .../covers/filter/SimpleFluidFilter.java | 145 +++--- .../covers/filter/SimpleItemFilter.java | 190 +++++--- .../common/covers/filter/SmartItemFilter.java | 124 ++++-- .../covers/filter/WidgetGroupFluidFilter.java | 41 +- .../covers/filter/WidgetGroupItemFilter.java | 35 +- .../filter/readers/BaseFilterReader.java | 124 ++++++ .../covers/filter/readers/FilterReader.java | 32 ++ .../filter/readers/OreDictFilterReader.java | 123 ++++++ .../readers/SimpleFluidFilterReader.java | 181 ++++++++ .../readers/SimpleItemFilterReader.java | 193 ++++++++ .../filter/readers/SmartItemFilterReader.java | 40 ++ .../gui/widget/HighlightedTextField.java | 127 ------ .../orefilter/ItemOreFilterTestSlot.java | 111 ----- .../widget/orefilter/OreFilterTestSlot.java | 202 --------- .../java/gregtech/common/items/MetaItem1.java | 21 +- .../behaviors/filter/BaseFilterUIManager.java | 55 +++ .../filter/OreDictFilterUIManager.java | 19 + .../filter/SimpleFilterUIManager.java | 19 + .../filter/SimpleFluidFilterUIManager.java | 19 + .../filter/SmartFilterUIManager.java | 19 + .../electric/MetaTileEntityItemCollector.java | 2 +- .../mui/widget/HighlightedTextField.java | 95 ++++ .../orefilter/ItemOreFilterTestSlot.java | 42 ++ .../widget/orefilter/OreFilterTestSlot.java | 144 ++++++ .../pipelike/itempipe/net/ItemNetHandler.java | 25 +- src/main/java/gregtech/core/CoreModule.java | 2 - .../provider/CoverInfoProvider.java | 101 +++-- .../loaders/recipe/MachineRecipeLoader.java | 10 + .../resources/assets/gregtech/lang/en_us.lang | 30 +- .../gui/overlay/conveyor_mode_overlay.png | Bin 0 -> 514 bytes .../gui/overlay/filter_mode_overlay.png | Bin 0 -> 230 bytes .../gui/overlay/filter_settings_overlay.png | Bin 0 -> 333 bytes .../overlay/fluid_transfer_mode_overlay.png | Bin 0 -> 454 bytes .../gui/overlay/manual_io_overlay.png | Bin 0 -> 593 bytes .../gui/overlay/transfer_mode_overlay.png | Bin 0 -> 455 bytes .../gui/overlay/voiding_mode_overlay.png | Bin 0 -> 232 bytes .../gui/widget/button_distribution_mode.png | Bin 765 -> 652 bytes 78 files changed, 3861 insertions(+), 2342 deletions(-) create mode 100644 src/main/java/gregtech/api/mui/sync/FixedFluidSlotSH.java delete mode 100644 src/main/java/gregtech/common/covers/IFilterMode.java create mode 100644 src/main/java/gregtech/common/covers/filter/BaseFilter.java create mode 100644 src/main/java/gregtech/common/covers/filter/BaseFilterContainer.java delete mode 100644 src/main/java/gregtech/common/covers/filter/FilterTypeRegistry.java delete mode 100644 src/main/java/gregtech/common/covers/filter/FluidFilter.java delete mode 100644 src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java create mode 100644 src/main/java/gregtech/common/covers/filter/IFilter.java delete mode 100644 src/main/java/gregtech/common/covers/filter/ItemFilter.java delete mode 100644 src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java create mode 100644 src/main/java/gregtech/common/covers/filter/MatchResult.java create mode 100644 src/main/java/gregtech/common/covers/filter/readers/BaseFilterReader.java create mode 100644 src/main/java/gregtech/common/covers/filter/readers/FilterReader.java create mode 100644 src/main/java/gregtech/common/covers/filter/readers/OreDictFilterReader.java create mode 100644 src/main/java/gregtech/common/covers/filter/readers/SimpleFluidFilterReader.java create mode 100644 src/main/java/gregtech/common/covers/filter/readers/SimpleItemFilterReader.java create mode 100644 src/main/java/gregtech/common/covers/filter/readers/SmartItemFilterReader.java delete mode 100644 src/main/java/gregtech/common/gui/widget/HighlightedTextField.java delete mode 100644 src/main/java/gregtech/common/gui/widget/orefilter/ItemOreFilterTestSlot.java delete mode 100644 src/main/java/gregtech/common/gui/widget/orefilter/OreFilterTestSlot.java create mode 100644 src/main/java/gregtech/common/items/behaviors/filter/BaseFilterUIManager.java create mode 100644 src/main/java/gregtech/common/items/behaviors/filter/OreDictFilterUIManager.java create mode 100644 src/main/java/gregtech/common/items/behaviors/filter/SimpleFilterUIManager.java create mode 100644 src/main/java/gregtech/common/items/behaviors/filter/SimpleFluidFilterUIManager.java create mode 100644 src/main/java/gregtech/common/items/behaviors/filter/SmartFilterUIManager.java create mode 100644 src/main/java/gregtech/common/mui/widget/HighlightedTextField.java create mode 100644 src/main/java/gregtech/common/mui/widget/orefilter/ItemOreFilterTestSlot.java create mode 100644 src/main/java/gregtech/common/mui/widget/orefilter/OreFilterTestSlot.java create mode 100644 src/main/resources/assets/gregtech/textures/gui/overlay/conveyor_mode_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/overlay/filter_mode_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/overlay/filter_settings_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/overlay/fluid_transfer_mode_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/overlay/manual_io_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/overlay/transfer_mode_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/overlay/voiding_mode_overlay.png diff --git a/dependencies.gradle b/dependencies.gradle index 445b5e3963b..49d93cc7bd5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -40,7 +40,7 @@ dependencies { // Published dependencies api("codechicken:codechickenlib:3.2.3.358") - api("com.cleanroommc:modularui:2.4.1") { transitive = false } + api("com.cleanroommc:modularui:2.4.3") { transitive = false } api("com.cleanroommc:groovyscript:0.8.0") { transitive = false } api("CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.684") api rfg.deobf("curse.maven:ae2-extended-life-570458:4402048") // AE2UEL 0.55.6 diff --git a/src/main/java/gregtech/api/capability/GregtechDataCodes.java b/src/main/java/gregtech/api/capability/GregtechDataCodes.java index 4fcead477d4..225e12e4f74 100644 --- a/src/main/java/gregtech/api/capability/GregtechDataCodes.java +++ b/src/main/java/gregtech/api/capability/GregtechDataCodes.java @@ -23,6 +23,9 @@ public static int assignId() { public static final int UPDATE_AUTO_OUTPUT_FLUIDS = assignId(); public static final int UPDATE_IS_VOIDING = assignId(); + // Robotic Arm + public static final int UPDATE_TRANSFER_MODE = assignId(); + // Drum public static final int UPDATE_AUTO_OUTPUT = assignId(); diff --git a/src/main/java/gregtech/api/cover/CoverWithUI.java b/src/main/java/gregtech/api/cover/CoverWithUI.java index f40f2df37bc..d8780c611d9 100644 --- a/src/main/java/gregtech/api/cover/CoverWithUI.java +++ b/src/main/java/gregtech/api/cover/CoverWithUI.java @@ -2,6 +2,7 @@ import gregtech.api.gui.IUIHolder; import gregtech.api.gui.ModularUI; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuiTheme; import gregtech.api.mui.GregTechGuiScreen; import gregtech.api.mui.factory.CoverGuiFactory; @@ -9,20 +10,25 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; +import net.minecraft.util.IStringSerializable; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import com.cleanroommc.modularui.api.IGuiHolder; +import com.cleanroommc.modularui.api.drawable.IDrawable; import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.drawable.ItemDrawable; import com.cleanroommc.modularui.factory.SidedPosGuiData; import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.screen.ModularScreen; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.utils.MouseData; import com.cleanroommc.modularui.value.BoolValue; import com.cleanroommc.modularui.value.sync.EnumSyncValue; import com.cleanroommc.modularui.value.sync.GuiSyncManager; import com.cleanroommc.modularui.value.sync.IntSyncValue; import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ToggleButton; import com.cleanroommc.modularui.widgets.layout.Row; import org.jetbrains.annotations.ApiStatus; @@ -92,13 +98,12 @@ default void markAsDirty() { /** * Create the Title bar widget for a Cover. */ - default Row createTitleRow() { - ItemStack item = getDefinition().getDropItemStack(); + static Row createTitleRow(ItemStack stack) { return new Row() .pos(4, 4) .height(16).coverChildrenWidth() - .child(new ItemDrawable(getDefinition().getDropItemStack()).asWidget().size(16).marginRight(4)) - .child(IKey.str(item.getDisplayName()).color(UI_TITLE_COLOR).asWidget().heightRel(1.0f)); + .child(new ItemDrawable(stack).asWidget().size(16).marginRight(4)) + .child(IKey.str(stack.getDisplayName()).color(UI_TITLE_COLOR).asWidget().heightRel(1.0f)); } /** @@ -108,6 +113,31 @@ default ParentWidget createSettingsRow() { return new ParentWidget<>().height(16).widthRel(1.0f).marginBottom(2); } + default int getIncrementValue(MouseData data) { + int adjust = 1; + if (data.shift) adjust *= 4; + if (data.ctrl) adjust *= 16; + if (data.alt) adjust *= 64; + return adjust; + } + + default IKey createAdjustOverlay(boolean increment) { + final StringBuilder builder = new StringBuilder(); + builder.append(increment ? '+' : '-'); + builder.append(getIncrementValue(MouseData.create(-1))); + + float scale = 1f; + if (builder.length() == 3) { + scale = 0.8f; + } else if (builder.length() == 4) { + scale = 0.6f; + } else if (builder.length() > 4) { + scale = 0.5f; + } + return IKey.str(builder.toString()) + .scale(scale); + } + /** * Get a BoolValue for use with toggle buttons which are "linked together," * meaning only one of them can be pressed at a time. @@ -123,4 +153,88 @@ default > BoolValue.Dynamic boolValueOf(EnumSyncValue syncV default BoolValue.Dynamic boolValueOf(IntSyncValue syncValue, int value) { return new BoolValue.Dynamic(() -> syncValue.getValue() == value, $ -> syncValue.setValue(value)); } + + class EnumRowBuilder> { + + private EnumSyncValue syncValue; + private final Class enumValue; + private String lang; + private IDrawable[] background; + private IDrawable selectedBackground; + private IDrawable[] overlay; + + public EnumRowBuilder(Class enumValue) { + this.enumValue = enumValue; + } + + public EnumRowBuilder value(EnumSyncValue syncValue) { + this.syncValue = syncValue; + return this; + } + + public EnumRowBuilder lang(String lang) { + this.lang = lang; + return this; + } + + public EnumRowBuilder background(IDrawable... background) { + this.background = background; + return this; + } + + public EnumRowBuilder selectedBackground(IDrawable selectedBackground) { + this.selectedBackground = selectedBackground; + return this; + } + + public EnumRowBuilder overlay(IDrawable... overlay) { + this.overlay = overlay; + return this; + } + + public EnumRowBuilder overlay(int size, IDrawable... overlay) { + this.overlay = new IDrawable[overlay.length]; + for (int i = 0; i < overlay.length; i++) { + this.overlay[i] = overlay[i].asIcon().size(size); + } + return this; + } + + private BoolValue.Dynamic boolValueOf(EnumSyncValue syncValue, T value) { + return new BoolValue.Dynamic(() -> syncValue.getValue() == value, $ -> syncValue.setValue(value)); + } + + public Row build() { + var row = new Row().marginBottom(2).coverChildrenHeight().widthRel(1f); + if (this.enumValue != null && this.syncValue != null) { + for (var enumVal : enumValue.getEnumConstants()) { + var button = new ToggleButton().size(18).marginRight(2) + .value(boolValueOf(this.syncValue, enumVal)); + + if (this.background != null && this.background.length > 0) + button.background(this.background); + else + button.background(GTGuiTextures.MC_BUTTON); + + if (this.selectedBackground != null) + button.selectedBackground(this.selectedBackground); + else + button.selectedBackground(GTGuiTextures.MC_BUTTON_DISABLED); + + if (this.overlay != null) + button.overlay(this.overlay[enumVal.ordinal()]); + + if (enumVal instanceof IStringSerializable serializable) { + button.addTooltipLine(IKey.lang(serializable.getName())); + } + row.child(button); + } + } + + if (this.lang != null && !this.lang.isEmpty()) + row.child(IKey.lang(this.lang).asWidget().align(Alignment.CenterRight).height(18)); + + return row; + } + } } diff --git a/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java b/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java index f6d3f4857f7..7fed3591548 100644 --- a/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java @@ -6,7 +6,11 @@ import gregtech.api.gui.ingredient.IGhostIngredientTarget; import gregtech.api.gui.ingredient.IIngredientSlot; import gregtech.api.gui.resources.IGuiTexture; -import gregtech.api.util.*; +import gregtech.api.util.GTLog; +import gregtech.api.util.LocalizationUtils; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import gregtech.api.util.TextFormattingUtil; import gregtech.client.utils.RenderUtil; import gregtech.client.utils.TooltipHelper; diff --git a/src/main/java/gregtech/api/items/metaitem/MetaItem.java b/src/main/java/gregtech/api/items/metaitem/MetaItem.java index f2674add426..a17559b05b2 100644 --- a/src/main/java/gregtech/api/items/metaitem/MetaItem.java +++ b/src/main/java/gregtech/api/items/metaitem/MetaItem.java @@ -33,6 +33,7 @@ import gregtech.api.util.Mods; import gregtech.client.utils.ToolChargeBarRenderer; import gregtech.common.ConfigHolder; +import gregtech.common.covers.filter.IFilter; import gregtech.common.creativetab.GTCreativeTabs; import net.minecraft.client.Minecraft; @@ -781,6 +782,7 @@ public MetaItem getMetaItem() { private final List behaviours = new ArrayList<>(); private IItemUseManager useManager; private ItemUIFactory uiManager; + private IFilter.Factory filterBehavior; private IItemColorProvider colorProvider; private IItemDurabilityManager durabilityManager; private IEnchantabilityHelper enchantabilityHelper; @@ -908,9 +910,12 @@ protected void addItemComponentsInternal(IItemComponent... stats) { if (itemComponent instanceof IFoodBehavior) { this.useManager = new FoodUseManager((IFoodBehavior) itemComponent); } - if (itemComponent instanceof ItemUIFactory) + if (itemComponent instanceof ItemUIFactory) { this.uiManager = (ItemUIFactory) itemComponent; - + } + if (itemComponent instanceof IFilter.Factory) { + this.filterBehavior = (IFilter.Factory) itemComponent; + } if (itemComponent instanceof IItemColorProvider) { this.colorProvider = (IItemColorProvider) itemComponent; } @@ -956,6 +961,11 @@ public ItemUIFactory getUIManager() { return uiManager; } + @Nullable + public IFilter.Factory getFilterFactory() { + return filterBehavior; + } + @Nullable public IItemColorProvider getColorProvider() { return colorProvider; diff --git a/src/main/java/gregtech/api/mui/GTGuiTextures.java b/src/main/java/gregtech/api/mui/GTGuiTextures.java index 3c99abaee1e..d585285efc2 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTextures.java +++ b/src/main/java/gregtech/api/mui/GTGuiTextures.java @@ -12,6 +12,7 @@ * while MUI port is still ongoing. When MUI port is done, this annotation will be removed. */ // TODO ^ +@SuppressWarnings("unused") @ApiStatus.Experimental public class GTGuiTextures { @@ -153,6 +154,56 @@ public static class IDs { .canApplyTheme() .build(); + public static final UITexture[] BUTTON_BLACKLIST = slice("textures/gui/widget/button_blacklist.png", + 16, 32, 16, 16, true); + public static final UITexture[] BUTTON_IGNORE_DAMAGE = slice("textures/gui/widget/button_filter_damage.png", + 16, 32, 16, 16, true); + public static final UITexture[] BUTTON_IGNORE_NBT = slice("textures/gui/widget/button_filter_nbt.png", + 16, 32, 16, 16, true); + + public static final UITexture[] BUTTON_CASE_SENSITIVE = slice( + "textures/gui/widget/ore_filter/button_case_sensitive.png", + 16, 32, 16, 16, true); + + public static final UITexture[] BUTTON_MATCH_ALL = slice("textures/gui/widget/ore_filter/button_match_all.png", + 16, 32, 16, 16, true); + + public static final UITexture OREDICT_ERROR = fullImage("textures/gui/widget/ore_filter/error.png"); + public static final UITexture OREDICT_INFO = fullImage("textures/gui/widget/ore_filter/info.png"); + public static final UITexture OREDICT_MATCH = fullImage("textures/gui/widget/ore_filter/match.png"); + public static final UITexture OREDICT_NO_MATCH = fullImage("textures/gui/widget/ore_filter/no_match.png"); + public static final UITexture OREDICT_SUCCESS = fullImage("textures/gui/widget/ore_filter/success.png"); + public static final UITexture OREDICT_WAITING = fullImage("textures/gui/widget/ore_filter/waiting.png"); + public static final UITexture OREDICT_WARN = fullImage("textures/gui/widget/ore_filter/warn.png"); + + public static final UITexture[] MANUAL_IO_OVERLAY = slice("textures/gui/overlay/manual_io_overlay.png", + 18, 18 * 3, 18, 18, true); + public static final UITexture[] CONVEYOR_MODE_OVERLAY = slice("textures/gui/overlay/conveyor_mode_overlay.png", + 18, 18 * 2, 18, 18, true); + + public static final UITexture[] TRANSFER_MODE_OVERLAY = slice("textures/gui/overlay/transfer_mode_overlay.png", + 18, 18 * 3, 18, 18, true); + + public static final UITexture[] FLUID_TRANSFER_MODE_OVERLAY = slice( + "textures/gui/overlay/fluid_transfer_mode_overlay.png", + 18, 18 * 3, 18, 18, true); + + public static final UITexture[] DISTRIBUTION_MODE_OVERLAY = slice( + "textures/gui/widget/button_distribution_mode.png", + 16, 48, 16, 16, true); + + public static final UITexture[] VOIDING_MODE_OVERLAY = slice( + "textures/gui/overlay/voiding_mode_overlay.png", + 16, 32, 16, 16, true); + + public static final UITexture[] FILTER_MODE_OVERLAY = slice( + "textures/gui/overlay/filter_mode_overlay.png", + 16, 48, 16, 16, true); + + public static final UITexture[] PRIVATE_MODE_BUTTON = slice( + "textures/gui/widget/button_public_private.png", + 18, 36, 18, 18, true); + // todo bronze/steel/primitive fluid slots? // SLOT OVERLAYS @@ -205,6 +256,9 @@ public static class IDs { public static final UITexture EXTRACTOR_OVERLAY_STEEL = fullImage( "textures/gui/overlay/extractor_overlay_steel.png"); public static final UITexture FILTER_SLOT_OVERLAY = fullImage("textures/gui/overlay/filter_slot_overlay.png", true); + public static final UITexture FILTER_SETTINGS_OVERLAY = fullImage( + "textures/gui/overlay/filter_settings_overlay.png", + true); public static final UITexture FURNACE_OVERLAY_1 = fullImage("textures/gui/overlay/furnace_overlay_1.png", true); public static final UITexture FURNACE_OVERLAY_2 = fullImage("textures/gui/overlay/furnace_overlay_2.png", true); public static final UITexture FURNACE_OVERLAY_BRONZE = fullImage("textures/gui/overlay/furnace_overlay_bronze.png"); @@ -265,7 +319,7 @@ public static class IDs { public static final UITexture BUTTON = new UITexture.Builder() .location(GTValues.MODID, "textures/gui/widget/button.png") .imageSize(18, 18) - .adaptable(1) + .adaptable(2) .name(IDs.STANDARD_BUTTON) .canApplyTheme() .build(); @@ -274,13 +328,13 @@ public static class IDs { .location("modularui", "gui/widgets/mc_button.png") // todo .imageSize(16, 32) .uv(0.0f, 0.0f, 1.0f, 0.5f) - .adaptable(1) + .adaptable(2) .build(); public static final UITexture MC_BUTTON_DISABLED = new UITexture.Builder() .location("modularui", "gui/widgets/mc_button_disabled.png") // todo .imageSize(16, 16) - .adaptable(1) + .adaptable(2) .build(); // BUTTON OVERLAYS @@ -453,6 +507,29 @@ private static UITexture fullImage(String path, boolean canApplyTheme) { return UITexture.fullImage(GTValues.MODID, path, canApplyTheme); } + @SuppressWarnings("SameParameterValue") + private static UITexture[] slice(String path, int imageWidth, int imageHeight, int sliceWidth, int sliceHeight, + boolean canApplyTheme) { + if (imageWidth % sliceWidth != 0 || imageHeight % sliceHeight != 0) + throw new IllegalArgumentException("Slice height and slice width must divide the image evenly!"); + + int countX = imageWidth / sliceWidth; + int countY = imageHeight / sliceHeight; + UITexture[] slices = new UITexture[countX * countY]; + + for (int indexX = 0; indexX < countX; indexX++) { + for (int indexY = 0; indexY < countY; indexY++) { + slices[(indexX * countX) + indexY] = UITexture.builder() + .location(GTValues.MODID, path) + .canApplyTheme(canApplyTheme) + .imageSize(imageWidth, imageHeight) + .uv(indexX * sliceWidth, indexY * sliceHeight, sliceWidth, sliceHeight) + .build(); + } + } + return slices; + } + private static UITexture progressBar(String path) { return progressBar(path, 20, 40, false); } diff --git a/src/main/java/gregtech/api/mui/sync/FixedFluidSlotSH.java b/src/main/java/gregtech/api/mui/sync/FixedFluidSlotSH.java new file mode 100644 index 00000000000..bf3c6c581d7 --- /dev/null +++ b/src/main/java/gregtech/api/mui/sync/FixedFluidSlotSH.java @@ -0,0 +1,150 @@ +package gregtech.api.mui.sync; + +import gregtech.common.covers.filter.readers.SimpleFluidFilterReader; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; + +import com.cleanroommc.modularui.utils.MouseData; +import com.cleanroommc.modularui.value.sync.FluidSlotSyncHandler; +import org.jetbrains.annotations.Nullable; + +public class FixedFluidSlotSH extends FluidSlotSyncHandler { + + @Nullable + private FluidStack lastStoredPhantomFluid; + + public FixedFluidSlotSH(IFluidTank fluidTank) { + super(fluidTank); + if (this.updateCacheFromSource(true) && fluidTank.getFluid() != null) { + this.lastStoredPhantomFluid = fluidTank.getFluid().copy(); + } + } + + @Override + public void readOnServer(int id, PacketBuffer buf) { + super.readOnServer(id, buf); + if (id == 0) { + var fluid = getFluidTank().getFluid(); + if (this.lastStoredPhantomFluid == null && fluid != null || + (this.lastStoredPhantomFluid != null && !this.lastStoredPhantomFluid.isFluidEqual(fluid))) { + this.lastStoredPhantomFluid = fluid; + } + } + } + + @Override + public void setValue(@Nullable FluidStack value, boolean setSource, boolean sync) { + super.setValue(value, setSource, sync); + if (setSource) { + this.getFluidTank().drain(Integer.MAX_VALUE, true); + if (!isFluidEmpty(value)) { + this.getFluidTank().fill(value.copy(), true); + } + } + } + + @Override + public void tryClickPhantom(MouseData mouseData) { + EntityPlayer player = getSyncManager().getPlayer(); + ItemStack currentStack = player.inventory.getItemStack(); + FluidStack currentFluid = this.getFluidTank().getFluid(); + IFluidHandlerItem fluidHandlerItem = currentStack + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null); + + if (mouseData.mouseButton == 0) { + if (currentStack.isEmpty() || fluidHandlerItem == null) { + if (this.canDrainSlot()) { + this.getFluidTank().drain(mouseData.shift ? Integer.MAX_VALUE : 1000, true); + } + } else { + FluidStack cellFluid = fluidHandlerItem.drain(Integer.MAX_VALUE, false); + if ((this.controlsAmount() || currentFluid == null) && cellFluid != null) { + if (this.canFillSlot()) { + if (!this.controlsAmount()) { + cellFluid.amount = 1; + } + if (this.getFluidTank().fill(cellFluid, true) > 0) { + this.lastStoredPhantomFluid = cellFluid.copy(); + } + } + } else { + if (this.canDrainSlot()) { + this.getFluidTank().drain(mouseData.shift ? Integer.MAX_VALUE : 1000, true); + } + } + } + } else if (mouseData.mouseButton == 1) { + if (this.canFillSlot()) { + if (currentFluid != null) { + if (this.controlsAmount()) { + FluidStack toFill = currentFluid.copy(); + toFill.amount = 1000; + this.getFluidTank().fill(toFill, true); + } + } else if (this.lastStoredPhantomFluid != null) { + FluidStack toFill = this.lastStoredPhantomFluid.copy(); + toFill.amount = this.controlsAmount() ? 1 : toFill.amount; + this.getFluidTank().fill(toFill, true); + } + } + } else if (mouseData.mouseButton == 2 && currentFluid != null && this.canDrainSlot()) { + this.getFluidTank().drain(mouseData.shift ? Integer.MAX_VALUE : 1000, true); + } + this.setValue(this.getFluidTank().getFluid(), false, true); + } + + @Override + public void tryScrollPhantom(MouseData mouseData) { + FluidStack currentFluid = this.getFluidTank().getFluid(); + int amount = mouseData.mouseButton; + if (!this.controlsAmount()) { + var fluid = getFluidTank().getFluid(); + int newAmt = amount == 1 ? 1 : 0; + if (fluid != null && fluid.amount != newAmt) { + fluid.amount = newAmt; + setValue(fluid, true, true); + return; + } + } + if (mouseData.shift) { + amount *= 10; + } + if (mouseData.ctrl) { + amount *= 100; + } + if (mouseData.alt) { + amount *= 1000; + } + if (currentFluid == null) { + if (amount > 0 && this.lastStoredPhantomFluid != null) { + FluidStack toFill = this.lastStoredPhantomFluid.copy(); + toFill.amount = this.controlsAmount() ? amount : 1; + this.getFluidTank().fill(toFill, true); + } + this.setValue(this.getFluidTank().getFluid(), false, true); + return; + } + if (amount > 0) { + FluidStack toFill = currentFluid.copy(); + toFill.amount = amount; + this.getFluidTank().fill(toFill, true); + } else if (amount < 0) { + this.getFluidTank().drain(-amount, true); + } + this.setValue(this.getFluidTank().getFluid(), false, true); + } + + @Override + public boolean controlsAmount() { + if (getFluidTank() instanceof SimpleFluidFilterReader.WritableFluidTank writableFluidTank) { + return writableFluidTank.showAmount(); + } + return super.controlsAmount(); + } +} diff --git a/src/main/java/gregtech/common/covers/CoverBehaviors.java b/src/main/java/gregtech/common/covers/CoverBehaviors.java index 3e5779fb3bf..78413327163 100644 --- a/src/main/java/gregtech/common/covers/CoverBehaviors.java +++ b/src/main/java/gregtech/common/covers/CoverBehaviors.java @@ -8,10 +8,6 @@ import gregtech.api.util.GTLog; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.detector.*; -import gregtech.common.covers.filter.OreDictionaryItemFilter; -import gregtech.common.covers.filter.SimpleFluidFilter; -import gregtech.common.covers.filter.SimpleItemFilter; -import gregtech.common.covers.filter.SmartItemFilter; import gregtech.common.items.MetaItems; import gregtech.common.items.behaviors.CoverDigitalInterfaceWirelessPlaceBehaviour; @@ -67,12 +63,12 @@ public static void init() { registerBehavior(gregtechId("ore_dictionary_filter"), MetaItems.ORE_DICTIONARY_FILTER, (def, tile, side) -> new CoverItemFilter(def, tile, side, "cover.ore_dictionary_filter.title", - Textures.ORE_DICTIONARY_FILTER_OVERLAY, new OreDictionaryItemFilter())); + Textures.ORE_DICTIONARY_FILTER_OVERLAY)); registerBehavior(gregtechId("item_filter"), MetaItems.ITEM_FILTER, (def, tile, side) -> new CoverItemFilter(def, - tile, side, "cover.item_filter.title", Textures.ITEM_FILTER_FILTER_OVERLAY, new SimpleItemFilter())); + tile, side, "cover.item_filter.title", Textures.ITEM_FILTER_FILTER_OVERLAY)); registerBehavior(gregtechId("fluid_filter"), MetaItems.FLUID_FILTER, (def, tile, side) -> new CoverFluidFilter(def, tile, side, "cover.fluid_filter.title", - Textures.FLUID_FILTER_OVERLAY, new SimpleFluidFilter())); + Textures.FLUID_FILTER_OVERLAY)); registerBehavior(gregtechId("shutter"), MetaItems.COVER_SHUTTER, CoverShutter::new); registerBehavior(gregtechId("solar_panel.basic"), MetaItems.COVER_SOLAR_PANEL, @@ -100,7 +96,7 @@ public static void init() { CoverMachineController::new); registerBehavior(gregtechId("smart_filter"), MetaItems.SMART_FILTER, (def, tile, side) -> new CoverItemFilter(def, tile, side, "cover.smart_item_filter.title", - Textures.SMART_FILTER_FILTER_OVERLAY, new SmartItemFilter())); + Textures.SMART_FILTER_FILTER_OVERLAY)); registerBehavior(gregtechId("facade"), MetaItems.COVER_FACADE, CoverFacade::new); registerBehavior(gregtechId("screen"), MetaItems.COVER_SCREEN, CoverScreen::new); diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 1408ae77c56..127c852fb83 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -1,6 +1,5 @@ package gregtech.common.covers; -import gregtech.api.GTValues; import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; @@ -9,9 +8,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.ItemStackHashStrategy; import gregtech.client.renderer.texture.Textures; @@ -26,7 +24,12 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.*; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.ITickable; import net.minecraft.util.math.MathHelper; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fml.relauncher.Side; @@ -39,10 +42,24 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.widget.Interactable; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.utils.MouseData; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet; import org.jetbrains.annotations.NotNull; @@ -76,7 +93,7 @@ public CoverConveyor(@NotNull CoverDefinition definition, @NotNull CoverableView } public void setTransferRate(int transferRate) { - this.transferRate = transferRate; + this.transferRate = MathHelper.clamp(transferRate, 1, maxItemTransferRate); CoverableView coverable = getCoverableView(); coverable.markDirty(); @@ -168,7 +185,7 @@ protected int doTransferItemsAny(IItemHandler itemHandler, IItemHandler myItemHa } protected int doTransferItemsByGroup(IItemHandler itemHandler, IItemHandler myItemHandler, - Map itemInfos, int maxTransferAmount) { + Map itemInfos, int maxTransferAmount) { if (conveyorMode == ConveyorMode.IMPORT) { return moveInventoryItems(itemHandler, myItemHandler, itemInfos, maxTransferAmount); } else if (conveyorMode == ConveyorMode.EXPORT) { @@ -177,8 +194,8 @@ protected int doTransferItemsByGroup(IItemHandler itemHandler, IItemHandler myIt return 0; } - protected Map doCountDestinationInventoryItemsByMatchIndex(IItemHandler itemHandler, - IItemHandler myItemHandler) { + protected Map doCountDestinationInventoryItemsByMatchIndex(IItemHandler itemHandler, + IItemHandler myItemHandler) { if (conveyorMode == ConveyorMode.IMPORT) { return countInventoryItemsByMatchSlot(myItemHandler); } else if (conveyorMode == ConveyorMode.EXPORT) { @@ -265,15 +282,17 @@ protected static boolean moveInventoryItemsExact(IItemHandler sourceInventory, I } protected int moveInventoryItems(IItemHandler sourceInventory, IItemHandler targetInventory, - Map itemInfos, int maxTransferAmount) { + Map itemInfos, int maxTransferAmount) { int itemsLeftToTransfer = maxTransferAmount; for (int i = 0; i < sourceInventory.getSlots(); i++) { ItemStack itemStack = sourceInventory.getStackInSlot(i); if (itemStack.isEmpty()) { continue; } - Object matchSlotIndex = itemFilterContainer.matchItemStack(itemStack); - if (matchSlotIndex == null || !itemInfos.containsKey(matchSlotIndex)) { + + var matchResult = itemFilterContainer.match(itemStack); + int matchSlotIndex = matchResult.getFilterIndex(); + if (!matchResult.isMatched() || !itemInfos.containsKey(matchSlotIndex)) { continue; } @@ -317,9 +336,10 @@ protected int moveInventoryItems(IItemHandler sourceInventory, IItemHandler targ if (sourceStack.isEmpty()) { continue; } - if (!itemFilterContainer.testItemStack(sourceStack)) { - continue; - } + + var result = itemFilterContainer.match(sourceStack); + if (!result.isMatched()) continue; + ItemStack remainder = GTTransferUtils.insertItem(targetInventory, sourceStack, true); int amountToInsert = sourceStack.getCount() - remainder.getCount(); @@ -341,11 +361,11 @@ protected int moveInventoryItems(IItemHandler sourceInventory, IItemHandler targ protected static class TypeItemInfo { public final ItemStack itemStack; - public final Object filterSlot; + public final int filterSlot; public final IntList slots; public int totalCount; - public TypeItemInfo(ItemStack itemStack, Object filterSlot, IntList slots, int totalCount) { + public TypeItemInfo(ItemStack itemStack, int filterSlot, IntList slots, int totalCount) { this.itemStack = itemStack; this.filterSlot = filterSlot; this.slots = slots; @@ -355,11 +375,11 @@ public TypeItemInfo(ItemStack itemStack, Object filterSlot, IntList slots, int t protected static class GroupItemInfo { - public final Object filterSlot; + public final int filterSlot; public final Set itemStackTypes; public int totalCount; - public GroupItemInfo(Object filterSlot, Set itemStackTypes, int totalCount) { + public GroupItemInfo(int filterSlot, Set itemStackTypes, int totalCount) { this.filterSlot = filterSlot; this.itemStackTypes = itemStackTypes; this.totalCount = totalCount; @@ -375,12 +395,13 @@ protected Map countInventoryItemsByType(@NotNull IItemH if (itemStack.isEmpty()) { continue; } - Object transferSlotIndex = itemFilterContainer.matchItemStack(itemStack); - if (transferSlotIndex == null) { - continue; - } + + var matchResult = itemFilterContainer.match(itemStack); + if (!matchResult.isMatched()) continue; + if (!result.containsKey(itemStack)) { - TypeItemInfo itemInfo = new TypeItemInfo(itemStack.copy(), transferSlotIndex, new IntArrayList(), 0); + TypeItemInfo itemInfo = new TypeItemInfo(itemStack.copy(), matchResult.getFilterIndex(), + new IntArrayList(), 0); itemInfo.totalCount += itemStack.getCount(); itemInfo.slots.add(srcIndex); result.put(itemStack.copy(), itemInfo); @@ -394,28 +415,30 @@ protected Map countInventoryItemsByType(@NotNull IItemH } @NotNull - protected Map countInventoryItemsByMatchSlot(@NotNull IItemHandler inventory) { - Map result = new Object2ObjectOpenHashMap<>(); + protected Map countInventoryItemsByMatchSlot(@NotNull IItemHandler inventory) { + Map result = new Int2ObjectOpenHashMap<>(); for (int srcIndex = 0; srcIndex < inventory.getSlots(); srcIndex++) { ItemStack itemStack = inventory.getStackInSlot(srcIndex); if (itemStack.isEmpty()) { continue; } - Object transferSlotIndex = itemFilterContainer.matchItemStack(itemStack); - if (transferSlotIndex == null) { - continue; - } - if (!result.containsKey(transferSlotIndex)) { - GroupItemInfo itemInfo = new GroupItemInfo(transferSlotIndex, + + var matchResult = itemFilterContainer.match(itemStack); + if (!matchResult.isMatched()) continue; + int matchedSlot = matchResult.getFilterIndex(); + + if (!result.containsKey(matchedSlot)) { + GroupItemInfo itemInfo = new GroupItemInfo(matchedSlot, new ObjectOpenCustomHashSet<>(ItemStackHashStrategy.comparingAllButCount()), 0); itemInfo.itemStackTypes.add(itemStack.copy()); itemInfo.totalCount += itemStack.getCount(); - result.put(transferSlotIndex, itemInfo); + result.put(matchedSlot, itemInfo); } else { - GroupItemInfo itemInfo = result.get(transferSlotIndex); + GroupItemInfo itemInfo = result.get(matchedSlot); itemInfo.itemStackTypes.add(itemStack.copy()); itemInfo.totalCount += itemStack.getCount(); } + } return result; } @@ -432,7 +455,7 @@ public boolean canInteractWithOutputSide() { @Override public void onRemoval() { - dropInventoryContents(itemFilterContainer.getFilterInventory()); + dropInventoryContents(itemFilterContainer); } @Override @@ -473,57 +496,123 @@ public T getCapability(Capability capability, T defaultValue) { return defaultValue; } - protected String getUITitle() { - return "cover.conveyor.title"; + @Override + public boolean usesMui2() { + return true; + } + + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + var panel = GTGuis.createPanel(this, 176, 192 + 18); + + getItemFilterContainer().setMaxTransferSize(getMaxStackSize()); + + return panel.child(CoverWithUI.createTitleRow(getPickItem())) + .child(createUI(panel, guiSyncManager)) + .bindPlayerInventory(); + } + + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager guiSyncManager) { + var column = new Column().top(24).margin(7, 0) + .widthRel(1f).coverChildrenHeight(); + + EnumSyncValue manualIOmode = new EnumSyncValue<>(ManualImportExportMode.class, + this::getManualImportExportMode, this::setManualImportExportMode); + + EnumSyncValue conveyorMode = new EnumSyncValue<>(ConveyorMode.class, + this::getConveyorMode, this::setConveyorMode); + + IntSyncValue throughput = new IntSyncValue(this::getTransferRate, this::setTransferRate); + throughput.updateCacheFromSource(true); + + StringSyncValue formattedThroughput = new StringSyncValue(throughput::getStringValue, + throughput::setStringValue); + + EnumSyncValue distributionMode = new EnumSyncValue<>(DistributionMode.class, + this::getDistributionMode, this::setDistributionMode); + + guiSyncManager.syncValue("manual_io", manualIOmode); + guiSyncManager.syncValue("conveyor_mode", conveyorMode); + guiSyncManager.syncValue("distribution_mode", distributionMode); + guiSyncManager.syncValue("throughput", throughput); + + if (createThroughputRow()) + column.child(new Row().coverChildrenHeight() + .marginBottom(2).widthRel(1f) + .child(new ButtonWidget<>() + .left(0).width(18) + .onMousePressed(mouseButton -> { + int val = throughput.getValue() - getIncrementValue(MouseData.create(mouseButton)); + throughput.setValue(val, true, true); + Interactable.playButtonClickSound(); + return true; + }) + .onUpdateListener(w -> w.overlay(createAdjustOverlay(false)))) + .child(new TextFieldWidget() + .left(18).right(18) + .setTextColor(Color.WHITE.darker(1)) + .setNumbers(1, maxItemTransferRate) + .value(formattedThroughput) + .background(GTGuiTextures.DISPLAY)) + .child(new ButtonWidget<>() + .right(0).width(18) + .onMousePressed(mouseButton -> { + int val = throughput.getValue() + getIncrementValue(MouseData.create(mouseButton)); + throughput.setValue(val, true, true); + Interactable.playButtonClickSound(); + return true; + }) + .onUpdateListener(w -> w.overlay(createAdjustOverlay(true))))); + + if (createFilterRow()) + column.child(getItemFilterContainer().initUI(mainPanel, guiSyncManager)); + + if (createManualIOModeRow()) + column.child(new EnumRowBuilder<>(ManualImportExportMode.class) + .value(manualIOmode) + .lang("cover.generic.manual_io") + .overlay(GTGuiTextures.MANUAL_IO_OVERLAY) + .build()); + + if (createConveyorModeRow()) + column.child(new EnumRowBuilder<>(ConveyorMode.class) + .value(conveyorMode) + .lang("cover.generic.io") + .overlay(GTGuiTextures.CONVEYOR_MODE_OVERLAY) + .build()); + + if (createDistributionModeRow()) + column.child(new EnumRowBuilder<>(DistributionMode.class) + .value(distributionMode) + .overlay(16, GTGuiTextures.DISTRIBUTION_MODE_OVERLAY) + .lang("cover.conveyor.distribution.name") + .build()); + + return column; + } + + protected boolean createThroughputRow() { + return true; } - protected ModularUI buildUI(ModularUI.Builder builder, EntityPlayer player) { - return builder.build(this, player); + protected boolean createFilterRow() { + return true; } - @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle(), GTValues.VN[tier])); - - primaryGroup.addWidget(new IncrementButtonWidget(136, 20, 30, 20, 1, 8, 64, 512, this::adjustTransferRate) - .setDefaultTooltip() - .setShouldClientCallback(false)); - primaryGroup.addWidget(new IncrementButtonWidget(10, 20, 30, 20, -1, -8, -64, -512, this::adjustTransferRate) - .setDefaultTooltip() - .setShouldClientCallback(false)); - - primaryGroup.addWidget(new ImageWidget(40, 20, 96, 20, GuiTextures.DISPLAY)); - primaryGroup.addWidget(new TextFieldWidget2(42, 26, 92, 20, () -> String.valueOf(transferRate), val -> { - if (val != null && !val.isEmpty()) - setTransferRate(MathHelper.clamp(Integer.parseInt(val), 1, maxItemTransferRate)); - }) - .setNumbersOnly(1, maxItemTransferRate) - .setMaxLength(4) - .setPostFix("cover.conveyor.transfer_rate")); - - primaryGroup.addWidget(new CycleButtonWidget(10, 45, 75, 20, - ConveyorMode.class, this::getConveyorMode, this::setConveyorMode)); - primaryGroup.addWidget(new CycleButtonWidget(7, 166, 116, 20, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); - - if (getTileEntityHere() instanceof TileEntityItemPipe || - getNeighbor(getAttachedSide()) instanceof TileEntityItemPipe) { - final ImageCycleButtonWidget distributionModeButton = new ImageCycleButtonWidget(149, 166, 20, 20, - GuiTextures.DISTRIBUTION_MODE, 3, - () -> distributionMode.ordinal(), - val -> setDistributionMode(DistributionMode.values()[val])) - .setTooltipHoverString(val -> DistributionMode.values()[val].getName()); - primaryGroup.addWidget(distributionModeButton); - } + protected boolean createManualIOModeRow() { + return true; + } - this.itemFilterContainer.initUI(70, primaryGroup::addWidget); + protected boolean createConveyorModeRow() { + return true; + } + + protected boolean createDistributionModeRow() { + return true; + } - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 190 + 82) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 190); - return buildUI(builder, player); + protected int getMaxStackSize() { + return 1; } @Override @@ -546,17 +635,23 @@ public void readCustomData(int discriminator, @NotNull PacketBuffer buf) { } @Override - public void writeInitialSyncData(PacketBuffer packetBuffer) { + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { super.writeInitialSyncData(packetBuffer); - packetBuffer.writeEnumValue(conveyorMode); - packetBuffer.writeEnumValue(distributionMode); + packetBuffer.writeInt(transferRate); + packetBuffer.writeByte(conveyorMode.ordinal()); + packetBuffer.writeByte(distributionMode.ordinal()); + packetBuffer.writeByte(manualImportExportMode.ordinal()); + getItemFilterContainer().writeInitialSyncData(packetBuffer); } @Override public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { super.readInitialSyncData(packetBuffer); - this.conveyorMode = packetBuffer.readEnumValue(ConveyorMode.class); - this.distributionMode = packetBuffer.readEnumValue(DistributionMode.class); + this.transferRate = packetBuffer.readInt(); + this.conveyorMode = ConveyorMode.VALUES[packetBuffer.readByte()]; + this.distributionMode = DistributionMode.VALUES[packetBuffer.readByte()]; + this.manualImportExportMode = ManualImportExportMode.VALUES[packetBuffer.readByte()]; + getItemFilterContainer().readInitialSyncData(packetBuffer); } @Override @@ -574,11 +669,12 @@ public void writeToNBT(@NotNull NBTTagCompound tagCompound) { public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.transferRate = tagCompound.getInteger("TransferRate"); - this.conveyorMode = ConveyorMode.values()[tagCompound.getInteger("ConveyorMode")]; - this.distributionMode = DistributionMode.values()[tagCompound.getInteger("DistributionMode")]; + this.conveyorMode = ConveyorMode.VALUES[tagCompound.getInteger("ConveyorMode")]; + this.distributionMode = DistributionMode.VALUES[tagCompound.getInteger("DistributionMode")]; this.isWorkingAllowed = tagCompound.getBoolean("WorkingAllowed"); - this.manualImportExportMode = ManualImportExportMode.values()[tagCompound.getInteger("ManualImportExportMode")]; + this.manualImportExportMode = ManualImportExportMode.VALUES[tagCompound.getInteger("ManualImportExportMode")]; this.itemFilterContainer.deserializeNBT(tagCompound.getCompoundTag("Filter")); + this.itemFilterContainer.handleLegacyNBT(tagCompound.getCompoundTag("Filter")); } @Override @@ -592,6 +688,7 @@ public enum ConveyorMode implements IStringSerializable, IIOMode { IMPORT("cover.conveyor.mode.import"), EXPORT("cover.conveyor.mode.export"); + public static final ConveyorMode[] VALUES = values(); public final String localeName; ConveyorMode(String localeName) { @@ -623,7 +720,7 @@ public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate return stack; } if (manualImportExportMode == ManualImportExportMode.FILTERED && - !itemFilterContainer.testItemStack(stack)) { + !itemFilterContainer.test(stack)) { return stack; } return super.insertItem(slot, stack, simulate); @@ -637,7 +734,7 @@ public ItemStack extractItem(int slot, int amount, boolean simulate) { } if (manualImportExportMode == ManualImportExportMode.FILTERED) { ItemStack result = super.extractItem(slot, amount, true); - if (result.isEmpty() || !itemFilterContainer.testItemStack(result)) { + if (result.isEmpty() || !itemFilterContainer.test(result)) { return ItemStack.EMPTY; } return simulate ? result : super.extractItem(slot, amount, false); diff --git a/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java b/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java index b34348c69bb..ffe2f9ed8a0 100644 --- a/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java +++ b/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java @@ -6,9 +6,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; import gregtech.api.util.FluidTankSwitchShim; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.VirtualTankRegistry; @@ -20,7 +19,11 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; -import net.minecraft.util.*; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ITickable; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -30,6 +33,22 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.drawable.DynamicDrawable; +import com.cleanroommc.modularui.drawable.Rectangle; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.FluidSlotSyncHandler; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widgets.FluidSlot; +import com.cleanroommc.modularui.widgets.ToggleButton; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -106,7 +125,7 @@ public void onAttachment(@NotNull CoverableView coverableView, @NotNull EnumFaci @Override public void onRemoval() { - dropInventoryContents(fluidFilter.getFilterInventory()); + dropInventoryContents(fluidFilter); } @Override @@ -121,9 +140,9 @@ protected void transferFluids() { getAttachedSide()); if (fluidHandler == null) return; if (pumpMode == CoverPump.PumpMode.IMPORT) { - GTTransferUtils.transferFluids(fluidHandler, linkedTank, TRANSFER_RATE, fluidFilter::testFluidStack); + GTTransferUtils.transferFluids(fluidHandler, linkedTank, TRANSFER_RATE, fluidFilter::test); } else if (pumpMode == CoverPump.PumpMode.EXPORT) { - GTTransferUtils.transferFluids(linkedTank, fluidHandler, TRANSFER_RATE, fluidFilter::testFluidStack); + GTTransferUtils.transferFluids(linkedTank, fluidHandler, TRANSFER_RATE, fluidFilter::test); } } @@ -143,36 +162,86 @@ public void openUI(EntityPlayerMP player) { } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup widgetGroup = new WidgetGroup(); - widgetGroup.addWidget(new LabelWidget(10, 5, "cover.ender_fluid_link.title")); - widgetGroup.addWidget(new ToggleButtonWidget(12, 18, 18, 18, GuiTextures.BUTTON_PUBLIC_PRIVATE, - this::isPrivate, this::setPrivate) - .setTooltipText("cover.ender_fluid_link.private.tooltip")); - widgetGroup.addWidget(new SyncableColorRectWidget(35, 18, 18, 18, () -> color) - .setBorderWidth(1) - .drawCheckerboard(4, 4)); - widgetGroup.addWidget(new TextFieldWidget(58, 13, 58, 18, true, - this::getColorStr, this::updateColor, 8) - .setValidator(str -> COLOR_INPUT_PATTERN.matcher(str).matches())); - widgetGroup.addWidget(new TankWidget(this.linkedTank, 123, 18, 18, 18) - .setContainerClicking(true, true) - .setBackgroundTexture(GuiTextures.FLUID_SLOT).setAlwaysShowFull(true)); - widgetGroup.addWidget(new ImageWidget(147, 19, 16, 16) - .setImage(GuiTextures.INFO_ICON) - .setPredicate(() -> isColorTemp) - .setTooltip("cover.ender_fluid_link.incomplete_hex") - .setIgnoreColor(true)); - widgetGroup.addWidget(new CycleButtonWidget(10, 42, 75, 18, - CoverPump.PumpMode.class, this::getPumpMode, this::setPumpMode)); - widgetGroup.addWidget(new CycleButtonWidget(92, 42, 75, 18, - this::isIoEnabled, this::setIoEnabled, "cover.ender_fluid_link.iomode.disabled", - "cover.ender_fluid_link.iomode.enabled")); - this.fluidFilter.initUI(65, widgetGroup::addWidget); - return ModularUI.builder(GuiTextures.BACKGROUND, 176, 221) - .widget(widgetGroup) - .bindPlayerInventory(player.inventory, 139) - .build(this, player); + public boolean usesMui2() { + return true; + } + + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + var panel = GTGuis.createPanel(this, 176, 192); + + getFluidFilterContainer().setMaxTransferSize(1); + + return panel.child(CoverWithUI.createTitleRow(getPickItem())) + .child(createWidgets(panel, guiSyncManager)) + .bindPlayerInventory(); + } + + protected Column createWidgets(ModularPanel panel, GuiSyncManager syncManager) { + var isPrivate = new BooleanSyncValue(this::isPrivate, this::setPrivate); + isPrivate.updateCacheFromSource(true); + + var color = new StringSyncValue(this::getColorStr, this::updateColor); + color.updateCacheFromSource(true); + + var pumpMode = new EnumSyncValue<>(CoverPump.PumpMode.class, this::getPumpMode, this::setPumpMode); + syncManager.syncValue("pump_mode", pumpMode); + pumpMode.updateCacheFromSource(true); + + var ioEnabled = new BooleanSyncValue(this::isIOEnabled, this::setIoEnabled); + + var fluidTank = new FluidSlotSyncHandler(this.linkedTank); + fluidTank.updateCacheFromSource(true); + + return new Column().coverChildrenHeight().top(24) + .margin(7, 0).widthRel(1f) + .child(new Row().marginBottom(2) + .coverChildrenHeight() + .child(new ToggleButton() + .tooltip(tooltip -> tooltip.setAutoUpdate(true)) + .background(GTGuiTextures.PRIVATE_MODE_BUTTON[0]) + .hoverBackground(GTGuiTextures.PRIVATE_MODE_BUTTON[0]) + .selectedBackground(GTGuiTextures.PRIVATE_MODE_BUTTON[1]) + .selectedHoverBackground(GTGuiTextures.PRIVATE_MODE_BUTTON[1]) + .tooltipBuilder(tooltip -> tooltip.addLine(IKey.lang(this.isPrivate ? + "cover.ender_fluid_link.private.tooltip.enabled" : + "cover.ender_fluid_link.private.tooltip.disabled"))) + .marginRight(2) + .value(isPrivate)) + .child(new DynamicDrawable(() -> new Rectangle() + .setColor(this.color) + .asIcon().size(16)) + .asWidget() + .background(GTGuiTextures.SLOT) + .size(18).marginRight(2)) + .child(new TextFieldWidget().height(18) + .value(color) + .setValidator(s -> { + if (s.length() != 8) { + return color.getStringValue(); + } + return s; + }) + .setPattern(COLOR_INPUT_PATTERN) + .widthRel(0.5f).marginRight(2)) + .child(new FluidSlot().size(18) + .syncHandler(fluidTank))) + .child(new Row().marginBottom(2) + .coverChildrenHeight() + .child(new ToggleButton() + .value(ioEnabled) + .overlay(IKey.dynamic(() -> IKey.lang(this.ioEnabled ? + "behaviour.soft_hammer.enabled" : + "behaviour.soft_hammer.disabled").get()) + .color(Color.WHITE.darker(1))) + .widthRel(0.6f) + .left(0))) + .child(getFluidFilterContainer().initUI(panel, syncManager)) + .child(new EnumRowBuilder<>(CoverPump.PumpMode.class) + .value(pumpMode) + .overlay(GTGuiTextures.CONVEYOR_MODE_OVERLAY) + .lang("cover.pump.mode") + .build()); } public void updateColor(String str) { diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index cd5d06ee5a4..648968c90dc 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -5,19 +5,19 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.CycleButtonWidget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; -import gregtech.common.covers.filter.FluidFilter; -import gregtech.common.covers.filter.FluidFilterWrapper; +import gregtech.client.utils.TooltipHelper; +import gregtech.common.covers.filter.BaseFilter; +import gregtech.common.covers.filter.FluidFilterContainer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; @@ -32,26 +32,34 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.drawable.Rectangle; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.layout.Column; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.IOException; + public class CoverFluidFilter extends CoverBase implements CoverWithUI { protected final String titleLocale; protected final SimpleOverlayRenderer texture; - protected final FluidFilterWrapper fluidFilter; + protected final FluidFilterContainer fluidFilterContainer; protected FluidFilterMode filterMode; protected FluidHandlerFiltered fluidHandler; public CoverFluidFilter(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, - @NotNull EnumFacing attachedSide, String titleLocale, SimpleOverlayRenderer texture, - FluidFilter fluidFilter) { + @NotNull EnumFacing attachedSide, String titleLocale, SimpleOverlayRenderer texture) { super(definition, coverableView, attachedSide); + this.fluidFilterContainer = new FluidFilterContainer(this); this.filterMode = FluidFilterMode.FILTER_FILL; this.titleLocale = titleLocale; this.texture = texture; - this.fluidFilter = new FluidFilterWrapper(this); - this.fluidFilter.setFluidFilter(fluidFilter); } public void setFilterMode(FluidFilterMode filterMode) { @@ -59,16 +67,51 @@ public void setFilterMode(FluidFilterMode filterMode) { this.getCoverableView().markDirty(); } - public FluidFilterMode getFilterMode() { - return filterMode; + @Override + public void onAttachment(@NotNull CoverableView coverableView, @NotNull EnumFacing side, + @Nullable EntityPlayer player, @NotNull ItemStack itemStack) { + super.onAttachment(coverableView, side, player, itemStack); + var dropStack = GTUtility.copy(1, itemStack); + this.fluidFilterContainer.setFilterStack(dropStack); } - public FluidFilterWrapper getFluidFilter() { - return this.fluidFilter; + @Override + public @NotNull ItemStack getPickItem() { + if (TooltipHelper.isCtrlDown()) + return getCoverableView().getStackForm(); + + return this.fluidFilterContainer.getFilterStack(); } - public boolean testFluidStack(FluidStack stack) { - return fluidFilter.testFluidStack(stack); + @Override + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + packetBuffer.writeByte(this.filterMode.ordinal()); + packetBuffer.writeBoolean(this.fluidFilterContainer.hasFilter()); + if (this.fluidFilterContainer.hasFilter()) { + packetBuffer.writeItemStack(this.fluidFilterContainer.getFilterStack()); + } + } + + @Override + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + this.filterMode = FluidFilterMode.VALUES[packetBuffer.readByte()]; + if (!packetBuffer.readBoolean()) return; + try { + this.fluidFilterContainer.setFilterStack(packetBuffer.readItemStack()); + } catch (IOException e) { + GTLog.logger.error("Failed to read filter for CoverFluidFilter! %s", getPos().toString()); + } + } + + public FluidFilterMode getFilterMode() { + return filterMode; + } + + @SuppressWarnings("DataFlowIssue") // this cover always has a filter + public @NotNull BaseFilter getFilter() { + return this.fluidFilterContainer.hasFilter() ? + this.fluidFilterContainer.getFilter() : + BaseFilter.ERROR_FILTER; } @Override @@ -89,18 +132,32 @@ public boolean canPipePassThrough() { return EnumActionResult.SUCCESS; } - public ModularUI createUI(EntityPlayer player) { - WidgetGroup fluidFilterGroup = new WidgetGroup(); - fluidFilterGroup.addWidget(new LabelWidget(10, 5, "cover.fluid_filter.title")); - fluidFilterGroup.addWidget(new CycleButtonWidget(10, 20, 110, 20, - GTUtility.mapToString(FluidFilterMode.values(), (it) -> it.localeName), () -> this.filterMode.ordinal(), - (newMode) -> this.setFilterMode(FluidFilterMode.values()[newMode]))); - this.fluidFilter.initUI(45, fluidFilterGroup::addWidget); - this.fluidFilter.blacklistUI(45, fluidFilterGroup::addWidget, () -> true); - return ModularUI.builder(GuiTextures.BACKGROUND, 176, 105 + 82) - .widget(fluidFilterGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 105) - .build(this, player); + @Override + public boolean usesMui2() { + return true; + } + + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + var filteringMode = new EnumSyncValue<>(FluidFilterMode.class, this::getFilterMode, this::setFilterMode); + + guiSyncManager.syncValue("filtering_mode", filteringMode); + this.fluidFilterContainer.setMaxTransferSize(1); + getFilter().getFilterReader().readStack(this.fluidFilterContainer.getFilterStack()); + + return getFilter().createPanel(guiSyncManager) + .size(176, 194).padding(7) + .child(CoverWithUI.createTitleRow(getPickItem())) + .child(new Column().widthRel(1f).align(Alignment.TopLeft).top(22).coverChildrenHeight() + .child(new EnumRowBuilder<>(FluidFilterMode.class) + .value(filteringMode) + .lang("cover.filter.mode.title") + .overlay(16, GTGuiTextures.FILTER_MODE_OVERLAY) + .build()) + .child(new Rectangle().setColor(UI_TEXT_COLOR).asWidget() + .height(1).widthRel(0.95f).margin(0, 4)) + .child(getFilter().createWidgets(guiSyncManager))) + .child(SlotGroupWidget.playerInventory().bottom(7).left(7)); } @Override @@ -127,18 +184,21 @@ public T getCapability(@NotNull Capability capability, @Nullable T defaul public void writeToNBT(@NotNull NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); tagCompound.setInteger("FilterMode", this.filterMode.ordinal()); - tagCompound.setBoolean("IsBlacklist", this.fluidFilter.isBlacklistFilter()); - NBTTagCompound filterComponent = new NBTTagCompound(); - this.fluidFilter.getFluidFilter().writeToNBT(filterComponent); - tagCompound.setTag("Filter", filterComponent); + tagCompound.setTag("Filter", this.fluidFilterContainer.serializeNBT()); } @Override public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.filterMode = FluidFilterMode.values()[tagCompound.getInteger("FilterMode")]; - this.fluidFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); - this.fluidFilter.getFluidFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); + var filterTag = tagCompound.getCompoundTag("Filter"); + if (!filterTag.hasKey("FilterInventory")) { + this.fluidFilterContainer.setFilterStack(getDefinition().getDropItemStack()); + } else { + this.fluidFilterContainer.deserializeNBT(filterTag); + } + + this.fluidFilterContainer.handleLegacyNBT(tagCompound); } private class FluidHandlerFiltered extends FluidHandlerDelegate { @@ -148,7 +208,7 @@ public FluidHandlerFiltered(@NotNull IFluidHandler delegate) { } public int fill(FluidStack resource, boolean doFill) { - if (getFilterMode() == FluidFilterMode.FILTER_DRAIN || !fluidFilter.testFluidStack(resource)) { + if (getFilterMode() == FluidFilterMode.FILTER_DRAIN || !fluidFilterContainer.test(resource)) { return 0; } return super.fill(resource, doFill); @@ -156,7 +216,7 @@ public int fill(FluidStack resource, boolean doFill) { @Nullable public FluidStack drain(FluidStack resource, boolean doDrain) { - if (getFilterMode() == FluidFilterMode.FILTER_FILL || !fluidFilter.testFluidStack(resource)) { + if (getFilterMode() == FluidFilterMode.FILTER_FILL || !fluidFilterContainer.test(resource)) { return null; } return super.drain(resource, doDrain); @@ -166,7 +226,7 @@ public FluidStack drain(FluidStack resource, boolean doDrain) { public FluidStack drain(int maxDrain, boolean doDrain) { if (getFilterMode() != FluidFilterMode.FILTER_FILL) { FluidStack result = super.drain(maxDrain, false); - if (result == null || result.amount <= 0 || !fluidFilter.testFluidStack(result)) { + if (result == null || result.amount <= 0 || !fluidFilterContainer.test(result)) { return null; } return doDrain ? super.drain(maxDrain, true) : result; diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 553f2734b46..dc55702148d 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -2,38 +2,37 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTTransferUtils; -import gregtech.api.util.TextFormattingUtil; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; -import gregtech.common.covers.filter.FluidFilter; import gregtech.common.covers.filter.FluidFilterContainer; +import gregtech.common.covers.filter.SimpleFluidFilter; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TextComponentString; -import net.minecraft.util.text.TextComponentTranslation; -import net.minecraft.util.text.event.HoverEvent; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import com.google.common.math.IntMath; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.apache.logging.log4j.message.FormattedMessage; import org.jetbrains.annotations.NotNull; import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Predicate; @@ -41,21 +40,11 @@ public class CoverFluidRegulator extends CoverPump { protected TransferMode transferMode = TransferMode.TRANSFER_ANY; - protected int transferAmount = 0; public CoverFluidRegulator(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, @NotNull EnumFacing attachedSide, int tier, int mbPerTick) { super(definition, coverableView, attachedSide, tier, mbPerTick); - this.fluidFilter = new FluidFilterContainer(this, this::shouldShowTip, maxFluidTransferRate * 100); - } - - @Override - protected boolean shouldShowTip() { - return transferMode != TransferMode.TRANSFER_ANY; - } - - public int getTransferAmount() { - return transferAmount; + this.fluidFilterContainer = new FluidFilterContainer(this); } @Override @@ -75,11 +64,12 @@ protected int doTransferFluidsInternal(IFluidHandler myFluidHandler, IFluidHandl } return switch (transferMode) { case TRANSFER_ANY -> GTTransferUtils.transferFluids(sourceHandler, destHandler, transferLimit, - fluidFilter::testFluidStack); - case KEEP_EXACT -> doKeepExact(transferLimit, sourceHandler, destHandler, fluidFilter::testFluidStack, - this.transferAmount); + fluidFilterContainer::test); + case KEEP_EXACT -> doKeepExact(transferLimit, sourceHandler, destHandler, + fluidFilterContainer::test, + this.fluidFilterContainer.getTransferSize()); case TRANSFER_EXACT -> doTransferExact(transferLimit, sourceHandler, destHandler, - fluidFilter::testFluidStack, this.transferAmount); + fluidFilterContainer::test, this.fluidFilterContainer.getTransferSize()); }; } @@ -88,9 +78,8 @@ protected int doTransferExact(int transferLimit, IFluidHandler sourceHandler, IF int fluidLeftToTransfer = transferLimit; for (IFluidTankProperties tankProperties : sourceHandler.getTankProperties()) { FluidStack sourceFluid = tankProperties.getContents(); - if (this.fluidFilter.getFilterWrapper().getFluidFilter() != null && - transferMode != TransferMode.TRANSFER_ANY) { - supplyAmount = this.fluidFilter.getFilterWrapper().getFluidFilter().getFluidTransferLimit(sourceFluid); + if (this.fluidFilterContainer.hasFilter()) { + supplyAmount = this.fluidFilterContainer.getFilter().getTransferLimit(sourceFluid, supplyAmount); } if (fluidLeftToTransfer < supplyAmount) break; @@ -132,9 +121,8 @@ protected int doKeepExact(final int transferLimit, if (transferred >= transferLimit) break; - if (this.fluidFilter.getFilterWrapper().getFluidFilter() != null && - transferMode != TransferMode.TRANSFER_ANY) { - keepAmount = this.fluidFilter.getFilterWrapper().getFluidFilter().getFluidTransferLimit(fluidStack); + if (this.fluidFilterContainer.hasFilter()) { + keepAmount = this.fluidFilterContainer.getFilter().getTransferLimit(fluidStack, keepAmount); } // if fluid needs to be moved to meet the Keep Exact value @@ -235,8 +223,11 @@ private static Map collectDistinctFluids(IFluidHandler hand } public void setTransferMode(TransferMode transferMode) { - this.transferMode = transferMode; - this.markDirty(); + if (this.transferMode != transferMode) { + this.transferMode = transferMode; + this.fluidFilterContainer.setMaxTransferSize(getMaxTransferRate()); + this.markDirty(); + } } public TransferMode getTransferMode() { @@ -244,122 +235,87 @@ public TransferMode getTransferMode() { } private boolean shouldDisplayAmountSlider() { - if (this.fluidFilter.getFilterWrapper().getFluidFilter() != null) { + if (transferMode == TransferMode.TRANSFER_ANY) { return false; } - return this.transferMode == TransferMode.TRANSFER_EXACT || this.transferMode == TransferMode.KEEP_EXACT; - } - - public String getTransferAmountString() { - return Integer.toString(this.bucketMode == BucketMode.BUCKET ? transferAmount / 1000 : transferAmount); - } - - private String getTransferSizeString() { - int val = transferAmount; - if (this.bucketMode == BucketMode.BUCKET) { - val /= 1000; - } - return val == -1 ? "" : TextFormattingUtil.formatLongToCompactString(val); - } - - protected void getHoverString(List textList) { - ITextComponent keepComponent = new TextComponentString(getTransferSizeString()); - TextComponentTranslation hoverKeep = new TextComponentTranslation( - "cover.fluid_regulator." + transferMode.name().toLowerCase(), this.transferAmount); - keepComponent.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverKeep)); - textList.add(keepComponent); + return fluidFilterContainer.showGlobalTransferLimitSlider(); } @Override - public void setBucketMode(BucketMode bucketMode) { - super.setBucketMode(bucketMode); - if (this.bucketMode == BucketMode.BUCKET) { - setTransferAmount(transferAmount / 1000 * 1000); - } + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 + 36); } - private void adjustTransferSize(int amount) { - if (bucketMode == BucketMode.BUCKET) - amount *= 1000; - switch (this.transferMode) { - case TRANSFER_EXACT -> setTransferAmount( - MathHelper.clamp(this.transferAmount + amount, 0, this.maxFluidTransferRate)); - case KEEP_EXACT -> setTransferAmount(MathHelper.clamp(this.transferAmount + amount, 0, Integer.MAX_VALUE)); - } + @Override + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncManager) { + var transferMode = new EnumSyncValue<>(TransferMode.class, this::getTransferMode, this::setTransferMode); + transferMode.updateCacheFromSource(true); + syncManager.syncValue("transfer_mode", transferMode); + + var bucketMode = new EnumSyncValue<>(BucketMode.class, this::getBucketMode, this::setBucketMode); + bucketMode.updateCacheFromSource(true); + syncManager.syncValue("bucket_mode", bucketMode); + + var filterTransferSize = new StringSyncValue(this::getStringTransferRate, this::setStringTransferRate); + filterTransferSize.updateCacheFromSource(true); + + return super.createUI(mainPanel, syncManager) + .child(new EnumRowBuilder<>(TransferMode.class) + .value(transferMode) + .lang("cover.generic.transfer_mode") + .overlay(GTGuiTextures.FLUID_TRANSFER_MODE_OVERLAY) + .build()) + .child(new EnumRowBuilder<>(BucketMode.class) + .value(bucketMode) + .overlay(IKey.str("kL"), IKey.str("L")) + .build() + .child(new TextFieldWidget().widthRel(0.5f).right(0) + .setEnabledIf(w -> shouldDisplayAmountSlider()) + .setNumbers(0, Integer.MAX_VALUE) + .value(filterTransferSize) + .setTextColor(Color.WHITE.darker(1)))); } - private void setTransferAmount(int transferAmount) { - this.transferAmount = transferAmount; - markDirty(); + @Override + public int getMaxTransferRate() { + return switch (this.transferMode) { + case TRANSFER_ANY -> 1; + case TRANSFER_EXACT -> maxFluidTransferRate; + case KEEP_EXACT -> Integer.MAX_VALUE; + }; } @Override - protected String getUITitle() { - return "cover.fluid_regulator.title"; + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.writeInitialSyncData(packetBuffer); + packetBuffer.writeByte(this.transferMode.ordinal()); } - @SuppressWarnings("UnstableApiUsage") @Override - protected ModularUI buildUI(ModularUI.Builder builder, EntityPlayer player) { - WidgetGroup filterGroup = new WidgetGroup(); - filterGroup.addWidget(new CycleButtonWidget(92, 43, 75, 18, - TransferMode.class, this::getTransferMode, this::setTransferMode) - .setTooltipHoverString("cover.fluid_regulator.transfer_mode.description")); - - ServerWidgetGroup stackSizeGroup = new ServerWidgetGroup(this::shouldDisplayAmountSlider); - stackSizeGroup.addWidget(new ImageWidget(110, 64, 38, 18, GuiTextures.DISPLAY)); - - stackSizeGroup.addWidget(new IncrementButtonWidget(148, 64, 18, 18, 1, 10, 100, 1000, this::adjustTransferSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - stackSizeGroup - .addWidget(new IncrementButtonWidget(92, 64, 18, 18, -1, -10, -100, -1000, this::adjustTransferSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - - stackSizeGroup.addWidget(new TextFieldWidget2(111, 70, 36, 11, this::getTransferAmountString, val -> { - if (val != null && !val.isEmpty()) { - int amount = Integer.parseInt(val); - if (this.bucketMode == BucketMode.BUCKET) { - amount = IntMath.saturatedMultiply(amount, 1000); - } - setTransferAmount(amount); - } - }) - .setCentered(true) - .setNumbersOnly(1, - transferMode == TransferMode.TRANSFER_EXACT ? maxFluidTransferRate : Integer.MAX_VALUE) - .setMaxLength(10) - .setScale(0.6f)); - - stackSizeGroup - .addWidget(new SimpleTextWidget(129, 78, "", 0xFFFFFF, () -> bucketMode.localeName).setScale(0.6f)); - - return super.buildUI(builder.widget(filterGroup).widget(stackSizeGroup), player); + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.readInitialSyncData(packetBuffer); + this.transferMode = TransferMode.VALUES[packetBuffer.readByte()]; } @Override public void writeToNBT(@NotNull NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); tagCompound.setInteger("TransferMode", transferMode.ordinal()); - tagCompound.setInteger("TransferAmount", transferAmount); tagCompound.setTag("filterv2", new NBTTagCompound()); } @Override public void readFromNBT(@NotNull NBTTagCompound tagCompound) { + this.transferMode = TransferMode.VALUES[tagCompound.getInteger("TransferMode")]; + this.fluidFilterContainer.setMaxTransferSize(this.transferMode.maxStackSize); super.readFromNBT(tagCompound); - this.transferMode = TransferMode.values()[tagCompound.getInteger("TransferMode")]; // legacy NBT tag if (!tagCompound.hasKey("filterv2") && tagCompound.hasKey("TransferAmount")) { - FluidFilter filter = getFluidFilterContainer().getFilterWrapper().getFluidFilter(); - if (filter != null) { - filter.configureFilterTanks(tagCompound.getInteger("TransferAmount")); + if (this.fluidFilterContainer.getFilter() instanceof SimpleFluidFilter simpleFluidFilter) { + simpleFluidFilter + .configureFilterTanks(tagCompound.getInteger("TransferAmount")); } } - this.transferAmount = tagCompound.getInteger("TransferAmount"); } @Override diff --git a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java index 4c1f097ccee..c781f816bef 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java +++ b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java @@ -3,11 +3,6 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.CycleButtonWidget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.WidgetGroup; import gregtech.api.util.GTTransferUtils; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.FluidFilterContainer; @@ -29,6 +24,15 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ToggleButton; +import com.cleanroommc.modularui.widgets.layout.Row; import org.jetbrains.annotations.NotNull; public class CoverFluidVoiding extends CoverPump { @@ -39,7 +43,8 @@ public CoverFluidVoiding(@NotNull CoverDefinition definition, @NotNull Coverable @NotNull EnumFacing attachedSide) { super(definition, coverableView, attachedSide, 0, Integer.MAX_VALUE); this.isWorkingAllowed = false; - this.fluidFilter = new FluidFilterContainer(this, this::shouldShowTip, Integer.MAX_VALUE); + this.fluidFilterContainer = new FluidFilterContainer(this); + this.fluidFilterContainer.setMaxTransferSize(Integer.MAX_VALUE); } @Override @@ -55,39 +60,46 @@ protected void doTransferFluids() { if (myFluidHandler == null) { return; } - GTTransferUtils.transferFluids(myFluidHandler, nullFluidTank, Integer.MAX_VALUE, fluidFilter::testFluidStack); + GTTransferUtils.transferFluids(myFluidHandler, nullFluidTank, Integer.MAX_VALUE, + fluidFilterContainer::test); } @Override - protected String getUITitle() { - return "cover.fluid.voiding.title"; + public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 translation, + IVertexOperation[] pipeline, @NotNull Cuboid6 plateBox, @NotNull BlockRenderLayer layer) { + Textures.FLUID_VOIDING.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle())); - - this.fluidFilter.initUI(20, primaryGroup::addWidget); - - primaryGroup.addWidget(new CycleButtonWidget(10, 92, 80, 18, this::isWorkingEnabled, this::setWorkingEnabled, - "cover.voiding.label.disabled", "cover.voiding.label.enabled") - .setTooltipHoverString("cover.voiding.tooltip")); + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 - 22); + } - primaryGroup.addWidget(new CycleButtonWidget(10, 112, 116, 18, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); + @Override + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncManager) { + var isWorking = new BooleanSyncValue(this::isWorkingEnabled, this::setWorkingEnabled); + + return super.createUI(mainPanel, syncManager) + .child(new Row().height(18).widthRel(1f) + .marginBottom(2) + .child(new ToggleButton() + .value(isWorking) + .overlay(IKey.dynamic(() -> IKey.lang(this.isWorkingAllowed ? + "behaviour.soft_hammer.enabled" : + "behaviour.soft_hammer.disabled").get()) + .color(Color.WHITE.darker(1))) + .widthRel(0.6f) + .left(0))); + } - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 100 + 82 + 16 + 24) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 100 + 16 + 24); - return builder.build(this, player); + @Override + protected boolean createPumpModeRow() { + return false; } @Override - public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 translation, - IVertexOperation[] pipeline, @NotNull Cuboid6 plateBox, @NotNull BlockRenderLayer layer) { - Textures.FLUID_VOIDING.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); + protected boolean createThroughputRow() { + return false; } @Override @@ -120,7 +132,7 @@ public NullFluidTank() { @Override public int fill(FluidStack resource, boolean doFill) { - if (fluidFilter.testFluidStack(resource)) { + if (fluidFilterContainer.test(resource)) { return resource.amount; } return 0; diff --git a/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java b/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java index 4d2290aa13b..3af29c03b3b 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java +++ b/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java @@ -2,18 +2,14 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTTransferUtils; import gregtech.client.renderer.texture.Textures; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.MathHelper; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -23,9 +19,17 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; -import java.util.function.Consumer; import java.util.function.Predicate; public class CoverFluidVoidingAdvanced extends CoverFluidVoiding { @@ -38,11 +42,6 @@ public CoverFluidVoidingAdvanced(@NotNull CoverDefinition definition, @NotNull C super(definition, coverableView, attachedSide); } - @Override - protected boolean shouldShowTip() { - return voidingMode != VoidingMode.VOID_ANY; - } - @Override protected void doTransferFluids() { IFluidHandler myFluidHandler = getCoverableView().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, @@ -52,8 +51,9 @@ protected void doTransferFluids() { } switch (voidingMode) { case VOID_ANY -> GTTransferUtils.transferFluids(myFluidHandler, nullFluidTank, Integer.MAX_VALUE, - fluidFilter::testFluidStack); - case VOID_OVERFLOW -> voidOverflow(myFluidHandler, fluidFilter::testFluidStack, this.transferAmount); + fluidFilterContainer::test); + case VOID_OVERFLOW -> voidOverflow(myFluidHandler, fluidFilterContainer::test, + this.transferAmount); } } @@ -72,45 +72,26 @@ protected void voidOverflow(final IFluidHandler sourceHandler, for (IFluidTankProperties tankProperties : sourceHandler.getTankProperties()) { FluidStack sourceFluid = tankProperties.getContents(); - if (this.fluidFilter.getFilterWrapper().getFluidFilter() != null && + if (this.fluidFilterContainer.hasFilter() && voidingMode == VoidingMode.VOID_OVERFLOW) { - keepAmount = this.fluidFilter.getFilterWrapper().getFluidFilter().getFluidTransferLimit(sourceFluid); + keepAmount = this.fluidFilterContainer.getFilter() + .getTransferLimit(sourceFluid, getMaxTransferRate()); } if (sourceFluid == null || sourceFluid.amount == 0 || - !getFluidFilterContainer().testFluidStack(sourceFluid, true)) + !getFluidFilterContainer().test(sourceFluid)) continue; sourceFluid.amount = sourceFluid.amount - keepAmount; sourceHandler.drain(sourceFluid, true); } } - @Override - public void setBucketMode(BucketMode bucketMode) { - super.setBucketMode(bucketMode); - if (this.bucketMode == BucketMode.BUCKET) { - setTransferAmount(transferAmount / 1000 * 1000); - } - } - - private void adjustTransferSize(int amount) { - if (bucketMode == BucketMode.BUCKET) - amount *= 1000; - if (this.voidingMode == VoidingMode.VOID_OVERFLOW) { - setTransferAmount(MathHelper.clamp(this.transferAmount + amount, 0, Integer.MAX_VALUE)); - } - } - - private void setTransferAmount(int transferAmount) { - this.transferAmount = transferAmount; - markDirty(); - } - public int getTransferAmount() { - return this.transferAmount; + return this.fluidFilterContainer.getTransferSize(); } public void setVoidingMode(VoidingMode transferMode) { this.voidingMode = transferMode; + this.fluidFilterContainer.setMaxTransferSize(getMaxTransferRate()); this.markDirty(); } @@ -118,101 +99,64 @@ public VoidingMode getVoidingMode() { return voidingMode; } - private boolean shouldDisplayAmountSlider() { - if (this.fluidFilter.getFilterWrapper().getFluidFilter() != null) { - return false; - } - - return this.voidingMode == VoidingMode.VOID_OVERFLOW; + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 + 20); } - public String getTransferAmountString() { - return Integer.toString(this.bucketMode == BucketMode.BUCKET ? transferAmount / 1000 : transferAmount); + @Override + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncManager) { + var voidingMode = new EnumSyncValue<>(VoidingMode.class, this::getVoidingMode, this::setVoidingMode); + syncManager.syncValue("voiding_mode", voidingMode); + + var bucketMode = new EnumSyncValue<>(BucketMode.class, this::getBucketMode, this::setBucketMode); + bucketMode.updateCacheFromSource(true); + syncManager.syncValue("bucket_mode", bucketMode); + + var filterTransferSize = new StringSyncValue(this::getStringTransferRate, this::setStringTransferRate); + var transferTextField = new TextFieldWidget().widthRel(0.5f).right(0); + transferTextField.setEnabled(this.fluidFilterContainer.showGlobalTransferLimitSlider() && + this.voidingMode == VoidingMode.VOID_OVERFLOW); + + return super.createUI(mainPanel, syncManager) + .child(new EnumRowBuilder<>(VoidingMode.class) + .value(voidingMode) + .lang("cover.voiding.voiding_mode") + .overlay(16, GTGuiTextures.VOIDING_MODE_OVERLAY) + .build()) + .child(new EnumRowBuilder<>(BucketMode.class) + .value(bucketMode) + .overlay(IKey.str("kL"), IKey.str("L")) + .build() + .child(transferTextField + .setEnabledIf(w -> this.fluidFilterContainer.showGlobalTransferLimitSlider() && + this.voidingMode == VoidingMode.VOID_OVERFLOW) + .setNumbers(0, Integer.MAX_VALUE) + .value(filterTransferSize) + .setTextColor(Color.WHITE.darker(1)))); } @Override - protected String getUITitle() { - return "cover.fluid.voiding.advanced.title"; + protected int getMaxTransferRate() { + return getVoidingMode().maxStackSize; } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle())); - - primaryGroup.addWidget(new CycleButtonWidget(92, 15, 75, 18, - VoidingMode.class, this::getVoidingMode, this::setVoidingMode) - .setTooltipHoverString("cover.voiding.voiding_mode.description")); - - this.initFilterUI(20, primaryGroup::addWidget); - - primaryGroup.addWidget(new CycleButtonWidget(10, 92, 80, 18, this::isWorkingEnabled, this::setWorkingEnabled, - "cover.voiding.label.disabled", "cover.voiding.label.enabled") - .setTooltipHoverString("cover.voiding.tooltip")); - - primaryGroup.addWidget(new CycleButtonWidget(10, 112, 116, 18, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); - - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 100 + 82 + 16 + 24) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 100 + 16 + 24); - return buildUI(builder, player); + public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 translation, + IVertexOperation[] pipeline, @NotNull Cuboid6 plateBox, @NotNull BlockRenderLayer layer) { + Textures.FLUID_VOIDING_ADVANCED.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } - public void initFilterUI(int y, Consumer widgetGroup) { - widgetGroup.accept(new LabelWidget(10, y, "cover.pump.fluid_filter.title")); - widgetGroup.accept(new SlotWidget(fluidFilter.getFilterInventory(), 0, 10, y + 15) - .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.FILTER_SLOT_OVERLAY)); - - ServerWidgetGroup stackSizeGroup = new ServerWidgetGroup(this::shouldDisplayAmountSlider); - stackSizeGroup.addWidget(new ImageWidget(110, 34, 38, 18, GuiTextures.DISPLAY)); - - stackSizeGroup.addWidget(new IncrementButtonWidget(148, 34, 18, 18, 1, 10, 100, 1000, this::adjustTransferSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - stackSizeGroup - .addWidget(new IncrementButtonWidget(92, 34, 18, 18, -1, -10, -100, -1000, this::adjustTransferSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - - stackSizeGroup.addWidget(new TextFieldWidget2(111, 39, 37, 11, this::getTransferAmountString, val -> { - if (val != null && !val.isEmpty()) { - int amount = Integer.parseInt(val); - if (this.bucketMode == BucketMode.BUCKET) { - amount *= 1000; - } - setTransferAmount(amount); - } - }) - .setCentered(true) - .setNumbersOnly(1, Integer.MAX_VALUE) - .setMaxLength(10) - .setScale(0.6f)); - - stackSizeGroup - .addWidget(new SimpleTextWidget(129, 47, "", 0xFFFFFF, () -> bucketMode.localeName).setScale(0.6f)); - - stackSizeGroup.addWidget(new CycleButtonWidget(114, 53, 30, 20, - BucketMode.class, this::getBucketMode, mode -> { - if (mode != bucketMode) { - setBucketMode(mode); - } - })); - - widgetGroup.accept(stackSizeGroup); - - this.fluidFilter.getFilterWrapper().initUI(y + 15, widgetGroup); - this.fluidFilter.getFilterWrapper().blacklistUI(y + 15, widgetGroup, - () -> voidingMode != VoidingMode.VOID_OVERFLOW); + @Override + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.readInitialSyncData(packetBuffer); + this.voidingMode = VoidingMode.VALUES[packetBuffer.readByte()]; } @Override - public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 translation, - IVertexOperation[] pipeline, @NotNull Cuboid6 plateBox, @NotNull BlockRenderLayer layer) { - Textures.FLUID_VOIDING_ADVANCED.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.writeInitialSyncData(packetBuffer); + packetBuffer.writeByte(this.voidingMode.ordinal()); } @Override @@ -224,8 +168,9 @@ public void writeToNBT(@NotNull NBTTagCompound tagCompound) { @Override public void readFromNBT(@NotNull NBTTagCompound tagCompound) { - super.readFromNBT(tagCompound); - this.voidingMode = VoidingMode.values()[tagCompound.getInteger("VoidingMode")]; + this.voidingMode = VoidingMode.VALUES[tagCompound.getInteger("VoidingMode")]; + this.fluidFilterContainer.setMaxTransferSize(this.voidingMode.maxStackSize); this.transferAmount = tagCompound.getInteger("TransferAmount"); + super.readFromNBT(tagCompound); } } diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 656fe17f5d8..909fb09e481 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -5,20 +5,19 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.CycleButtonWidget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; -import gregtech.common.covers.filter.ItemFilter; -import gregtech.common.covers.filter.ItemFilterWrapper; +import gregtech.client.utils.TooltipHelper; +import gregtech.common.covers.filter.BaseFilter; +import gregtech.common.covers.filter.ItemFilterContainer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; @@ -32,25 +31,69 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.drawable.Rectangle; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.layout.Column; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; public class CoverItemFilter extends CoverBase implements CoverWithUI { protected final String titleLocale; protected final SimpleOverlayRenderer texture; - protected final ItemFilterWrapper itemFilter; + protected final ItemFilterContainer itemFilterContainer; protected ItemFilterMode filterMode = ItemFilterMode.FILTER_INSERT; protected ItemHandlerFiltered itemHandler; public CoverItemFilter(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, - @NotNull EnumFacing attachedSide, String titleLocale, SimpleOverlayRenderer texture, - ItemFilter itemFilter) { + @NotNull EnumFacing attachedSide, String titleLocale, SimpleOverlayRenderer texture) { super(definition, coverableView, attachedSide); this.titleLocale = titleLocale; this.texture = texture; - this.itemFilter = new ItemFilterWrapper(this); - this.itemFilter.setItemFilter(itemFilter); - this.itemFilter.setMaxStackSize(1); + this.itemFilterContainer = new ItemFilterContainer(this); + } + + @Override + public void onAttachment(@NotNull CoverableView coverableView, @NotNull EnumFacing side, + @Nullable EntityPlayer player, @NotNull ItemStack itemStack) { + super.onAttachment(coverableView, side, player, itemStack); + var dropStack = GTUtility.copy(1, itemStack); + this.itemFilterContainer.setFilterStack(dropStack); + } + + @Override + public @NotNull ItemStack getPickItem() { + if (TooltipHelper.isCtrlDown()) + return getCoverableView().getStackForm(); + + return this.itemFilterContainer.getFilterStack(); + } + + @Override + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + packetBuffer.writeBoolean(itemFilterContainer.hasFilter()); + if (itemFilterContainer.hasFilter()) { + packetBuffer.writeByte(this.filterMode.ordinal()); + packetBuffer.writeItemStack(this.itemFilterContainer.getFilterStack()); + } + } + + @Override + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + if (!packetBuffer.readBoolean()) return; + this.filterMode = ItemFilterMode.VALUES[packetBuffer.readByte()]; + try { + this.itemFilterContainer.setFilterStack(packetBuffer.readItemStack()); + } catch (IOException e) { + GTLog.logger.error("Failed to read filter for CoverItemFilter! %s", getPos().toString()); + } } public void setFilterMode(ItemFilterMode filterMode) { @@ -62,8 +105,11 @@ public ItemFilterMode getFilterMode() { return filterMode; } - public ItemFilterWrapper getItemFilter() { - return this.itemFilter; + @SuppressWarnings("DataFlowIssue") // this cover should always have a filter + public @NotNull BaseFilter getFilter() { + return this.itemFilterContainer.hasFilter() ? + this.itemFilterContainer.getFilter() : + BaseFilter.ERROR_FILTER; } @Override @@ -86,22 +132,34 @@ public boolean canPipePassThrough() { } public boolean testItemStack(ItemStack stack) { - return itemFilter.testItemStack(stack); + return itemFilterContainer.test(stack); } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup filterGroup = new WidgetGroup(); - filterGroup.addWidget(new LabelWidget(10, 5, titleLocale)); - filterGroup.addWidget(new CycleButtonWidget(10, 20, 110, 20, - GTUtility.mapToString(ItemFilterMode.values(), it -> it.localeName), - () -> filterMode.ordinal(), (newMode) -> setFilterMode(ItemFilterMode.values()[newMode]))); - this.itemFilter.initUI(45, filterGroup::addWidget); - this.itemFilter.blacklistUI(45, filterGroup::addWidget, () -> true); - return ModularUI.builder(GuiTextures.BACKGROUND, 176, 105 + 82) - .widget(filterGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 105) - .build(this, player); + public boolean usesMui2() { + return true; + } + + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + var filteringMode = new EnumSyncValue<>(ItemFilterMode.class, this::getFilterMode, this::setFilterMode); + + guiSyncManager.syncValue("filtering_mode", filteringMode); + getFilter().getFilterReader().readStack(this.itemFilterContainer.getFilterStack()); + + return getFilter().createPanel(guiSyncManager) + .size(176, 194).padding(7) + .child(CoverWithUI.createTitleRow(getPickItem()).left(4)) + .child(new Column().widthRel(1f).align(Alignment.TopLeft).top(22).coverChildrenHeight() + .child(new EnumRowBuilder<>(ItemFilterMode.class) + .value(filteringMode) + .lang("cover.filter.mode.title") + .overlay(16, GTGuiTextures.FILTER_MODE_OVERLAY) + .build()) + .child(new Rectangle().setColor(UI_TEXT_COLOR).asWidget() + .height(1).widthRel(0.95f).margin(0, 4)) + .child(getFilter().createWidgets(guiSyncManager).left(0))) + .child(SlotGroupWidget.playerInventory().bottom(7).left(7)); } @Override @@ -114,18 +172,20 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO public void writeToNBT(@NotNull NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); tagCompound.setInteger("FilterMode", filterMode.ordinal()); - tagCompound.setBoolean("IsBlacklist", this.itemFilter.isBlacklistFilter()); - NBTTagCompound filterComponent = new NBTTagCompound(); - this.itemFilter.getItemFilter().writeToNBT(filterComponent); - tagCompound.setTag("Filter", filterComponent); + tagCompound.setTag("Filter", this.itemFilterContainer.serializeNBT()); } @Override public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); - this.filterMode = ItemFilterMode.values()[tagCompound.getInteger("FilterMode")]; - this.itemFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); - this.itemFilter.getItemFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); + this.filterMode = ItemFilterMode.VALUES[tagCompound.getInteger("FilterMode")]; + var filterTag = tagCompound.getCompoundTag("Filter"); + if (!filterTag.hasKey("FilterInventory")) { + this.itemFilterContainer.setFilterStack(getDefinition().getDropItemStack()); + } else { + this.itemFilterContainer.deserializeNBT(filterTag); + } + this.itemFilterContainer.handleLegacyNBT(tagCompound); } @Override @@ -152,7 +212,7 @@ public ItemHandlerFiltered(IItemHandler delegate) { @NotNull @Override public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { - if (getFilterMode() == ItemFilterMode.FILTER_EXTRACT || !itemFilter.testItemStack(stack)) { + if (getFilterMode() == ItemFilterMode.FILTER_EXTRACT || !itemFilterContainer.test(stack)) { return stack; } return super.insertItem(slot, stack, simulate); @@ -163,7 +223,7 @@ public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate public ItemStack extractItem(int slot, int amount, boolean simulate) { if (getFilterMode() != ItemFilterMode.FILTER_INSERT) { ItemStack result = super.extractItem(slot, amount, true); - if (result.isEmpty() || !itemFilter.testItemStack(result)) { + if (result.isEmpty() || !itemFilterContainer.test(result)) { return ItemStack.EMPTY; } return simulate ? result : super.extractItem(slot, amount, false); diff --git a/src/main/java/gregtech/common/covers/CoverItemVoiding.java b/src/main/java/gregtech/common/covers/CoverItemVoiding.java index 9a515b670d3..977968bbab1 100644 --- a/src/main/java/gregtech/common/covers/CoverItemVoiding.java +++ b/src/main/java/gregtech/common/covers/CoverItemVoiding.java @@ -3,11 +3,6 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.CycleButtonWidget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.WidgetGroup; import gregtech.client.renderer.texture.Textures; import net.minecraft.entity.player.EntityPlayer; @@ -26,6 +21,16 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ToggleButton; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; import org.jetbrains.annotations.NotNull; public class CoverItemVoiding extends CoverConveyor { @@ -60,7 +65,7 @@ void voidAny(IItemHandler myItemHandler) { if (sourceStack.isEmpty()) { continue; } - if (!itemFilterContainer.testItemStack(sourceStack)) { + if (!itemFilterContainer.test(sourceStack)) { continue; } myItemHandler.extractItem(srcIndex, Integer.MAX_VALUE, false); @@ -68,29 +73,40 @@ void voidAny(IItemHandler myItemHandler) { } @Override - protected String getUITitle() { - return "cover.item.voiding.title"; + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 - 22); } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle())); - this.itemFilterContainer.initUI(20, primaryGroup::addWidget); - - primaryGroup - .addWidget(new CycleButtonWidget(10, 92 + 23, 80, 18, this::isWorkingEnabled, this::setWorkingEnabled, - "cover.voiding.label.disabled", "cover.voiding.label.enabled") - .setTooltipHoverString("cover.voiding.tooltip")); - - primaryGroup.addWidget(new CycleButtonWidget(10, 112 + 23, 116, 18, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); - - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 125 + 82 + 16 + 24) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 125 + 16 + 24); - return builder.build(this, player); + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager guiSyncManager) { + var isWorking = new BooleanSyncValue(this::isWorkingEnabled, this::setWorkingEnabled); + + return super.createUI(mainPanel, guiSyncManager) + .child(new Row().height(18).widthRel(1f) + .marginBottom(2) + .child(new ToggleButton() + .value(isWorking) + .overlay(IKey.dynamic(() -> IKey.lang(this.isWorkingAllowed ? + "behaviour.soft_hammer.enabled" : + "behaviour.soft_hammer.disabled").get()) + .color(Color.WHITE.darker(1))) + .widthRel(0.6f) + .left(0))); + } + + @Override + protected boolean createThroughputRow() { + return false; + } + + @Override + protected boolean createConveyorModeRow() { + return false; + } + + @Override + protected boolean createDistributionModeRow() { + return false; } @Override @@ -137,7 +153,7 @@ public ItemStack getStackInSlot(int slot) { @NotNull @Override public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { - if (!itemFilterContainer.testItemStack(stack)) { + if (!itemFilterContainer.test(stack)) { return stack; } return ItemStack.EMPTY; diff --git a/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java b/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java index 62d2844aaa3..fe7a52f64e5 100644 --- a/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java +++ b/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java @@ -2,18 +2,14 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; import gregtech.client.renderer.texture.Textures; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.MathHelper; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; @@ -21,10 +17,19 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; import java.util.Map; -import java.util.function.Consumer; public class CoverItemVoidingAdvanced extends CoverItemVoiding { @@ -34,7 +39,7 @@ public CoverItemVoidingAdvanced(@NotNull CoverDefinition definition, @NotNull Co @NotNull EnumFacing attachedSide) { super(definition, coverableView, attachedSide); this.voidingMode = VoidingMode.VOID_ANY; - this.itemFilterContainer.setMaxStackSize(1); + this.itemFilterContainer.setMaxTransferSize(1); } @Override @@ -56,13 +61,11 @@ protected void voidOverflow(IItemHandler myItemHandler) { for (TypeItemInfo typeItemInfo : itemTypeCount.values()) { int itemToVoidAmount = 0; - if (getItemFilterContainer().getFilterWrapper().getItemFilter() == null) { - itemToVoidAmount = typeItemInfo.totalCount - itemFilterContainer.getTransferStackSize(); + if (!getItemFilterContainer().hasFilter()) { + itemToVoidAmount = typeItemInfo.totalCount - itemFilterContainer.getTransferSize(); } else { - if (itemFilterContainer.testItemStack(typeItemInfo.itemStack)) { - Object matchedSlot = itemFilterContainer.matchItemStack(typeItemInfo.itemStack); - itemToVoidAmount = typeItemInfo.totalCount - itemFilterContainer.getSlotTransferLimit(matchedSlot); - } + var result = itemFilterContainer.match(typeItemInfo.itemStack); + itemToVoidAmount = result.getItemStack().getCount(); } if (itemToVoidAmount <= 0) { @@ -86,75 +89,41 @@ protected void voidOverflow(IItemHandler myItemHandler) { } @Override - protected String getUITitle() { - return "cover.item.voiding.advanced.title"; + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 + 18); } @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle())); - - primaryGroup.addWidget(new CycleButtonWidget(91, 14, 75, 20, - VoidingMode.class, this::getVoidingMode, this::setVoidingMode) - .setTooltipHoverString("cover.voiding.voiding_mode.description")); - - this.initFilterUI(20, primaryGroup::addWidget); - - primaryGroup - .addWidget(new CycleButtonWidget(10, 92 + 23, 80, 18, this::isWorkingEnabled, this::setWorkingEnabled, - "cover.voiding.label.disabled", "cover.voiding.label.enabled") - .setTooltipHoverString("cover.voiding.tooltip")); - - primaryGroup.addWidget(new CycleButtonWidget(10, 112 + 23, 116, 18, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); - - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 125 + 82 + 16 + 24) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 125 + 16 + 24); - return buildUI(builder, player); + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager guiSyncManager) { + var voidingMode = new EnumSyncValue<>(VoidingMode.class, this::getVoidingMode, this::setVoidingMode); + guiSyncManager.syncValue("voiding_mode", voidingMode); + + var filterTransferSize = new StringSyncValue( + () -> String.valueOf(this.itemFilterContainer.getTransferSize()), + s -> this.itemFilterContainer.setTransferSize(Integer.parseInt(s))); + filterTransferSize.updateCacheFromSource(true); + var transferTextField = new TextFieldWidget().widthRel(0.5f).right(0); + transferTextField.setEnabled(this.itemFilterContainer.showGlobalTransferLimitSlider() && + this.voidingMode == VoidingMode.VOID_OVERFLOW); + + return super.createUI(mainPanel, guiSyncManager) + .child(new EnumRowBuilder<>(VoidingMode.class) + .value(voidingMode) + .lang("cover.voiding.voiding_mode") + .overlay(16, GTGuiTextures.VOIDING_MODE_OVERLAY) + .build()) + .child(new Row().right(0).coverChildrenHeight() + .child(transferTextField + .setEnabledIf(w -> this.itemFilterContainer.showGlobalTransferLimitSlider() && + this.voidingMode == VoidingMode.VOID_OVERFLOW) + .setNumbers(0, Integer.MAX_VALUE) + .value(filterTransferSize) + .setTextColor(Color.WHITE.darker(1)))); } - // Basically the item filter container GUI code, with different Y widget positioning - public void initFilterUI(int y, Consumer widgetGroup) { - widgetGroup.accept(new LabelWidget(10, y, "cover.conveyor.item_filter.title")); - widgetGroup.accept(new SlotWidget(itemFilterContainer.getFilterInventory(), 0, 10, y + 15) - .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.FILTER_SLOT_OVERLAY)); - - ServerWidgetGroup stackSizeGroup = new ServerWidgetGroup( - () -> itemFilterContainer.getFilterWrapper().getItemFilter() == null && - voidingMode == VoidingMode.VOID_OVERFLOW); - stackSizeGroup.addWidget(new ImageWidget(111, 34, 35, 20, GuiTextures.DISPLAY)); - - stackSizeGroup.addWidget( - new IncrementButtonWidget(146, 34, 20, 20, 1, 8, 64, 512, itemFilterContainer::adjustTransferStackSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - stackSizeGroup.addWidget(new IncrementButtonWidget(91, 34, 20, 20, -1, -8, -64, -512, - itemFilterContainer::adjustTransferStackSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - - stackSizeGroup.addWidget(new TextFieldWidget2(113, 41, 31, 20, - () -> String.valueOf(itemFilterContainer.getTransferStackSize()), val -> { - if (val != null && !val.isEmpty()) - itemFilterContainer.setTransferStackSize( - MathHelper.clamp(Integer.parseInt(val), 1, voidingMode.maxStackSize)); - }) - .setCentered(true) - .setNumbersOnly(1, Integer.MAX_VALUE) - .setMaxLength(10) - .setScale(0.9f)); - - widgetGroup.accept(stackSizeGroup); - - this.itemFilterContainer.getFilterWrapper().initUI(y + 38, widgetGroup); - - this.itemFilterContainer.getFilterWrapper().blacklistUI(y + 38, widgetGroup, - () -> voidingMode != VoidingMode.VOID_OVERFLOW); + @Override + protected int getMaxStackSize() { + return getVoidingMode().maxStackSize; } @Override @@ -165,7 +134,7 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO public void setVoidingMode(VoidingMode voidingMode) { this.voidingMode = voidingMode; - this.itemFilterContainer.setMaxStackSize(voidingMode.maxStackSize); + this.itemFilterContainer.setMaxTransferSize(getMaxStackSize()); this.getCoverableView().markDirty(); } @@ -173,6 +142,18 @@ public VoidingMode getVoidingMode() { return voidingMode; } + @Override + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.writeInitialSyncData(packetBuffer); + packetBuffer.writeByte(this.voidingMode.ordinal()); + } + + @Override + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.readInitialSyncData(packetBuffer); + this.voidingMode = VoidingMode.VALUES[packetBuffer.readByte()]; + } + @Override public void writeToNBT(NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); @@ -181,7 +162,8 @@ public void writeToNBT(NBTTagCompound tagCompound) { @Override public void readFromNBT(NBTTagCompound tagCompound) { + this.voidingMode = VoidingMode.VALUES[tagCompound.getInteger("VoidMode")]; + this.itemFilterContainer.setMaxTransferSize(this.voidingMode.maxStackSize); super.readFromNBT(tagCompound); - this.voidingMode = VoidingMode.values()[tagCompound.getInteger("VoidMode")]; } } diff --git a/src/main/java/gregtech/common/covers/CoverMachineController.java b/src/main/java/gregtech/common/covers/CoverMachineController.java index 423a44fccd3..517a9bc5711 100644 --- a/src/main/java/gregtech/common/covers/CoverMachineController.java +++ b/src/main/java/gregtech/common/covers/CoverMachineController.java @@ -120,7 +120,7 @@ public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManag guiSyncManager.syncValue("inverted", invertedValue); return GTGuis.createPanel(this, 176, 112) - .child(createTitleRow()) + .child(CoverWithUI.createTitleRow(getPickItem())) .child(new Column() .widthRel(1.0f).margin(7, 0) .top(24).coverChildrenHeight() diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index 961e349be6b..e91a59118a6 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -1,6 +1,5 @@ package gregtech.common.covers; -import gregtech.api.GTValues; import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; @@ -9,14 +8,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.CycleButtonWidget; -import gregtech.api.gui.widgets.ImageWidget; -import gregtech.api.gui.widgets.IncrementButtonWidget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.TextFieldWidget2; -import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; @@ -47,13 +40,23 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; -import com.google.common.math.IntMath; +import com.cleanroommc.modularui.api.widget.Interactable; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.utils.MouseData; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.function.Function; -import java.util.function.IntSupplier; - public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable { public final int tier; @@ -65,7 +68,7 @@ public class CoverPump extends CoverBase implements CoverWithUI, ITickable, ICon protected int fluidLeftToTransferLastSecond; private CoverableFluidHandlerWrapper fluidHandlerWrapper; protected boolean isWorkingAllowed = true; - protected FluidFilterContainer fluidFilter; + protected FluidFilterContainer fluidFilterContainer; protected BucketMode bucketMode = BucketMode.MILLI_BUCKET; public CoverPump(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, @@ -75,25 +78,35 @@ public CoverPump(@NotNull CoverDefinition definition, @NotNull CoverableView cov this.maxFluidTransferRate = mbPerTick; this.transferRate = mbPerTick; this.fluidLeftToTransferLastSecond = transferRate; - this.fluidFilter = new FluidFilterContainer(this, this::shouldShowTip); + this.fluidFilterContainer = new FluidFilterContainer(this); + } + + public void setStringTransferRate(String s) { + this.fluidFilterContainer.setTransferSize( + getBucketMode() == BucketMode.MILLI_BUCKET ? + Integer.parseInt(s) : + Integer.parseInt(s) * 1000); } - protected boolean shouldShowTip() { - return false; + public String getStringTransferRate() { + return String.valueOf(getBucketMode() == BucketMode.MILLI_BUCKET ? + this.fluidFilterContainer.getTransferSize() : + this.fluidFilterContainer.getTransferSize() / 1000); } public void setTransferRate(int transferRate) { - this.transferRate = transferRate; + if (bucketMode == BucketMode.BUCKET) transferRate *= 1000; + this.transferRate = MathHelper.clamp(transferRate, 1, maxFluidTransferRate); markDirty(); } public int getTransferRate() { - return transferRate; + return bucketMode == BucketMode.BUCKET ? transferRate / 1000 : transferRate; } protected void adjustTransferRate(int amount) { amount *= this.bucketMode == BucketMode.BUCKET ? 1000 : 1; - setTransferRate(MathHelper.clamp(transferRate + amount, 1, maxFluidTransferRate)); + setTransferRate(this.transferRate + amount); } public void setPumpMode(PumpMode pumpMode) { @@ -127,7 +140,7 @@ protected void setManualImportExportMode(ManualImportExportMode manualImportExpo } public FluidFilterContainer getFluidFilterContainer() { - return fluidFilter; + return fluidFilterContainer; } @Override @@ -157,100 +170,124 @@ protected int doTransferFluidsInternal(IFluidHandler myFluidHandler, IFluidHandl int transferLimit) { if (pumpMode == PumpMode.IMPORT) { return GTTransferUtils.transferFluids(fluidHandler, myFluidHandler, transferLimit, - fluidFilter::testFluidStack); + fluidFilterContainer::test); } else if (pumpMode == PumpMode.EXPORT) { return GTTransferUtils.transferFluids(myFluidHandler, fluidHandler, transferLimit, - fluidFilter::testFluidStack); + fluidFilterContainer::test); } return 0; } protected boolean checkInputFluid(FluidStack fluidStack) { - return fluidFilter.testFluidStack(fluidStack); + return fluidFilterContainer.test(fluidStack); } - protected ModularUI buildUI(ModularUI.Builder builder, EntityPlayer player) { - return builder.build(this, player); + @Override + public boolean usesMui2() { + return true; } - protected String getUITitle() { - return "cover.pump.title"; + @Override + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + var panel = GTGuis.createPanel(this, 176, 192); + + getFluidFilterContainer().setMaxTransferSize(getMaxTransferRate()); + + return panel.child(CoverWithUI.createTitleRow(getPickItem())) + .child(createUI(panel, guiSyncManager)) + .bindPlayerInventory(); + } + + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncManager) { + var manualIOmode = new EnumSyncValue<>(ManualImportExportMode.class, + this::getManualImportExportMode, this::setManualImportExportMode); + manualIOmode.updateCacheFromSource(true); + + var throughput = new IntSyncValue(this::getTransferRate, this::setTransferRate); + throughput.updateCacheFromSource(true); + + var throughputString = new StringSyncValue( + throughput::getStringValue, + throughput::setStringValue); + throughputString.updateCacheFromSource(true); + + var pumpMode = new EnumSyncValue<>(PumpMode.class, this::getPumpMode, this::setPumpMode); + pumpMode.updateCacheFromSource(true); + + syncManager.syncValue("manual_io", manualIOmode); + syncManager.syncValue("pump_mode", pumpMode); + syncManager.syncValue("throughput", throughput); + + var column = new Column().top(24).margin(7, 0) + .widthRel(1f).coverChildrenHeight(); + + if (createThroughputRow()) + column.child(new Row().coverChildrenHeight() + .marginBottom(2).widthRel(1f) + .child(new ButtonWidget<>() + .left(0).width(18) + .onMousePressed(mouseButton -> { + int val = throughput.getValue() - getIncrementValue(MouseData.create(mouseButton)); + throughput.setValue(val, true, true); + Interactable.playButtonClickSound(); + return true; + }) + .onUpdateListener(w -> w.overlay(createAdjustOverlay(false)))) + .child(new TextFieldWidget() + .left(18).right(18) + .setTextColor(Color.WHITE.darker(1)) + .setNumbers(1, maxFluidTransferRate) + .value(throughputString) + .background(GTGuiTextures.DISPLAY)) + .child(new ButtonWidget<>() + .right(0).width(18) + .onMousePressed(mouseButton -> { + int val = throughput.getValue() + getIncrementValue(MouseData.create(mouseButton)); + throughput.setValue(val, true, true); + Interactable.playButtonClickSound(); + return true; + }) + .onUpdateListener(w -> w.overlay(createAdjustOverlay(true))))); + + if (createFilterRow()) + column.child(getFluidFilterContainer() + .initUI(mainPanel, syncManager)); + + if (createManualIOModeRow()) + column.child(new EnumRowBuilder<>(ManualImportExportMode.class) + .value(manualIOmode) + .lang("cover.generic.manual_io") + .overlay(GTGuiTextures.MANUAL_IO_OVERLAY) + .build()); + + if (createPumpModeRow()) + column.child(new EnumRowBuilder<>(PumpMode.class) + .value(pumpMode) + .lang("cover.pump.mode") + .overlay(GTGuiTextures.CONVEYOR_MODE_OVERLAY) // todo pump mode overlays + .build()); + + return column; + } + + protected boolean createThroughputRow() { + return true; } - @SuppressWarnings("UnstableApiUsage") - @Override - public ModularUI createUI(EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new LabelWidget(10, 5, getUITitle(), GTValues.VN[tier])); - - primaryGroup.addWidget(new ImageWidget(44, 20, 62, 20, GuiTextures.DISPLAY)); - - primaryGroup.addWidget(new IncrementButtonWidget(136, 20, 30, 20, 1, 10, 100, 1000, this::adjustTransferRate) - .setDefaultTooltip() - .setShouldClientCallback(false)); - primaryGroup.addWidget(new IncrementButtonWidget(10, 20, 34, 20, -1, -10, -100, -1000, this::adjustTransferRate) - .setDefaultTooltip() - .setShouldClientCallback(false)); - - TextFieldWidget2 textField = new TextFieldWidget2(45, 26, 60, 20, () -> bucketMode == BucketMode.BUCKET ? - Integer.toString(transferRate / 1000) : Integer.toString(transferRate), val -> { - if (val != null && !val.isEmpty()) { - int amount = Integer.parseInt(val); - if (this.bucketMode == BucketMode.BUCKET) { - amount = IntMath.saturatedMultiply(amount, 1000); - } - setTransferRate(amount); - } - }) - .setCentered(true) - .setNumbersOnly(1, - bucketMode == BucketMode.BUCKET ? maxFluidTransferRate / 1000 : maxFluidTransferRate) - .setMaxLength(8); - primaryGroup.addWidget(textField); - - primaryGroup.addWidget(new CycleButtonWidget(106, 20, 30, 20, - BucketMode.class, this::getBucketMode, mode -> { - if (mode != bucketMode) { - setBucketMode(mode); - } - })); - - primaryGroup.addWidget(new CycleButtonWidget(10, 43, 75, 18, - PumpMode.class, this::getPumpMode, this::setPumpMode)); - - primaryGroup.addWidget(new CycleButtonWidget(7, 160, 116, 20, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); - - this.fluidFilter.initUI(88, primaryGroup::addWidget); - - ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 184 + 82) - .widget(primaryGroup) - .bindPlayerInventory(player.inventory, GuiTextures.SLOT, 7, 184); - return buildUI(builder, player); - } - - public static Function getTextFieldValidator(IntSupplier maxSupplier) { - int min = 1; - return val -> { - if (val.isEmpty()) { - return String.valueOf(min); - } - int max = maxSupplier.getAsInt(); - int num; - try { - num = Integer.parseInt(val); - } catch (NumberFormatException ignored) { - return String.valueOf(max); - } - if (num < min) { - return String.valueOf(min); - } - if (num > max) { - return String.valueOf(max); - } - return val; - }; + protected boolean createFilterRow() { + return true; + } + + protected boolean createManualIOModeRow() { + return true; + } + + protected boolean createPumpModeRow() { + return true; + } + + protected int getMaxTransferRate() { + return 1; } @Override @@ -274,13 +311,15 @@ public void readCustomData(int discriminator, @NotNull PacketBuffer buf) { @Override public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { super.writeInitialSyncData(packetBuffer); - packetBuffer.writeEnumValue(pumpMode); + packetBuffer.writeByte(pumpMode.ordinal()); + getFluidFilterContainer().writeInitialSyncData(packetBuffer); } @Override public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { super.readInitialSyncData(packetBuffer); - this.pumpMode = packetBuffer.readEnumValue(PumpMode.class); + this.pumpMode = PumpMode.VALUES[packetBuffer.readByte()]; + getFluidFilterContainer().readInitialSyncData(packetBuffer); } @Override @@ -295,7 +334,7 @@ public boolean canInteractWithOutputSide() { @Override public void onRemoval() { - dropInventoryContents(fluidFilter.getFilterInventory()); + dropInventoryContents(fluidFilterContainer); } @Override @@ -344,18 +383,21 @@ public void writeToNBT(@NotNull NBTTagCompound tagCompound) { tagCompound.setInteger("DistributionMode", distributionMode.ordinal()); tagCompound.setBoolean("WorkingAllowed", isWorkingAllowed); tagCompound.setInteger("ManualImportExportMode", manualImportExportMode.ordinal()); - tagCompound.setTag("Filter", fluidFilter.serializeNBT()); + tagCompound.setInteger("BucketMode", bucketMode.ordinal()); + tagCompound.setTag("Filter", fluidFilterContainer.serializeNBT()); } @Override public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.transferRate = tagCompound.getInteger("TransferRate"); - this.pumpMode = PumpMode.values()[tagCompound.getInteger("PumpMode")]; - this.distributionMode = DistributionMode.values()[tagCompound.getInteger("DistributionMode")]; + this.pumpMode = PumpMode.VALUES[tagCompound.getInteger("PumpMode")]; + this.distributionMode = DistributionMode.VALUES[tagCompound.getInteger("DistributionMode")]; this.isWorkingAllowed = tagCompound.getBoolean("WorkingAllowed"); - this.manualImportExportMode = ManualImportExportMode.values()[tagCompound.getInteger("ManualImportExportMode")]; - this.fluidFilter.deserializeNBT(tagCompound.getCompoundTag("Filter")); + this.manualImportExportMode = ManualImportExportMode.VALUES[tagCompound.getInteger("ManualImportExportMode")]; + this.bucketMode = BucketMode.VALUES[tagCompound.getInteger("BucketMode")]; + this.fluidFilterContainer.deserializeNBT(tagCompound.getCompoundTag("Filter")); + this.fluidFilterContainer.handleLegacyNBT(tagCompound); } @Override @@ -369,6 +411,7 @@ public enum PumpMode implements IStringSerializable, IIOMode { IMPORT("cover.pump.mode.import"), EXPORT("cover.pump.mode.export"); + public static final PumpMode[] VALUES = values(); public final String localeName; PumpMode(String localeName) { @@ -392,6 +435,7 @@ public enum BucketMode implements IStringSerializable { BUCKET("cover.bucket.mode.bucket"), MILLI_BUCKET("cover.bucket.mode.milli_bucket"); + public static final BucketMode[] VALUES = values(); public final String localeName; BucketMode(String localeName) { diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 902ffcd62f4..883fe18f9ec 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -1,27 +1,34 @@ package gregtech.common.covers; +import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.ModularUI.Builder; -import gregtech.api.gui.widgets.*; +import gregtech.api.mui.GTGuiTextures; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.SmartItemFilter; import gregtech.common.pipelike.itempipe.net.ItemNetHandler; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.MathHelper; import net.minecraftforge.items.IItemHandler; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.factory.SidedPosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; import java.util.Iterator; @@ -36,7 +43,7 @@ public CoverRoboticArm(@NotNull CoverDefinition definition, @NotNull CoverableVi @NotNull EnumFacing attachedSide, int tier, int itemsPerSecond) { super(definition, coverableView, attachedSide, tier, itemsPerSecond); this.transferMode = TransferMode.TRANSFER_ANY; - this.itemFilterContainer.setMaxStackSize(1); + this.itemFilterContainer.setMaxTransferSize(1); } @Override @@ -72,16 +79,17 @@ protected int doTransferExact(IItemHandler itemHandler, IItemHandler myItemHandl while (iterator.hasNext()) { TypeItemInfo sourceInfo = sourceItemAmount.get(iterator.next()); int itemAmount = sourceInfo.totalCount; - int itemToMoveAmount = itemFilterContainer.getSlotTransferLimit(sourceInfo.filterSlot); + int itemToMoveAmount = itemFilterContainer.getTransferLimit(sourceInfo.itemStack); - // if smart item filter - if (itemFilterContainer.getFilterWrapper().getItemFilter() instanceof SmartItemFilter) { - if (itemFilterContainer.getTransferStackSize() > 1 && itemToMoveAmount * 2 <= itemAmount) { + // if smart item filter and whitelist + if (itemFilterContainer.getFilter() instanceof SmartItemFilter && + !itemFilterContainer.isBlacklistFilter()) { + if (itemFilterContainer.getTransferSize() > 1 && itemToMoveAmount * 2 <= itemAmount) { // get the max we can extract from the item filter variable int maxMultiplier = Math.floorDiv(maxTransferAmount, itemToMoveAmount); // multiply up to the total count of all the items - itemToMoveAmount *= Math.min(itemFilterContainer.getTransferStackSize(), maxMultiplier); + itemToMoveAmount *= Math.min(itemFilterContainer.getTransferSize(), maxMultiplier); } } @@ -115,24 +123,24 @@ protected int doTransferExact(IItemHandler itemHandler, IItemHandler myItemHandl } protected int doKeepExact(IItemHandler itemHandler, IItemHandler myItemHandler, int maxTransferAmount) { - Map currentItemAmount = doCountDestinationInventoryItemsByMatchIndex(itemHandler, + Map currentItemAmount = doCountDestinationInventoryItemsByMatchIndex(itemHandler, myItemHandler); - Map sourceItemAmounts = doCountDestinationInventoryItemsByMatchIndex(myItemHandler, + Map sourceItemAmounts = doCountDestinationInventoryItemsByMatchIndex(myItemHandler, itemHandler); - Iterator iterator = sourceItemAmounts.keySet().iterator(); + Iterator iterator = sourceItemAmounts.keySet().iterator(); while (iterator.hasNext()) { - Object filterSlotIndex = iterator.next(); + int filterSlotIndex = iterator.next(); GroupItemInfo sourceInfo = sourceItemAmounts.get(filterSlotIndex); - int itemToKeepAmount = itemFilterContainer.getSlotTransferLimit(sourceInfo.filterSlot); + int itemToKeepAmount = itemFilterContainer.getTransferLimit(sourceInfo.filterSlot); // only run multiplier for smart item - if (itemFilterContainer.getFilterWrapper().getItemFilter() instanceof SmartItemFilter) { - if (itemFilterContainer.getTransferStackSize() > 1 && itemToKeepAmount * 2 <= sourceInfo.totalCount) { + if (itemFilterContainer.getFilter() instanceof SmartItemFilter) { + if (itemFilterContainer.getTransferSize() > 1 && itemToKeepAmount * 2 <= sourceInfo.totalCount) { // get the max we can keep from the item filter variable int maxMultiplier = Math.floorDiv(sourceInfo.totalCount, itemToKeepAmount); // multiply up to the total count of all the items - itemToKeepAmount *= Math.min(itemFilterContainer.getTransferStackSize(), maxMultiplier); + itemToKeepAmount *= Math.min(itemFilterContainer.getTransferSize(), maxMultiplier); } } @@ -163,9 +171,13 @@ public void clearBuffer() { } public void setTransferMode(TransferMode transferMode) { - this.transferMode = transferMode; - this.getCoverableView().markDirty(); - this.itemFilterContainer.setMaxStackSize(transferMode.maxStackSize); + if (this.transferMode != transferMode) { + this.transferMode = transferMode; + this.getCoverableView().markDirty(); + this.itemFilterContainer.setMaxTransferSize(transferMode.maxStackSize); + writeCustomData(GregtechDataCodes.UPDATE_TRANSFER_MODE, + buffer -> buffer.writeByte(this.transferMode.ordinal())); + } } public TransferMode getTransferMode() { @@ -180,44 +192,60 @@ private boolean shouldDisplayAmountSlider() { } @Override - protected String getUITitle() { - return "cover.robotic_arm.title"; + public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { + return super.buildUI(guiData, guiSyncManager).height(192 + 36 + 18 + 2); + } + + @Override + protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager guiSyncManager) { + EnumSyncValue transferMode = new EnumSyncValue<>(TransferMode.class, this::getTransferMode, + this::setTransferMode); + guiSyncManager.syncValue("transfer_mode", transferMode); + + var filterTransferSize = new StringSyncValue( + () -> String.valueOf(this.itemFilterContainer.getTransferSize()), + s -> this.itemFilterContainer.setTransferSize(Integer.parseInt(s))); + filterTransferSize.updateCacheFromSource(true); + + return super.createUI(mainPanel, guiSyncManager) + .child(new EnumRowBuilder<>(TransferMode.class) + .value(transferMode) + .lang("cover.generic.transfer_mode") + .overlay(GTGuiTextures.TRANSFER_MODE_OVERLAY) + .build()) + .child(new Row().right(0).coverChildrenHeight() + .child(new TextFieldWidget().widthRel(0.5f).right(0) + .setEnabledIf(w -> shouldDisplayAmountSlider()) + .setNumbers(0, Integer.MAX_VALUE) + .value(filterTransferSize) + .setTextColor(Color.WHITE.darker(1)))); + } + + @Override + protected int getMaxStackSize() { + return getTransferMode().maxStackSize; } @Override - protected ModularUI buildUI(Builder builder, EntityPlayer player) { - WidgetGroup primaryGroup = new WidgetGroup(); - primaryGroup.addWidget(new CycleButtonWidget(91, 45, 75, 20, - TransferMode.class, this::getTransferMode, this::setTransferMode) - .setTooltipHoverString("cover.robotic_arm.transfer_mode.description")); - - ServerWidgetGroup stackSizeGroup = new ServerWidgetGroup(this::shouldDisplayAmountSlider); - stackSizeGroup.addWidget(new ImageWidget(111, 70, 35, 20, GuiTextures.DISPLAY)); - - stackSizeGroup.addWidget( - new IncrementButtonWidget(146, 70, 20, 20, 1, 8, 64, 512, itemFilterContainer::adjustTransferStackSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - stackSizeGroup.addWidget(new IncrementButtonWidget(91, 70, 20, 20, -1, -8, -64, -512, - itemFilterContainer::adjustTransferStackSize) - .setDefaultTooltip() - .setTextScale(0.7f) - .setShouldClientCallback(false)); - - stackSizeGroup.addWidget(new TextFieldWidget2(113, 77, 31, 20, - () -> String.valueOf(itemFilterContainer.getTransferStackSize()), val -> { - if (val != null && !val.isEmpty()) - itemFilterContainer.setTransferStackSize( - MathHelper.clamp(Integer.parseInt(val), 1, transferMode.maxStackSize)); - }) - .setNumbersOnly(1, transferMode.maxStackSize) - .setMaxLength(4) - .setScale(0.9f)); - - primaryGroup.addWidget(stackSizeGroup); - - return super.buildUI(builder.widget(primaryGroup), player); + public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.writeInitialSyncData(packetBuffer); + packetBuffer.writeByte(this.transferMode.ordinal()); + } + + @Override + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + super.readInitialSyncData(packetBuffer); + this.transferMode = TransferMode.VALUES[packetBuffer.readByte()]; + this.itemFilterContainer.setMaxTransferSize(this.transferMode.maxStackSize); + } + + @Override + public void readCustomData(int discriminator, @NotNull PacketBuffer buf) { + super.readCustomData(discriminator, buf); + if (discriminator == GregtechDataCodes.UPDATE_TRANSFER_MODE) { + this.transferMode = TransferMode.VALUES[buf.readByte()]; + this.itemFilterContainer.setMaxTransferSize(this.transferMode.maxStackSize); + } } @Override @@ -228,7 +256,8 @@ public void writeToNBT(NBTTagCompound tagCompound) { @Override public void readFromNBT(NBTTagCompound tagCompound) { + this.transferMode = TransferMode.VALUES[tagCompound.getInteger("TransferMode")]; + this.itemFilterContainer.setMaxTransferSize(this.transferMode.maxStackSize); super.readFromNBT(tagCompound); - this.transferMode = TransferMode.values()[tagCompound.getInteger("TransferMode")]; } } diff --git a/src/main/java/gregtech/common/covers/DistributionMode.java b/src/main/java/gregtech/common/covers/DistributionMode.java index 24268bdc6a0..c704d045b18 100644 --- a/src/main/java/gregtech/common/covers/DistributionMode.java +++ b/src/main/java/gregtech/common/covers/DistributionMode.java @@ -10,6 +10,7 @@ public enum DistributionMode implements IStringSerializable { ROUND_ROBIN_PRIO("cover.conveyor.distribution.round_robin"), INSERT_FIRST("cover.conveyor.distribution.first_insert"); + public static final DistributionMode[] VALUES = values(); public final String localeName; DistributionMode(String localeName) { diff --git a/src/main/java/gregtech/common/covers/FluidFilterMode.java b/src/main/java/gregtech/common/covers/FluidFilterMode.java index ee372ff8b09..e26c6192e8b 100644 --- a/src/main/java/gregtech/common/covers/FluidFilterMode.java +++ b/src/main/java/gregtech/common/covers/FluidFilterMode.java @@ -1,11 +1,14 @@ package gregtech.common.covers; -public enum FluidFilterMode implements IFilterMode { +import net.minecraft.util.IStringSerializable; + +public enum FluidFilterMode implements IStringSerializable { FILTER_FILL("cover.fluid_filter.mode.filter_fill"), FILTER_DRAIN("cover.fluid_filter.mode.filter_drain"), FILTER_BOTH("cover.fluid_filter.mode.filter_both"); + public static final FluidFilterMode[] VALUES = values(); public final String localeName; FluidFilterMode(String localeName) { diff --git a/src/main/java/gregtech/common/covers/IFilterMode.java b/src/main/java/gregtech/common/covers/IFilterMode.java deleted file mode 100644 index ecc0fde802f..00000000000 --- a/src/main/java/gregtech/common/covers/IFilterMode.java +++ /dev/null @@ -1,6 +0,0 @@ -package gregtech.common.covers; - -public interface IFilterMode { - - String getName(); -} diff --git a/src/main/java/gregtech/common/covers/ItemFilterMode.java b/src/main/java/gregtech/common/covers/ItemFilterMode.java index 2a871e2984e..6d612915161 100644 --- a/src/main/java/gregtech/common/covers/ItemFilterMode.java +++ b/src/main/java/gregtech/common/covers/ItemFilterMode.java @@ -1,11 +1,14 @@ package gregtech.common.covers; -public enum ItemFilterMode implements IFilterMode { +import net.minecraft.util.IStringSerializable; + +public enum ItemFilterMode implements IStringSerializable { FILTER_INSERT("cover.filter.mode.filter_insert"), FILTER_EXTRACT("cover.filter.mode.filter_extract"), FILTER_BOTH("cover.filter.mode.filter_both"); + public static final ItemFilterMode[] VALUES = values(); public final String localeName; ItemFilterMode(String localeName) { diff --git a/src/main/java/gregtech/common/covers/ManualImportExportMode.java b/src/main/java/gregtech/common/covers/ManualImportExportMode.java index d044322425c..df3942d7163 100644 --- a/src/main/java/gregtech/common/covers/ManualImportExportMode.java +++ b/src/main/java/gregtech/common/covers/ManualImportExportMode.java @@ -10,6 +10,7 @@ public enum ManualImportExportMode implements IStringSerializable { FILTERED("cover.universal.manual_import_export.mode.filtered"), UNFILTERED("cover.universal.manual_import_export.mode.unfiltered"); + public static final ManualImportExportMode[] VALUES = values(); public final String localeName; ManualImportExportMode(String localeName) { diff --git a/src/main/java/gregtech/common/covers/TransferMode.java b/src/main/java/gregtech/common/covers/TransferMode.java index ebf708dfdf4..2f278c88ce4 100644 --- a/src/main/java/gregtech/common/covers/TransferMode.java +++ b/src/main/java/gregtech/common/covers/TransferMode.java @@ -8,8 +8,9 @@ public enum TransferMode implements IStringSerializable { TRANSFER_ANY("cover.robotic_arm.transfer_mode.transfer_any", 1), TRANSFER_EXACT("cover.robotic_arm.transfer_mode.transfer_exact", 1024), - KEEP_EXACT("cover.robotic_arm.transfer_mode.keep_exact", 1024); + KEEP_EXACT("cover.robotic_arm.transfer_mode.keep_exact", Integer.MAX_VALUE); + public static final TransferMode[] VALUES = values(); public final String localeName; public final int maxStackSize; diff --git a/src/main/java/gregtech/common/covers/VoidingMode.java b/src/main/java/gregtech/common/covers/VoidingMode.java index 48aa9d0b8de..b7e85666f65 100644 --- a/src/main/java/gregtech/common/covers/VoidingMode.java +++ b/src/main/java/gregtech/common/covers/VoidingMode.java @@ -7,8 +7,9 @@ public enum VoidingMode implements IStringSerializable { VOID_ANY("cover.voiding.voiding_mode.void_any", 1), - VOID_OVERFLOW("cover.voiding.voiding_mode.void_overflow", 1024); + VOID_OVERFLOW("cover.voiding.voiding_mode.void_overflow", Integer.MAX_VALUE); + public static final VoidingMode[] VALUES = values(); public final String localeName; public final int maxStackSize; diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java index 32239be9036..56d7eb246c9 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java @@ -92,7 +92,7 @@ public ModularUI createUI(EntityPlayer player) { // "cover.generic.advanced_detector.invert_label")); group.addWidget( new CycleButtonWidget(10, 3 * (SIZE + PADDING), 4 * SIZE, SIZE, this::isInverted, this::setInverted, - "cover.machine_controller.normal", "cover.machine_controller.inverted") + "cover.advanced_energy_detector.normal", "cover.advanced_energy_detector.inverted") .setTooltipHoverString("cover.generic.advanced_detector.invert_tooltip")); group.addWidget( new CycleButtonWidget(94, 3 * (SIZE + PADDING), 4 * SIZE, SIZE, this::isLatched, this::setLatched, @@ -145,7 +145,7 @@ public void update() { for (IFluidTankProperties properties : tankProperties) { FluidStack contents = properties.getContents(); - if (contents != null && fluidFilter.testFluidStack(contents)) + if (contents != null && fluidFilter.test(contents)) storedFluid += contents.amount; } diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java index 7d992674a93..e2475756fd5 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java @@ -78,7 +78,7 @@ public ModularUI createUI(EntityPlayer player) { // "cover.generic.advanced_detector.invert_label")); group.addWidget( new CycleButtonWidget(10, 3 * (SIZE + PADDING), 4 * SIZE, SIZE, this::isInverted, this::setInverted, - "cover.machine_controller.normal", "cover.machine_controller.inverted") + "cover.advanced_energy_detector.normal", "cover.advanced_energy_detector.inverted") .setTooltipHoverString("cover.generic.advanced_detector.invert_tooltip")); // group.addWidget(new LabelWidget(10, 5 + 4 * (SIZE + PADDING), // "cover.generic.advanced_detector.latch_label")); @@ -151,7 +151,7 @@ public void update() { int storedItems = 0; for (int i = 0; i < itemHandler.getSlots(); i++) { - if (itemFilter.testItemStack(itemHandler.getStackInSlot(i))) + if (itemFilter.test(itemHandler.getStackInSlot(i))) storedItems += itemHandler.getStackInSlot(i).getCount(); } diff --git a/src/main/java/gregtech/common/covers/filter/BaseFilter.java b/src/main/java/gregtech/common/covers/filter/BaseFilter.java new file mode 100644 index 00000000000..ae72a78626d --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/BaseFilter.java @@ -0,0 +1,183 @@ +package gregtech.common.covers.filter; + +import gregtech.api.items.metaitem.MetaItem; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; +import gregtech.api.util.IDirtyNotifiable; +import gregtech.common.covers.filter.readers.BaseFilterReader; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fluids.FluidStack; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widget.Widget; +import com.cleanroommc.modularui.widgets.CycleButtonWidget; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class BaseFilter implements IFilter { + + public static final BaseFilter ERROR_FILTER = new BaseFilter() { + + private final BaseFilterReader filterReader = new BaseFilterReader(ItemStack.EMPTY, 0); + + @Override + public BaseFilterReader getFilterReader() { + return this.filterReader; + } + + @Override + public @NotNull ModularPanel createPopupPanel(GuiSyncManager syncManager) { + return GTGuis.createPopupPanel("error", 100, 100) + .child(createWidgets(syncManager)); + } + + @Override + public @NotNull ModularPanel createPanel(GuiSyncManager syncManager) { + return GTGuis.createPanel("error", 100, 100) + .child(createWidgets(syncManager)); + } + + @Override + public @NotNull Widget createWidgets(GuiSyncManager syncManager) { + return IKey.lang("INVALID FILTER").alignment(Alignment.Center).asWidget(); + } + + @Override + public FilterType getType() { + return FilterType.ITEM; + } + }; + protected IDirtyNotifiable dirtyNotifiable; + + public abstract BaseFilterReader getFilterReader(); + + public final ItemStack getContainerStack() { + return this.getFilterReader().getContainer(); + } + + public static @Nullable BaseFilter getFilterFromStack(ItemStack stack) { + if (stack.getItem() instanceof MetaItemmetaItem) { + var metaValueItem = metaItem.getItem(stack); + var factory = metaValueItem == null ? null : metaValueItem.getFilterFactory(); + if (factory != null) + return factory.create(stack); + } + return null; + } + + public final void setBlacklistFilter(boolean blacklistFilter) { + this.getFilterReader().setBlacklistFilter(blacklistFilter); + markDirty(); + } + + @Override + public final MatchResult match(Object toMatch) { + if (toMatch instanceof ItemStack stack) { + return matchItem(stack); + } else if (toMatch instanceof FluidStack stack) { + return matchFluid(stack); + } + return MatchResult.NONE; + } + + public MatchResult matchFluid(FluidStack fluidStack) { + return MatchResult.NONE; + } + + public MatchResult matchItem(ItemStack itemStack) { + return MatchResult.NONE; + } + + @Override + public final boolean test(Object toTest) { + boolean b = false; + if (toTest instanceof ItemStack stack) { + b = testItem(stack); + } else if (toTest instanceof FluidStack stack) { + b = testFluid(stack); + } + return b != isBlacklistFilter(); + } + + public boolean testFluid(FluidStack toTest) { + return false; + } + + public boolean testItem(ItemStack toTest) { + return false; + } + + @Override + public final int getTransferLimit(Object o, int transferSize) { + if (o instanceof ItemStack stack) { + return getTransferLimit(stack, transferSize); + } else if (o instanceof FluidStack stack) { + return getTransferLimit(stack, transferSize); + } + return 0; + } + + public int getTransferLimit(FluidStack stack, int transferSize) { + return 0; + } + + public int getTransferLimit(ItemStack stack, int transferSize) { + return 0; + } + + public final boolean isBlacklistFilter() { + return getFilterReader().isBlacklistFilter(); + } + + public IWidget createBlacklistUI() { + return new ParentWidget<>().coverChildren() + .child(new CycleButtonWidget() + .value(new BooleanSyncValue( + this::isBlacklistFilter, + this::setBlacklistFilter)) + .textureGetter(state -> GTGuiTextures.BUTTON_BLACKLIST[state]) + .addTooltip(0, IKey.lang("cover.filter.blacklist.disabled")) + .addTooltip(1, IKey.lang("cover.filter.blacklist.enabled"))); + } + + public final int getMaxTransferSize() { + return this.getFilterReader().getMaxTransferRate(); + } + + public final void setMaxTransferSize(int maxStackSize) { + this.getFilterReader().setMaxTransferRate(maxStackSize); + } + + public boolean showGlobalTransferLimitSlider() { + return isBlacklistFilter(); + } + + public final void setDirtyNotifiable(IDirtyNotifiable dirtyNotifiable) { + this.dirtyNotifiable = dirtyNotifiable; + this.getFilterReader().setDirtyNotifiable(dirtyNotifiable); + } + + public final void markDirty() { + if (dirtyNotifiable != null) { + dirtyNotifiable.markAsDirty(); + } + } + + public void readFromNBT(NBTTagCompound tag) { + this.getFilterReader().deserializeNBT(tag); + markDirty(); + } + + public void writeInitialSyncData(PacketBuffer packetBuffer) {} + + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) {} +} diff --git a/src/main/java/gregtech/common/covers/filter/BaseFilterContainer.java b/src/main/java/gregtech/common/covers/filter/BaseFilterContainer.java new file mode 100644 index 00000000000..489fd70659d --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/BaseFilterContainer.java @@ -0,0 +1,273 @@ +package gregtech.common.covers.filter; + +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.util.IDirtyNotifiable; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.items.ItemStackHandler; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.api.widget.Interactable; +import com.cleanroommc.modularui.drawable.GuiTextures; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.PanelSyncHandler; +import com.cleanroommc.modularui.value.sync.SyncHandlers; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.ItemSlot; +import com.cleanroommc.modularui.widgets.layout.Row; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; + +public abstract class BaseFilterContainer extends ItemStackHandler { + + private int maxTransferSize = 1; + private int transferSize; + private @Nullable BaseFilter currentFilter; + private @Nullable Runnable onFilterInstanceChange; + private final IDirtyNotifiable dirtyNotifiable; + + protected BaseFilterContainer(IDirtyNotifiable dirtyNotifiable) { + super(); + this.dirtyNotifiable = dirtyNotifiable; + } + + public boolean test(Object toTest) { + return !hasFilter() || getFilter().test(toTest); + } + + public MatchResult match(Object toMatch) { + if (!hasFilter()) + return MatchResult.create(true, toMatch, -1); + + return getFilter().match(toMatch); + } + + public int getTransferLimit(Object stack) { + if (!hasFilter() || isBlacklistFilter()) { + return getTransferSize(); + } + return getFilter().getTransferLimit(stack, getTransferSize()); + } + + @Override + public int getSlotLimit(int slot) { + return 1; + } + + public void onFilterInstanceChange() { + dirtyNotifiable.markAsDirty(); + if (onFilterInstanceChange != null) { + onFilterInstanceChange.run(); + } + } + + public void setOnFilterInstanceChange(@Nullable Runnable onFilterInstanceChange) { + this.onFilterInstanceChange = onFilterInstanceChange; + } + + public final @NotNull ItemStack getFilterStack() { + return this.getStackInSlot(0); + } + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + if (ItemStack.areItemStacksEqual(stack, getFilterStack())) + return; + + if (stack.isEmpty()) { + setFilter(null); + } else if (isItemValid(stack)) { + setFilter(BaseFilter.getFilterFromStack(stack)); + } + + super.setStackInSlot(slot, stack); + } + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + return isItemValid(stack); + } + + protected abstract boolean isItemValid(ItemStack stack); + + protected abstract String getFilterName(); + + @Override + public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + if (!isItemValid(stack)) return stack; + var remainder = super.insertItem(slot, stack, simulate); + if (!simulate) setFilter(BaseFilter.getFilterFromStack(stack)); + return remainder; + } + + @Override + public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { + var extracted = super.extractItem(slot, amount, simulate); + if (!extracted.isEmpty()) { + setFilter(null); + } + return extracted; + } + + public final void setFilterStack(ItemStack stack) { + setStackInSlot(0, stack); + } + + public int getMaxTransferSize() { + return !showGlobalTransferLimitSlider() && hasFilter() ? currentFilter.getMaxTransferSize() : + this.maxTransferSize; + } + + public void setMaxTransferSize(int maxTransferSize) { + this.maxTransferSize = MathHelper.clamp(maxTransferSize, 1, Integer.MAX_VALUE); + this.transferSize = MathHelper.clamp(this.transferSize, 1, this.maxTransferSize); + if (hasFilter()) currentFilter.setMaxTransferSize(this.maxTransferSize); + } + + public final boolean hasFilter() { + return currentFilter != null; + } + + public final @Nullable BaseFilter getFilter() { + return currentFilter; + } + + public final void setFilter(@Nullable BaseFilter newFilter) { + this.currentFilter = newFilter; + if (hasFilter()) { + this.currentFilter.setDirtyNotifiable(this.dirtyNotifiable); + this.currentFilter.setMaxTransferSize(this.maxTransferSize); + } + if (onFilterInstanceChange != null) { + this.onFilterInstanceChange.run(); + } + } + + public boolean showGlobalTransferLimitSlider() { + return this.maxTransferSize > 0 && (!hasFilter() || getFilter().showGlobalTransferLimitSlider()); + } + + public void setBlacklistFilter(boolean blacklistFilter) { + if (hasFilter()) getFilter().setBlacklistFilter(blacklistFilter); + onFilterInstanceChange(); + } + + public final boolean isBlacklistFilter() { + return hasFilter() && getFilter().isBlacklistFilter(); + } + + public int getTransferSize() { + if (!showGlobalTransferLimitSlider()) { + return getMaxTransferSize(); + } + return this.transferSize; + } + + public int getTransferLimit(int slotIndex) { + if (isBlacklistFilter() || !hasFilter()) { + return getTransferSize(); + } + return this.currentFilter.getTransferLimit(slotIndex, getTransferSize()); + } + + public void setTransferSize(int transferSize) { + this.transferSize = MathHelper.clamp(transferSize, 1, getMaxTransferSize()); + onFilterInstanceChange(); + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tagCompound = new NBTTagCompound(); + tagCompound.setTag("FilterInventory", super.serializeNBT()); + // tagCompound.setInteger("MaxStackSize", getMaxTransferSize()); + tagCompound.setInteger("TransferStackSize", getTransferSize()); + return tagCompound; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt.getCompoundTag("FilterInventory")); + setFilter(BaseFilter.getFilterFromStack(getFilterStack())); + if (nbt.hasKey("TransferStackSize")) + this.transferSize = nbt.getInteger("TransferStackSize"); + } + + public void handleLegacyNBT(NBTTagCompound nbt) { + if (hasFilter()) { + getFilter().getFilterReader().handleLegacyNBT(nbt); + } + } + + /** Uses Cleanroom MUI */ + public IWidget initUI(ModularPanel main, GuiSyncManager manager) { + var panel = new PanelSyncHandler(main) { + + // the panel can't be opened if there's no filter, so `getFilter()` should not be null + @Override + public ModularPanel createUI(ModularPanel mainPanel, GuiSyncManager syncManager) { + var filter = hasFilter() ? getFilter() : BaseFilter.ERROR_FILTER; + filter.setMaxTransferSize(getMaxTransferSize()); + return filter.createPopupPanel(syncManager); + } + }; + + manager.syncValue("filter_panel", panel); + var filterButton = new ButtonWidget<>(); + filterButton.setEnabled(hasFilter()); + + return new Row().coverChildrenHeight() + .marginBottom(2).widthRel(1f) + .child(new ItemSlot() + .slot(SyncHandlers.itemSlot(this, 0) + .filter(this::isItemValid) + .singletonSlotGroup(101) + .changeListener((newItem, onlyAmountChanged, client, init) -> { + if (!isItemValid(newItem) && panel.isPanelOpen()) { + panel.closePanel(); + } + })) + .size(18).marginRight(2) + .background(GTGuiTextures.SLOT, GTGuiTextures.FILTER_SLOT_OVERLAY.asIcon().size(16))) + .child(filterButton + .background(GTGuiTextures.MC_BUTTON, GTGuiTextures.FILTER_SETTINGS_OVERLAY.asIcon().size(16)) + .hoverBackground(GuiTextures.MC_BUTTON_HOVERED, + GTGuiTextures.FILTER_SETTINGS_OVERLAY.asIcon().size(16)) + .setEnabledIf(w -> hasFilter()) + .onMousePressed(i -> { + if (!panel.isPanelOpen()) { + panel.openPanel(); + } else { + panel.closePanel(); + } + Interactable.playButtonClickSound(); + return true; + })) + .child(IKey.dynamic(this::getFilterName) + .alignment(Alignment.CenterRight).asWidget() + .left(36).right(0).height(18)); + } + + public void writeInitialSyncData(PacketBuffer packetBuffer) { + packetBuffer.writeItemStack(this.getFilterStack()); + packetBuffer.writeInt(this.maxTransferSize); + packetBuffer.writeInt(this.transferSize); + } + + public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { + var stack = ItemStack.EMPTY; + try { + stack = packetBuffer.readItemStack(); + } catch (IOException ignore) {} + this.setFilterStack(stack); + this.setMaxTransferSize(packetBuffer.readInt()); + this.setTransferSize(packetBuffer.readInt()); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/FilterTypeRegistry.java b/src/main/java/gregtech/common/covers/filter/FilterTypeRegistry.java deleted file mode 100644 index 633242b05d2..00000000000 --- a/src/main/java/gregtech/common/covers/filter/FilterTypeRegistry.java +++ /dev/null @@ -1,103 +0,0 @@ -package gregtech.common.covers.filter; - -import gregtech.api.unification.stack.ItemAndMetadata; -import gregtech.api.util.GTLog; -import gregtech.common.items.MetaItems; - -import net.minecraft.item.ItemStack; - -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; - -import java.util.Map; - -public class FilterTypeRegistry { - - private static final Map itemFilterIdByStack = new Object2IntOpenHashMap<>(); - private static final Map fluidFilterIdByStack = new Object2IntOpenHashMap<>(); - private static final BiMap> itemFilterById = HashBiMap.create(); - private static final BiMap> fluidFilterById = HashBiMap.create(); - - public static void init() { - registerFluidFilter(1, SimpleFluidFilter.class, MetaItems.FLUID_FILTER.getStackForm()); - registerItemFilter(2, SimpleItemFilter.class, MetaItems.ITEM_FILTER.getStackForm()); - registerItemFilter(3, OreDictionaryItemFilter.class, MetaItems.ORE_DICTIONARY_FILTER.getStackForm()); - registerItemFilter(4, SmartItemFilter.class, MetaItems.SMART_FILTER.getStackForm()); - } - - public static void registerFluidFilter(int id, Class fluidFilterClass, ItemStack itemStack) { - if (fluidFilterById.containsKey(id)) { - throw new IllegalArgumentException("Id is already occupied: " + id); - } - fluidFilterIdByStack.put(new ItemAndMetadata(itemStack), id); - fluidFilterById.put(id, fluidFilterClass); - } - - public static void registerItemFilter(int id, Class itemFilterClass, ItemStack itemStack) { - if (itemFilterById.containsKey(id)) { - throw new IllegalArgumentException("Id is already occupied: " + id); - } - itemFilterIdByStack.put(new ItemAndMetadata(itemStack), id); - itemFilterById.put(id, itemFilterClass); - } - - public static int getIdForItemFilter(ItemFilter itemFilter) { - Integer filterId = itemFilterById.inverse().get(itemFilter.getClass()); - if (filterId == null) { - throw new IllegalArgumentException("Unknown filter type " + itemFilter.getClass()); - } - return filterId; - } - - public static int getIdForFluidFilter(FluidFilter fluidFilter) { - Integer filterId = fluidFilterById.inverse().get(fluidFilter.getClass()); - if (filterId == null) { - throw new IllegalArgumentException("Unknown filter type " + fluidFilter.getClass()); - } - return filterId; - } - - public static ItemFilter createItemFilterById(int filterId) { - Class filterClass = itemFilterById.get(filterId); - if (filterClass == null) { - throw new IllegalArgumentException("Unknown filter id: " + filterId); - } - return createNewFilterInstance(filterClass); - } - - public static FluidFilter createFluidFilterById(int filterId) { - Class filterClass = fluidFilterById.get(filterId); - if (filterClass == null) { - throw new IllegalArgumentException("Unknown filter id: " + filterId); - } - return createNewFilterInstance(filterClass); - } - - public static ItemFilter getItemFilterForStack(ItemStack itemStack) { - Integer filterId = itemFilterIdByStack.get(new ItemAndMetadata(itemStack)); - if (filterId == null) { - return null; - } - Class filterClass = itemFilterById.get(filterId); - return createNewFilterInstance(filterClass); - } - - public static FluidFilter getFluidFilterForStack(ItemStack itemStack) { - Integer filterId = fluidFilterIdByStack.get(new ItemAndMetadata(itemStack)); - if (filterId == null) { - return null; - } - Class filterClass = fluidFilterById.get(filterId); - return createNewFilterInstance(filterClass); - } - - private static T createNewFilterInstance(Class filterClass) { - try { - return filterClass.newInstance(); - } catch (ReflectiveOperationException exception) { - GTLog.logger.error("Failed to create filter instance for class {}", filterClass, exception); - return null; - } - } -} diff --git a/src/main/java/gregtech/common/covers/filter/FluidFilter.java b/src/main/java/gregtech/common/covers/filter/FluidFilter.java deleted file mode 100644 index 6d6dc23254b..00000000000 --- a/src/main/java/gregtech/common/covers/filter/FluidFilter.java +++ /dev/null @@ -1,41 +0,0 @@ -package gregtech.common.covers.filter; - -import gregtech.api.gui.Widget; -import gregtech.api.util.IDirtyNotifiable; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.fluids.FluidStack; - -import java.util.function.Consumer; - -public abstract class FluidFilter { - - private IDirtyNotifiable dirtyNotifiable; - boolean showTip; - - public abstract boolean testFluid(FluidStack fluidStack); - - public abstract int getFluidTransferLimit(FluidStack fluidStack); - - public abstract int getMaxOccupiedHeight(); - - public abstract void initUI(Consumer widgetGroup); - - public abstract void writeToNBT(NBTTagCompound tagCompound); - - public abstract void readFromNBT(NBTTagCompound tagCompound); - - public final void setDirtyNotifiable(IDirtyNotifiable dirtyNotifiable) { - this.dirtyNotifiable = dirtyNotifiable; - } - - public abstract void configureFilterTanks(int amount); - - public abstract void setMaxConfigurableFluidSize(int maxStackSize); - - public final void markDirty() { - if (dirtyNotifiable != null) { - dirtyNotifiable.markAsDirty(); - } - } -} diff --git a/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java b/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java index 41beb67b6d6..a3793c0ffed 100644 --- a/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java +++ b/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java @@ -1,128 +1,64 @@ package gregtech.common.covers.filter; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.SlotWidget; import gregtech.api.util.IDirtyNotifiable; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.items.ItemStackHandler; -import org.jetbrains.annotations.NotNull; +import com.cleanroommc.modularui.api.drawable.IKey; +import org.jetbrains.annotations.ApiStatus; +import java.util.function.BooleanSupplier; import java.util.function.Consumer; -import java.util.function.Supplier; -public class FluidFilterContainer implements INBTSerializable { - - private final ItemStackHandler filterInventory; - private final FluidFilterWrapper filterWrapper; - - public FluidFilterContainer(IDirtyNotifiable dirtyNotifiable, int capacity) { - this.filterWrapper = new FluidFilterWrapper(dirtyNotifiable, capacity); - this.filterInventory = new ItemStackHandler(1) { - - @Override - public boolean isItemValid(int slot, @NotNull ItemStack stack) { - return FilterTypeRegistry.getFluidFilterForStack(stack) != null; - } - - @Override - public int getSlotLimit(int slot) { - return 1; - } - - @Override - protected void onLoad() { - onFilterSlotChange(false); - } - - @Override - protected void onContentsChanged(int slot) { - onFilterSlotChange(true); - } - }; - } - - public FluidFilterContainer(IDirtyNotifiable dirtyNotifiable, Supplier showTip, int maxSize) { - this(dirtyNotifiable, maxSize); - filterWrapper.setTipSupplier(showTip); - } - - public FluidFilterContainer(IDirtyNotifiable dirtyNotifiable, Supplier showTip) { - this(dirtyNotifiable, 1000); - filterWrapper.setTipSupplier(showTip); - } +public class FluidFilterContainer extends BaseFilterContainer { public FluidFilterContainer(IDirtyNotifiable dirtyNotifiable) { - this(dirtyNotifiable, 1000); - filterWrapper.setTipSupplier(() -> false); - } - - public ItemStackHandler getFilterInventory() { - return filterInventory; - } - - public FluidFilterWrapper getFilterWrapper() { - return filterWrapper; - } - - public void initUI(int y, Consumer widgetGroup) { - widgetGroup.accept(new LabelWidget(10, y, "cover.pump.fluid_filter.title")); - widgetGroup.accept(new SlotWidget(filterInventory, 0, 10, y + 15) - .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.FILTER_SLOT_OVERLAY)); - - this.filterWrapper.initUI(y + 15, widgetGroup); - this.filterWrapper.blacklistUI(y + 15, widgetGroup, () -> true); + super(dirtyNotifiable); } - protected void onFilterSlotChange(boolean notify) { - ItemStack filterStack = filterInventory.getStackInSlot(0); - FluidFilter newFluidFilter = FilterTypeRegistry.getFluidFilterForStack(filterStack); - FluidFilter currentFluidFilter = filterWrapper.getFluidFilter(); - if (newFluidFilter == null) { - if (currentFluidFilter != null) { - filterWrapper.setFluidFilter(null); - if (notify) filterWrapper.onFilterInstanceChange(); - } - } else if (currentFluidFilter == null || - newFluidFilter.getClass() != currentFluidFilter.getClass()) { - filterWrapper.setFluidFilter(newFluidFilter); - if (notify) filterWrapper.onFilterInstanceChange(); - } + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void initUI(int y, Consumer widgetGroup) { + widgetGroup.accept(new gregtech.api.gui.widgets.LabelWidget(10, y, "cover.pump.fluid_filter.title")); + widgetGroup.accept(new gregtech.api.gui.widgets.SlotWidget(this, 0, 10, y + 15) + .setBackgroundTexture(gregtech.api.gui.GuiTextures.SLOT, + gregtech.api.gui.GuiTextures.FILTER_SLOT_OVERLAY)); + + this.initFilterUI(y + 15, widgetGroup); + this.blacklistUI(y + 15, widgetGroup, () -> true); } - public boolean testFluidStack(FluidStack fluidStack) { - return filterWrapper.testFluidStack(fluidStack); + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void initFilterUI(int y, Consumer widgetGroup) { + widgetGroup.accept(new WidgetGroupFluidFilter(y, this::getFilter, this::showGlobalTransferLimitSlider)); } - public boolean testFluidStack(FluidStack fluidStack, Boolean whitelist) { - return filterWrapper.testFluidStack(fluidStack, whitelist); + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { + gregtech.api.gui.widgets.ServerWidgetGroup blacklistButton = new gregtech.api.gui.widgets.ServerWidgetGroup( + this::hasFilter); + blacklistButton.addWidget(new gregtech.api.gui.widgets.ToggleButtonWidget(144, y, 18, 18, + gregtech.api.gui.GuiTextures.BUTTON_BLACKLIST, + this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) + .setTooltipText("cover.filter.blacklist")); + widgetGroup.accept(blacklistButton); } @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tagCompound = new NBTTagCompound(); - tagCompound.setTag("FilterInventory", filterInventory.serializeNBT()); - tagCompound.setBoolean("IsBlacklist", filterWrapper.isBlacklistFilter()); - if (filterWrapper.getFluidFilter() != null) { - NBTTagCompound filterInventory = new NBTTagCompound(); - filterWrapper.getFluidFilter().writeToNBT(filterInventory); - tagCompound.setTag("Filter", filterInventory); - } - return tagCompound; + protected boolean isItemValid(ItemStack stack) { + var filter = BaseFilter.getFilterFromStack(stack); + return filter != null && filter.getType() == IFilter.FilterType.FLUID; } @Override - public void deserializeNBT(NBTTagCompound tagCompound) { - this.filterInventory.deserializeNBT(tagCompound.getCompoundTag("FilterInventory")); - this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); - if (filterWrapper.getFluidFilter() != null) { - this.filterWrapper.getFluidFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); - } + protected String getFilterName() { + return hasFilter() ? + getFilterStack().getDisplayName() : + IKey.lang("metaitem.fluid_filter.name").get(); } } diff --git a/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java b/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java deleted file mode 100644 index 2ef1f76a32e..00000000000 --- a/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java +++ /dev/null @@ -1,98 +0,0 @@ -package gregtech.common.covers.filter; - -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.ServerWidgetGroup; -import gregtech.api.gui.widgets.ToggleButtonWidget; -import gregtech.api.util.IDirtyNotifiable; - -import net.minecraftforge.fluids.FluidStack; - -import java.util.function.BooleanSupplier; -import java.util.function.Consumer; -import java.util.function.Supplier; - -public class FluidFilterWrapper { - - private final IDirtyNotifiable dirtyNotifiable; - private boolean isBlacklistFilter = false; - private FluidFilter currentFluidFilter; - private Supplier showTipSupplier; - private int maxSize = 1000; - - public FluidFilterWrapper(IDirtyNotifiable dirtyNotifiable, int maxSize) { - this.dirtyNotifiable = dirtyNotifiable; - this.maxSize = maxSize; - } - - public FluidFilterWrapper(IDirtyNotifiable dirtyNotifiable) { - this.dirtyNotifiable = dirtyNotifiable; - } - - public void initUI(int y, Consumer widgetGroup) { - widgetGroup.accept(new WidgetGroupFluidFilter(y, this::getFluidFilter, shouldShowTip())); - } - - public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { - ServerWidgetGroup blacklistButton = new ServerWidgetGroup(() -> getFluidFilter() != null); - blacklistButton.addWidget(new ToggleButtonWidget(144, y, 18, 18, GuiTextures.BUTTON_BLACKLIST, - this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) - .setTooltipText("cover.filter.blacklist")); - widgetGroup.accept(blacklistButton); - } - - public void setFluidFilter(FluidFilter fluidFilter) { - this.currentFluidFilter = fluidFilter; - if (currentFluidFilter != null) { - currentFluidFilter.setDirtyNotifiable(dirtyNotifiable); - currentFluidFilter.setMaxConfigurableFluidSize(maxSize); - } - } - - private Supplier shouldShowTip() { - return showTipSupplier; - } - - protected void setTipSupplier(Supplier supplier) { - this.showTipSupplier = supplier; - } - - public FluidFilter getFluidFilter() { - return currentFluidFilter; - } - - public void onFilterInstanceChange() { - dirtyNotifiable.markAsDirty(); - } - - public void setBlacklistFilter(boolean blacklistFilter) { - isBlacklistFilter = blacklistFilter; - dirtyNotifiable.markAsDirty(); - } - - public boolean isBlacklistFilter() { - return isBlacklistFilter; - } - - public boolean testFluidStack(FluidStack fluidStack, boolean whitelist) { - boolean result = true; - if (currentFluidFilter != null) { - result = currentFluidFilter.testFluid(fluidStack); - } - if (!whitelist) { - result = !result; - } - return result; - } - - public boolean testFluidStack(FluidStack fluidStack) { - boolean result = true; - if (currentFluidFilter != null) { - result = currentFluidFilter.testFluid(fluidStack); - } - if (isBlacklistFilter) { - result = !result; - } - return result; - } -} diff --git a/src/main/java/gregtech/common/covers/filter/IFilter.java b/src/main/java/gregtech/common/covers/filter/IFilter.java new file mode 100644 index 00000000000..06345143982 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/IFilter.java @@ -0,0 +1,77 @@ +package gregtech.common.covers.filter; + +import gregtech.api.items.metaitem.stats.IItemComponent; +import gregtech.api.util.IDirtyNotifiable; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.Widget; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Consumer; + +public interface IFilter { + + @Deprecated + default void initUI(Consumer widgetGroup) {} + + /** Uses Cleanroom MUI */ + @NotNull + ModularPanel createPopupPanel(GuiSyncManager syncManager); + + /** Uses Cleanroom MUI */ + @NotNull + ModularPanel createPanel(GuiSyncManager syncManager); + + /** Uses Cleanroom MUI - Creates the widgets standalone so that they can be put into their own panel */ + + @NotNull + Widget createWidgets(GuiSyncManager syncManager); + + ItemStack getContainerStack(); + + void setDirtyNotifiable(@Nullable IDirtyNotifiable dirtyNotifiable); + + void markDirty(); + + int getMaxTransferSize(); + + void setMaxTransferSize(int maxTransferSize); + + boolean showGlobalTransferLimitSlider(); + + MatchResult match(Object toMatch); + + boolean test(Object toTest); + + int getTransferLimit(Object stack, int transferSize); + + default int getTransferLimit(int slot, int transferSize) { + return transferSize; + } + + void readFromNBT(NBTTagCompound tagCompound); + + FilterType getType(); + + enum FilterType { + ITEM, + FLUID + } + + // this only exists so i can pass in the constructor reference as a metaitem componant + static Factory factory(Factory factory) { + return factory; + } + + @FunctionalInterface + interface Factory extends IItemComponent { + + @NotNull + BaseFilter create(@NotNull ItemStack stack); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilter.java b/src/main/java/gregtech/common/covers/filter/ItemFilter.java deleted file mode 100644 index a5b350da33d..00000000000 --- a/src/main/java/gregtech/common/covers/filter/ItemFilter.java +++ /dev/null @@ -1,50 +0,0 @@ -package gregtech.common.covers.filter; - -import gregtech.api.gui.Widget; -import gregtech.api.util.IDirtyNotifiable; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; - -import java.util.function.Consumer; - -public abstract class ItemFilter { - - private IDirtyNotifiable dirtyNotifiable; - private int maxStackSize = Integer.MAX_VALUE; - - public final int getMaxStackSize() { - return maxStackSize; - } - - public final void setMaxStackSize(int maxStackSize) { - this.maxStackSize = maxStackSize; - onMaxStackSizeChange(); - } - - protected void onMaxStackSizeChange() {} - - public abstract boolean showGlobalTransferLimitSlider(); - - public abstract int getSlotTransferLimit(Object matchSlot, int globalTransferLimit); - - public abstract Object matchItemStack(ItemStack itemStack); - - public abstract int getTotalOccupiedHeight(); - - public abstract void initUI(Consumer widgetGroup); - - public abstract void writeToNBT(NBTTagCompound tagCompound); - - public abstract void readFromNBT(NBTTagCompound tagCompound); - - final void setDirtyNotifiable(IDirtyNotifiable dirtyNotifiable) { - this.dirtyNotifiable = dirtyNotifiable; - } - - public final void markDirty() { - if (dirtyNotifiable != null) { - dirtyNotifiable.markAsDirty(); - } - } -} diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java b/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java index 71be9ff14d3..d282595253d 100644 --- a/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java +++ b/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java @@ -1,165 +1,65 @@ package gregtech.common.covers.filter; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; import gregtech.api.gui.widgets.LabelWidget; +import gregtech.api.gui.widgets.ServerWidgetGroup; import gregtech.api.gui.widgets.SlotWidget; +import gregtech.api.gui.widgets.ToggleButtonWidget; import gregtech.api.util.IDirtyNotifiable; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.math.MathHelper; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.items.ItemStackHandler; -import org.jetbrains.annotations.NotNull; +import com.cleanroommc.modularui.api.drawable.IKey; +import org.jetbrains.annotations.ApiStatus; +import java.util.function.BooleanSupplier; import java.util.function.Consumer; -public class ItemFilterContainer implements INBTSerializable { - - private final ItemStackHandler filterInventory; - private final ItemFilterWrapper filterWrapper; - private int maxStackSizeLimit = 1; - private int transferStackSize; +public class ItemFilterContainer extends BaseFilterContainer { public ItemFilterContainer(IDirtyNotifiable dirtyNotifiable) { - this.filterWrapper = new ItemFilterWrapper(dirtyNotifiable); - this.filterWrapper.setOnFilterInstanceChange(this::onFilterInstanceChange); - this.filterInventory = new ItemStackHandler(1) { - - @Override - public boolean isItemValid(int slot, @NotNull ItemStack stack) { - return FilterTypeRegistry.getItemFilterForStack(stack) != null; - } - - @Override - public int getSlotLimit(int slot) { - return 1; - } - - @Override - protected void onLoad() { - onFilterSlotChange(false); - } - - @Override - protected void onContentsChanged(int slot) { - onFilterSlotChange(true); - } - }; - } - - public ItemStackHandler getFilterInventory() { - return filterInventory; - } - - public ItemFilterWrapper getFilterWrapper() { - return filterWrapper; - } - - private void onFilterInstanceChange() { - this.filterWrapper.setMaxStackSize(getTransferStackSize()); - } - - public int getMaxStackSize() { - return maxStackSizeLimit; - } - - public int getTransferStackSize() { - if (!showGlobalTransferLimitSlider()) { - return getMaxStackSize(); - } - return transferStackSize; + super(dirtyNotifiable); } - public void setTransferStackSize(int transferStackSize) { - this.transferStackSize = MathHelper.clamp(transferStackSize, 1, getMaxStackSize()); - this.filterWrapper.setMaxStackSize(getTransferStackSize()); - } - - public void adjustTransferStackSize(int amount) { - setTransferStackSize(transferStackSize + amount); - } - - public void initUI(int y, Consumer widgetGroup) { + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void initUI(int y, Consumer widgetGroup) { widgetGroup.accept(new LabelWidget(10, y, "cover.conveyor.item_filter.title")); - widgetGroup.accept(new SlotWidget(filterInventory, 0, 10, y + 15) - .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.FILTER_SLOT_OVERLAY)); - - this.filterWrapper.initUI(y + 38, widgetGroup); - this.filterWrapper.blacklistUI(y + 38, widgetGroup, () -> true); - } - - protected void onFilterSlotChange(boolean notify) { - ItemStack filterStack = filterInventory.getStackInSlot(0); - ItemFilter newItemFilter = FilterTypeRegistry.getItemFilterForStack(filterStack); - ItemFilter currentItemFilter = filterWrapper.getItemFilter(); - if (newItemFilter == null) { - if (currentItemFilter != null) { - filterWrapper.setItemFilter(null); - filterWrapper.setBlacklistFilter(false); - if (notify) filterWrapper.onFilterInstanceChange(); - } - } else if (currentItemFilter == null || - newItemFilter.getClass() != currentItemFilter.getClass()) { - filterWrapper.setItemFilter(newItemFilter); - if (notify) filterWrapper.onFilterInstanceChange(); - } - } - - public void setMaxStackSize(int maxStackSizeLimit) { - this.maxStackSizeLimit = maxStackSizeLimit; - setTransferStackSize(transferStackSize); - } - - public boolean showGlobalTransferLimitSlider() { - return getMaxStackSize() > 1 && filterWrapper.showGlobalTransferLimitSlider(); - } - - public int getSlotTransferLimit(Object slotIndex) { - return filterWrapper.getSlotTransferLimit(slotIndex, getTransferStackSize()); - } - - public Object matchItemStack(ItemStack itemStack) { - return filterWrapper.matchItemStack(itemStack); - } + widgetGroup.accept(new SlotWidget(this, 0, 10, y + 15) + .setBackgroundTexture(gregtech.api.gui.GuiTextures.SLOT, + gregtech.api.gui.GuiTextures.FILTER_SLOT_OVERLAY)); - public Object matchItemStack(ItemStack itemStack, boolean whitelist) { - return filterWrapper.matchItemStack(itemStack, whitelist); + this.initFilterUI(y + 38, widgetGroup); } - public boolean testItemStack(ItemStack itemStack) { - return matchItemStack(itemStack) != null; + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void initFilterUI(int y, Consumer widgetGroup) { + widgetGroup.accept(new WidgetGroupItemFilter(y, this::getFilter)); } - public boolean testItemStack(ItemStack itemStack, boolean whitelist) { - return matchItemStack(itemStack, whitelist) != null; + /** @deprecated uses old builtin MUI */ + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { + ServerWidgetGroup blacklistButton = new ServerWidgetGroup(this::hasFilter); + blacklistButton.addWidget(new ToggleButtonWidget(144, y, 20, 20, gregtech.api.gui.GuiTextures.BUTTON_BLACKLIST, + this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) + .setTooltipText("cover.filter.blacklist")); + widgetGroup.accept(blacklistButton); } @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tagCompound = new NBTTagCompound(); - tagCompound.setTag("FilterInventory", filterInventory.serializeNBT()); - tagCompound.setBoolean("IsBlacklist", filterWrapper.isBlacklistFilter()); - tagCompound.setInteger("MaxStackSize", maxStackSizeLimit); - tagCompound.setInteger("TransferStackSize", transferStackSize); - if (filterWrapper.getItemFilter() != null) { - NBTTagCompound filterInventory = new NBTTagCompound(); - filterWrapper.getItemFilter().writeToNBT(filterInventory); - tagCompound.setTag("Filter", filterInventory); - } - return tagCompound; + protected boolean isItemValid(ItemStack stack) { + var filter = BaseFilter.getFilterFromStack(stack); + return filter != null && filter.getType() == IFilter.FilterType.ITEM; } @Override - public void deserializeNBT(NBTTagCompound tagCompound) { - this.filterInventory.deserializeNBT(tagCompound.getCompoundTag("FilterInventory")); - this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); - setMaxStackSize(tagCompound.getInteger("MaxStackSize")); - setTransferStackSize(tagCompound.getInteger("TransferStackSize")); - if (filterWrapper.getItemFilter() != null) { - this.filterWrapper.getItemFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); - } + protected String getFilterName() { + return hasFilter() ? + getFilterStack().getDisplayName() : + IKey.lang("metaitem.item_filter.name").get(); } } diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java b/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java deleted file mode 100644 index d11905e00b5..00000000000 --- a/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java +++ /dev/null @@ -1,132 +0,0 @@ -package gregtech.common.covers.filter; - -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.ServerWidgetGroup; -import gregtech.api.gui.widgets.ToggleButtonWidget; -import gregtech.api.util.IDirtyNotifiable; - -import net.minecraft.item.ItemStack; - -import java.util.function.BooleanSupplier; -import java.util.function.Consumer; - -public class ItemFilterWrapper { - - private static final Object MATCH_RESULT_TRUE = new Object(); - private final IDirtyNotifiable dirtyNotifiable; - private boolean isBlacklistFilter = false; - private int maxStackSize = 1; - private ItemFilter currentItemFilter; - private Runnable onFilterInstanceChange; - - public ItemFilterWrapper(IDirtyNotifiable dirtyNotifiable) { - this.dirtyNotifiable = dirtyNotifiable; - } - - public void initUI(int y, Consumer widgetGroup) { - widgetGroup.accept(new WidgetGroupItemFilter(y, this::getItemFilter)); - } - - public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { - ServerWidgetGroup blacklistButton = new ServerWidgetGroup(() -> getItemFilter() != null); - blacklistButton.addWidget(new ToggleButtonWidget(144, y, 20, 20, GuiTextures.BUTTON_BLACKLIST, - this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) - .setTooltipText("cover.filter.blacklist")); - widgetGroup.accept(blacklistButton); - } - - public void setItemFilter(ItemFilter itemFilter) { - this.currentItemFilter = itemFilter; - if (currentItemFilter != null) { - currentItemFilter.setDirtyNotifiable(dirtyNotifiable); - } - if (onFilterInstanceChange != null) { - this.onFilterInstanceChange.run(); - } - } - - public ItemFilter getItemFilter() { - return currentItemFilter; - } - - public void setOnFilterInstanceChange(Runnable onFilterInstanceChange) { - this.onFilterInstanceChange = onFilterInstanceChange; - } - - public void onFilterInstanceChange() { - if (currentItemFilter != null) { - currentItemFilter.setMaxStackSize(getInternalMaxStackSize()); - } - dirtyNotifiable.markAsDirty(); - } - - public void setMaxStackSize(int maxStackSize) { - this.maxStackSize = maxStackSize; - onFilterInstanceChange(); - dirtyNotifiable.markAsDirty(); - } - - public void setBlacklistFilter(boolean blacklistFilter) { - isBlacklistFilter = blacklistFilter; - onFilterInstanceChange(); - dirtyNotifiable.markAsDirty(); - } - - public boolean isBlacklistFilter() { - return isBlacklistFilter; - } - - public int getMaxStackSize() { - return maxStackSize; - } - - private int getInternalMaxStackSize() { - if (isBlacklistFilter()) { - return 1; - } else { - return getMaxStackSize(); - } - } - - public boolean showGlobalTransferLimitSlider() { - return isBlacklistFilter() || currentItemFilter == null || currentItemFilter.showGlobalTransferLimitSlider(); - } - - public int getSlotTransferLimit(Object matchSlot, int globalTransferLimit) { - if (isBlacklistFilter() || currentItemFilter == null) { - return globalTransferLimit; - } - return currentItemFilter.getSlotTransferLimit(matchSlot, globalTransferLimit); - } - - public Object matchItemStack(ItemStack itemStack) { - Object originalResult; - if (currentItemFilter == null) { - originalResult = MATCH_RESULT_TRUE; - } else { - originalResult = currentItemFilter.matchItemStack(itemStack); - } - if (isBlacklistFilter()) { - originalResult = originalResult == null ? MATCH_RESULT_TRUE : null; - } - return originalResult; - } - - public Object matchItemStack(ItemStack itemStack, boolean whitelist) { - Object originalResult; - if (currentItemFilter == null) { - originalResult = MATCH_RESULT_TRUE; - } else { - originalResult = currentItemFilter.matchItemStack(itemStack); - } - if (!whitelist) { - originalResult = originalResult == null ? MATCH_RESULT_TRUE : null; - } - return originalResult; - } - - public boolean testItemStack(ItemStack itemStack) { - return matchItemStack(itemStack) != null; - } -} diff --git a/src/main/java/gregtech/common/covers/filter/MatchResult.java b/src/main/java/gregtech/common/covers/filter/MatchResult.java new file mode 100644 index 00000000000..028da359cb3 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/MatchResult.java @@ -0,0 +1,46 @@ +package gregtech.common.covers.filter; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class MatchResult { + + public static final MatchResult NONE = new MatchResult(false, null, -1); + public static final MatchResult ANY = new MatchResult(true, null, -1); + private final boolean matched; + private final Object matchedObject; + private final int filterIndex; + + private MatchResult(boolean matched, Object matchedObject, int filterIndex) { + this.matched = matched; + this.matchedObject = matchedObject; + this.filterIndex = filterIndex; + } + + public boolean isMatched() { + return matched; + } + + public Object getMatchedObject() { + return matchedObject; + } + + public @NotNull ItemStack getItemStack() { + return matchedObject instanceof ItemStack stack ? stack : ItemStack.EMPTY; + } + + public @Nullable FluidStack getFluidStack() { + return matchedObject instanceof FluidStack stack ? stack : null; + } + + public int getFilterIndex() { + return filterIndex; + } + + public static MatchResult create(boolean matched, Object matchedStack, int filterIndex) { + return new MatchResult(matched, matchedStack, filterIndex); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java b/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java index 1db9a6087e3..2a9fcaf402d 100644 --- a/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java +++ b/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java @@ -1,78 +1,69 @@ package gregtech.common.covers.filter; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.resources.TextureArea; -import gregtech.api.gui.widgets.DrawableWidget; -import gregtech.api.gui.widgets.ImageCycleButtonWidget; -import gregtech.api.gui.widgets.ImageWidget; +import gregtech.api.cover.CoverWithUI; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.stack.ItemVariantMap; import gregtech.api.unification.stack.MultiItemVariantMap; import gregtech.api.unification.stack.SingleItemVariantMap; -import gregtech.api.util.function.BooleanConsumer; -import gregtech.api.util.oreglob.OreGlob; import gregtech.api.util.oreglob.OreGlobCompileResult; -import gregtech.common.covers.filter.oreglob.impl.ImpossibleOreGlob; -import gregtech.common.gui.widget.HighlightedTextField; -import gregtech.common.gui.widget.orefilter.ItemOreFilterTestSlot; -import gregtech.common.gui.widget.orefilter.OreGlobCompileStatusWidget; +import gregtech.common.covers.filter.readers.OreDictFilterReader; +import gregtech.common.mui.widget.HighlightedTextField; +import gregtech.common.mui.widget.orefilter.OreFilterTestSlot; +import net.minecraft.client.resources.I18n; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.PacketBuffer; import net.minecraft.util.text.TextFormatting; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.drawable.UITexture; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.Tooltip; +import com.cleanroommc.modularui.utils.BooleanConsumer; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widget.Widget; +import com.cleanroommc.modularui.widgets.CycleButtonWidget; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Set; -import java.util.function.BooleanSupplier; import java.util.function.Consumer; -public class OreDictionaryItemFilter extends ItemFilter { +public class OreDictionaryItemFilter extends BaseFilter { private final Map> matchCache = new Object2ObjectOpenHashMap<>(); private final SingleItemVariantMap noOreDictMatch = new SingleItemVariantMap<>(); + private final OreDictFilterReader filterReader; - protected String expression = ""; - - private OreGlob glob = ImpossibleOreGlob.getInstance(); - private boolean error; - - private boolean caseSensitive; - /** - * {@code false} requires any of the entry to be match in order for the match to be success, {@code true} requires - * all entries to match - */ - private boolean matchAll; + public OreDictionaryItemFilter(ItemStack stack) { + this.filterReader = new OreDictFilterReader(stack); + recompile(); + } - @NotNull - public String getExpression() { - return expression; + @Override + public OreDictFilterReader getFilterReader() { + return filterReader; } @NotNull - public OreGlob getGlob() { - return this.glob; + public String getExpression() { + return this.filterReader.getExpression(); } - protected void recompile(@Nullable Consumer<@Nullable OreGlobCompileResult> callback) { + protected void recompile() { clearCache(); - String expr = this.expression; - if (!expr.isEmpty()) { - OreGlobCompileResult result = OreGlob.compile(expr, !this.caseSensitive); - this.glob = result.getInstance(); - this.error = result.hasError(); - if (callback != null) callback.accept(result); - } else { - this.glob = ImpossibleOreGlob.getInstance(); - this.error = true; - if (callback != null) callback.accept(null); - } + this.filterReader.recompile(); } protected void clearCache() { @@ -81,106 +72,211 @@ protected void clearCache() { } @Override - public void initUI(Consumer widgetGroup) { - ItemOreFilterTestSlot[] testSlot = new ItemOreFilterTestSlot[5]; - for (int i = 0; i < testSlot.length; i++) { - ItemOreFilterTestSlot slot = new ItemOreFilterTestSlot(20 + 22 * i, 0); - slot.setGlob(getGlob()); - slot.setMatchAll(this.matchAll); - widgetGroup.accept(slot); - testSlot[i] = slot; - } - OreGlobCompileStatusWidget compilationStatus = new OreGlobCompileStatusWidget(10, 10); + public void initUI(Consumer widgetGroup) {} - Consumer<@Nullable OreGlobCompileResult> compileCallback = result -> { - compilationStatus.setCompileResult(result); - for (ItemOreFilterTestSlot slot : testSlot) { - slot.setGlob(getGlob()); + @Override + public @NotNull ModularPanel createPopupPanel(GuiSyncManager syncManager) { + return GTGuis.createPopupPanel("ore_dict_filter", 188, 76) + .padding(7) + .child(CoverWithUI.createTitleRow(getContainerStack())) + .child(createWidgets(syncManager).top(22)); + } + + @Override + public @NotNull ModularPanel createPanel(GuiSyncManager syncManager) { + return GTGuis.createPanel("ore_dict_filter", 100, 100); + } + + @Override + public @NotNull Widget createWidgets(GuiSyncManager syncManager) { + List oreSlots = new ArrayList<>(); + var expression = new StringSyncValue(this.filterReader::getExpression, this.filterReader::setExpression); + + BooleanConsumer setCaseSensitive = b -> { + this.filterReader.setCaseSensitive(b); + if (!syncManager.isClient()) return; + for (var slot : oreSlots) { + slot.updatePreview(); } }; - HighlightedTextField textField = new HighlightedTextField(14, 26, 152, 14, () -> this.expression, - s -> { - if (s.equals(this.expression)) return; - this.expression = s; - markDirty(); - recompile(compileCallback); - }); - compilationStatus.setTextField(textField); - - widgetGroup.accept(new ImageWidget(10, 0, 7, 7, GuiTextures.ORE_FILTER_INFO) - .setTooltip("cover.ore_dictionary_filter.info")); - widgetGroup.accept(compilationStatus); - widgetGroup.accept(new DrawableWidget(10, 22, 156, 16) - .setBackgroundDrawer((mouseX, mouseY, partialTicks, context, widget) -> { - Widget.drawGradientRect(widget.getPosition().x, widget.getPosition().y, - widget.getSize().width, widget.getSize().height, - 0xFF808080, 0xFF808080, false); - Widget.drawGradientRect(widget.getPosition().x + 1, widget.getPosition().y + 1, - widget.getSize().width - 2, widget.getSize().height - 2, - 0xFF000000, 0xFF000000, false); - })); - widgetGroup.accept(textField - .setHighlightRule(h -> { - String t = h.getOriginalText(); - for (int i = 0; i < t.length(); i++) { - switch (t.charAt(i)) { - case '|', '&', '^', '(', ')' -> h.format(i, TextFormatting.GOLD); - case '*', '?' -> h.format(i, TextFormatting.GREEN); - case '!' -> h.format(i, TextFormatting.RED); - case '\\' -> h.format(i++, TextFormatting.YELLOW); - case '$' -> { // TODO: remove this switch case in 2.9 - h.format(i, TextFormatting.DARK_GREEN); - for (; i < t.length(); i++) { - switch (t.charAt(i)) { - case ' ', '\t', '\n', '\r' -> {} - case '\\' -> { - i++; - continue; - } - default -> { - continue; - } - } - break; - } + BooleanConsumer setMatchAll = b -> { + this.clearCache(); + this.filterReader.setMatchAll(b); + if (!syncManager.isClient()) return; + for (var slot : oreSlots) { + slot.setMatchAll(b); + } + }; + + var caseSensitive = new BooleanSyncValue(this.filterReader::isCaseSensitive, setCaseSensitive); + var matchAll = new BooleanSyncValue(this.filterReader::shouldMatchAll, setMatchAll); + + return new Column().widthRel(1f).coverChildrenHeight() + .child(new HighlightedTextField() + .setHighlightRule(this::highlightRule) + .onUnfocus(() -> { + for (var slot : oreSlots) { + slot.updatePreview(); + } + }) + .setTextColor(Color.WHITE.darker(1)) + .value(expression).marginBottom(4) + .height(18).widthRel(1f)) + .child(new Row().coverChildrenHeight() + .widthRel(1f) + .child(new Column().height(18) + .coverChildrenWidth().marginRight(2) + .child(GTGuiTextures.OREDICT_INFO.asWidget() + .size(8).top(0) + .addTooltipLine(IKey.lang("cover.ore_dictionary_filter.info"))) + .child(new Widget<>() + .size(8).bottom(0) + .onUpdateListener(this::getStatusIcon) + .tooltipBuilder(this::createStatusTooltip) + .tooltip(tooltip -> tooltip.setAutoUpdate(true)))) + .child(SlotGroupWidget.builder() + .row("XXXXX") + .key('X', i -> { + var slot = new OreFilterTestSlot() + .setGlobSupplier(this.filterReader::getGlob); + slot.setMatchAll(this.filterReader.shouldMatchAll()); + oreSlots.add(slot); + return slot; + }) + .build().marginRight(2)) + .child(new CycleButtonWidget() + .size(18).value(caseSensitive) + .marginRight(2) + .textureGetter(state -> GTGuiTextures.BUTTON_CASE_SENSITIVE[state]) + .addTooltip(0, + IKey.lang("cover.ore_dictionary_filter.button.case_sensitive.disabled")) + .addTooltip(1, + IKey.lang("cover.ore_dictionary_filter.button.case_sensitive.enabled"))) + .child(new CycleButtonWidget() + .size(18).value(matchAll) + .marginRight(2) + .textureGetter(state -> GTGuiTextures.BUTTON_MATCH_ALL[state]) + .addTooltip(0, + IKey.lang("cover.ore_dictionary_filter.button.match_all.disabled")) + .addTooltip(1, + IKey.lang("cover.ore_dictionary_filter.button.match_all.enabled"))) + .child(createBlacklistUI())); + } + + protected void getStatusIcon(Widget widget) { + UITexture texture; + var result = this.filterReader.getResult(); + + if (result == null) { + texture = GTGuiTextures.OREDICT_WAITING; + } else if (result.getReports().length == 0) { + texture = GTGuiTextures.OREDICT_SUCCESS; + } else if (result.hasError()) { + texture = GTGuiTextures.OREDICT_ERROR; + } else { + texture = GTGuiTextures.OREDICT_WARN; + } + widget.background(texture); + } + + protected void createStatusTooltip(Tooltip tooltip) { + var result = this.filterReader.getResult(); + if (result == null) return; + List list = new ArrayList<>(); + + int error = 0, warn = 0; + for (OreGlobCompileResult.Report report : result.getReports()) { + if (report.isError()) error++; + else warn++; + list.add((report.isError() ? TextFormatting.RED : TextFormatting.GOLD) + report.toString()); + } + if (error > 0) { + if (warn > 0) { + list.add(0, I18n.format("cover.ore_dictionary_filter.status.err_warn", error, warn)); + } else { + list.add(0, I18n.format("cover.ore_dictionary_filter.status.err", error)); + } + } else { + if (warn > 0) { + list.add(0, I18n.format("cover.ore_dictionary_filter.status.warn", warn)); + } else { + list.add(I18n.format("cover.ore_dictionary_filter.status.no_issues")); + } + list.add(""); + list.add(I18n.format("cover.ore_dictionary_filter.status.explain")); + list.add(""); + list.addAll(result.getInstance().toFormattedString()); + } + tooltip.addStringLines(list); + } + + protected String highlightRule(String text) { + StringBuilder builder = new StringBuilder(text); + for (int i = 0; i < builder.length(); i++) { + switch (builder.charAt(i)) { + case '|', '&', '^', '(', ')' -> { + builder.insert(i, TextFormatting.GOLD); + i += 2; + } + case '*', '?' -> { + builder.insert(i, TextFormatting.GREEN); + i += 2; + } + case '!' -> { + builder.insert(i, TextFormatting.RED); + i += 2; + } + case '\\' -> { + builder.insert(i++, TextFormatting.YELLOW); + i += 2; + } + case '$' -> { // TODO: remove this switch case in 2.9 + builder.insert(i, TextFormatting.DARK_GREEN); + for (; i < builder.length(); i++) { + switch (builder.charAt(i)) { + case ' ', '\t', '\n', '\r' -> {} + case '\\' -> { + i++; + continue; } default -> { continue; } } - h.format(i + 1, TextFormatting.RESET); - } - }).setMaxLength(64)); - widgetGroup.accept(new ForcedInitialSyncImageCycleButtonWidget(130, 38, 18, 18, - GuiTextures.ORE_FILTER_BUTTON_CASE_SENSITIVE, () -> this.caseSensitive, caseSensitive -> { - if (this.caseSensitive == caseSensitive) return; - this.caseSensitive = caseSensitive; - markDirty(); - recompile(compileCallback); - }).setTooltipHoverString( - i -> "cover.ore_dictionary_filter.button.case_sensitive." + (i == 0 ? "disabled" : "enabled"))); - widgetGroup.accept(new ForcedInitialSyncImageCycleButtonWidget(148, 38, 18, 18, - GuiTextures.ORE_FILTER_BUTTON_MATCH_ALL, () -> this.matchAll, matchAll -> { - if (this.matchAll == matchAll) return; - this.matchAll = matchAll; - markDirty(); - clearCache(); - for (ItemOreFilterTestSlot slot : testSlot) { - slot.setMatchAll(matchAll); + break; } - }).setTooltipHoverString( - i -> "cover.ore_dictionary_filter.button.match_all." + (i == 0 ? "disabled" : "enabled"))); + } + default -> { + continue; + } + } + builder.insert(i + 1, TextFormatting.RESET); + } + return builder.toString(); + } + + @Override + public MatchResult matchItem(ItemStack itemStack) { + // "wtf is this system?? i can put any non null object here and it i will work??? $arch" + // not anymore :thanosdaddy: -ghzdude + var match = matchesItemStack(itemStack); + return MatchResult.create(match != isBlacklistFilter(), match ? itemStack.copy() : ItemStack.EMPTY, -1); + } + + @Override + public boolean testItem(ItemStack toTest) { + return matchesItemStack(toTest); } @Override - public Object matchItemStack(ItemStack itemStack) { - return matchesItemStack(itemStack) ? - "wtf is this system?? i can put any non null object here and it i will work??? $arch" : null; + public FilterType getType() { + return FilterType.ITEM; } public boolean matchesItemStack(@NotNull ItemStack itemStack) { - if (this.error) return false; + var result = this.filterReader.getResult(); + if (result == null || result.hasError()) return false; Item item = itemStack.getItem(); ItemVariantMap> oreDictEntry = OreDictUnifier.getOreDictionaryEntry(item); @@ -188,7 +284,7 @@ public boolean matchesItemStack(@NotNull ItemStack itemStack) { // no oredict entries associated Boolean cached = this.noOreDictMatch.getEntry(); if (cached == null) { - cached = this.glob.matches(""); + cached = this.filterReader.getGlob().matches(""); } this.matchCache.put(item, this.noOreDictMatch); return cached; @@ -205,7 +301,7 @@ public boolean matchesItemStack(@NotNull ItemStack itemStack) { // no oredict entries associated Boolean cached = this.noOreDictMatch.getEntry(); if (cached == null) { - cached = this.glob.matches(""); + cached = this.filterReader.getGlob().matches(""); this.noOreDictMatch.put(cached); } this.matchCache.put(item, this.noOreDictMatch); @@ -217,64 +313,15 @@ public boolean matchesItemStack(@NotNull ItemStack itemStack) { } this.matchCache.put(item, cacheEntry); } - boolean matches = this.matchAll ? this.glob.matchesAll(itemStack) : this.glob.matchesAny(itemStack); + boolean matches = this.filterReader.shouldMatchAll() ? + this.filterReader.getGlob().matchesAll(itemStack) : + this.filterReader.getGlob().matchesAny(itemStack); cacheEntry.put(itemStack, matches); return matches; } - @Override - public int getSlotTransferLimit(Object matchSlot, int globalTransferLimit) { - return globalTransferLimit; - } - @Override public boolean showGlobalTransferLimitSlider() { return true; } - - @Override - public int getTotalOccupiedHeight() { - return 37; - } - - @Override - public void writeToNBT(NBTTagCompound tag) { - tag.setString("OreDictionaryFilter", expression); - if (this.caseSensitive) tag.setBoolean("caseSensitive", true); - if (this.matchAll) tag.setBoolean("matchAll", true); - } - - @Override - public void readFromNBT(NBTTagCompound tag) { - this.expression = tag.getString("OreDictionaryFilter"); - this.caseSensitive = tag.getBoolean("caseSensitive"); - this.matchAll = tag.getBoolean("matchAll"); - recompile(null); - } - - public static class ForcedInitialSyncImageCycleButtonWidget extends ImageCycleButtonWidget { - - private final BooleanConsumer updater; - - public ForcedInitialSyncImageCycleButtonWidget(int xPosition, int yPosition, int width, int height, - TextureArea buttonTexture, BooleanSupplier supplier, - BooleanConsumer updater) { - super(xPosition, yPosition, width, height, buttonTexture, supplier, updater); - this.currentOption = 0; - this.updater = updater; - } - - @Override - public void readUpdateInfo(int id, PacketBuffer buffer) { - if (id == 1) { - int currentOptionCache = this.currentOption; - super.readUpdateInfo(id, buffer); - if (this.currentOption != currentOptionCache) { - this.updater.apply(currentOption >= 1); // call updater to apply necessary state changes - } - } else { - super.readUpdateInfo(id, buffer); - } - } - } } diff --git a/src/main/java/gregtech/common/covers/filter/SimpleFluidFilter.java b/src/main/java/gregtech/common/covers/filter/SimpleFluidFilter.java index c3abb86898e..c19a5600d2e 100644 --- a/src/main/java/gregtech/common/covers/filter/SimpleFluidFilter.java +++ b/src/main/java/gregtech/common/covers/filter/SimpleFluidFilter.java @@ -1,118 +1,119 @@ package gregtech.common.covers.filter; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.PhantomFluidWidget; +import gregtech.api.cover.CoverWithUI; +import gregtech.api.mui.GTGuis; +import gregtech.api.mui.sync.FixedFluidSlotSH; +import gregtech.common.covers.filter.readers.SimpleFluidFilterReader; -import net.minecraft.nbt.NBTBase; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; +import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; -import org.jetbrains.annotations.Nullable; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.Widget; +import com.cleanroommc.modularui.widgets.FluidSlot; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.layout.Row; +import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; -public class SimpleFluidFilter extends FluidFilter { +public class SimpleFluidFilter extends BaseFilter { private static final int MAX_FLUID_SLOTS = 9; - protected final FluidTank[] fluidFilterTanks = new FluidTank[MAX_FLUID_SLOTS]; + private final SimpleFluidFilterReader filterReader; - public SimpleFluidFilter() { - for (int i = 0; i < MAX_FLUID_SLOTS; ++i) { - fluidFilterTanks[i] = new FluidTank(1000) { - - @Override - public void setFluid(@Nullable FluidStack fluid) { - super.setFluid(fluid); - SimpleFluidFilter.this.markDirty(); - } - }; - } + public SimpleFluidFilter(ItemStack stack) { + filterReader = new SimpleFluidFilterReader(stack, MAX_FLUID_SLOTS); } @Override + public SimpleFluidFilterReader getFilterReader() { + return filterReader; + } + public void configureFilterTanks(int amount) { - for (FluidTank fluidTank : fluidFilterTanks) { - if (fluidTank.getFluid() != null) - fluidTank.getFluid().amount = amount; - } + this.filterReader.setFluidAmounts(amount); this.markDirty(); } @Override - public void setMaxConfigurableFluidSize(int maxSize) { - for (FluidTank fluidTank : fluidFilterTanks) { - fluidTank.setCapacity(maxSize); - } + public @NotNull ModularPanel createPopupPanel(GuiSyncManager syncManager) { + return GTGuis.createPopupPanel("simple_fluid_filter", 98, 81) + .padding(4) + .child(CoverWithUI.createTitleRow(getContainerStack())) + .child(createWidgets(syncManager).top(22)); } @Override - public boolean testFluid(FluidStack fluidStack) { - return checkInputFluid(fluidFilterTanks, fluidStack); + public @NotNull ModularPanel createPanel(GuiSyncManager syncManager) { + return GTGuis.createPanel(getContainerStack(), 176, 168); } @Override - public int getMaxOccupiedHeight() { - return 36; + public @NotNull Widget createWidgets(GuiSyncManager syncManager) { + return new Row().coverChildrenHeight().widthRel(1f) + .child(SlotGroupWidget.builder() + .matrix("FFF", + "FFF", + "FFF") + .key('F', i -> new FluidSlot() + .syncHandler(new FixedFluidSlotSH(filterReader.getFluidTank(i)).phantom(true))) + .build().marginRight(4)) + .child(createBlacklistUI()); } @Override - public void initUI(Consumer widgetGroup) { - for (int i = 0; i < 9; ++i) { - widgetGroup.accept((new PhantomFluidWidget(10 + 18 * (i % 3), 18 * (i / 3), 18, 18, - this.fluidFilterTanks[i])) - .setBackgroundTexture(GuiTextures.SLOT).showTipSupplier(this::shouldShowTip)); + public MatchResult matchFluid(FluidStack fluidStack) { + int index = -1; + FluidStack returnable = null; + for (int i = 0; i < filterReader.getSize(); i++) { + var fluid = filterReader.getFluidStack(i); + if (fluid != null && fluid.isFluidEqual(fluidStack)) { + index = i; + returnable = fluid.copy(); + break; + } } + return MatchResult.create(index != -1, returnable, index); } - private boolean shouldShowTip() { - return showTip; - } - - public void writeToNBT(NBTTagCompound tagCompound) { - NBTTagList filterSlots = new NBTTagList(); - for (int i = 0; i < this.fluidFilterTanks.length; ++i) { - FluidTank fluidTank = this.fluidFilterTanks[i]; - if (fluidTank.getFluid() != null) { - NBTTagCompound stackTag = new NBTTagCompound(); - fluidTank.getFluid().writeToNBT(stackTag); - stackTag.setInteger("Slot", i); - filterSlots.appendTag(stackTag); + @Override + public boolean testFluid(FluidStack toTest) { + for (int i = 0; i < filterReader.getSize(); i++) { + var fluid = filterReader.getFluidStack(i); + if (fluid != null && fluid.isFluidEqual(toTest)) { + return true; } } - tagCompound.setTag("FluidFilter", filterSlots); + return false; } - public void readFromNBT(NBTTagCompound tagCompound) { - NBTTagList filterSlots = tagCompound.getTagList("FluidFilter", 10); - for (NBTBase nbtBase : filterSlots) { - NBTTagCompound stackTag = (NBTTagCompound) nbtBase; - FluidStack fluidStack = FluidStack.loadFluidStackFromNBT(stackTag); - this.fluidFilterTanks[stackTag.getInteger("Slot")].setFluid(fluidStack); + @Override + public void initUI(Consumer widgetGroup) { + for (int i = 0; i < 9; ++i) { + widgetGroup.accept((new gregtech.api.gui.widgets.PhantomFluidWidget(10 + 18 * (i % 3), 18 * (i / 3), 18, 18, + filterReader.getFluidTank(i))) + .setBackgroundTexture(gregtech.api.gui.GuiTextures.SLOT)); } } - public static boolean checkInputFluid(FluidTank[] fluidFilterTanks, FluidStack fluidStack) { - for (FluidTank fluidTank : fluidFilterTanks) { - if (fluidTank.getFluid() != null && fluidTank.getFluid().isFluidEqual(fluidStack)) { - return true; + @Override + public int getTransferLimit(FluidStack fluidStack, int transferSize) { + int limit = 0; + + for (int i = 0; i < this.filterReader.getSize(); i++) { + var fluid = this.filterReader.getFluidStack(i); + if (fluid != null && fluid.isFluidEqual(fluidStack)) { + limit = fluid.amount; } } - return false; + return isBlacklistFilter() ? transferSize : limit; } @Override - public int getFluidTransferLimit(FluidStack fluidStack) { - int limit = 0; - for (FluidTank fluidTank : fluidFilterTanks) { - if (fluidTank.getFluid() != null && fluidTank.getFluid().isFluidEqual(fluidStack)) { - limit = fluidTank.getFluid().amount; - break; - } - } - return limit; + public FilterType getType() { + return FilterType.FLUID; } } diff --git a/src/main/java/gregtech/common/covers/filter/SimpleItemFilter.java b/src/main/java/gregtech/common/covers/filter/SimpleItemFilter.java index 864986ca805..8bb4c556753 100644 --- a/src/main/java/gregtech/common/covers/filter/SimpleItemFilter.java +++ b/src/main/java/gregtech/common/covers/filter/SimpleItemFilter.java @@ -1,119 +1,167 @@ package gregtech.common.covers.filter; +import gregtech.api.cover.CoverWithUI; import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; import gregtech.api.gui.widgets.PhantomSlotWidget; import gregtech.api.gui.widgets.ToggleButtonWidget; -import gregtech.api.util.LargeStackSizeItemStackHandler; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; +import gregtech.api.util.TextFormattingUtil; +import gregtech.common.covers.CoverItemVoidingAdvanced; +import gregtech.common.covers.CoverRoboticArm; +import gregtech.common.covers.TransferMode; +import gregtech.common.covers.VoidingMode; +import gregtech.common.covers.filter.readers.SimpleItemFilterReader; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemStackHandler; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.value.sync.SyncHandlers; +import com.cleanroommc.modularui.widget.Widget; +import com.cleanroommc.modularui.widgets.CycleButtonWidget; +import com.cleanroommc.modularui.widgets.ItemSlot; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.slot.SlotGroup; +import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; -public class SimpleItemFilter extends ItemFilter { +public class SimpleItemFilter extends BaseFilter { private static final int MAX_MATCH_SLOTS = 9; + private final SimpleItemFilterReader filterReader; - protected final ItemStackHandler itemFilterSlots; - protected boolean ignoreDamage = true; - protected boolean ignoreNBT = true; - - public SimpleItemFilter() { - this.itemFilterSlots = new LargeStackSizeItemStackHandler(MAX_MATCH_SLOTS) { - - @Override - public int getSlotLimit(int slot) { - return getMaxStackSize(); - } - }; + public SimpleItemFilter(ItemStack stack) { + filterReader = new SimpleItemFilterReader(stack, MAX_MATCH_SLOTS); } @Override - protected void onMaxStackSizeChange() { - for (int i = 0; i < itemFilterSlots.getSlots(); i++) { - ItemStack itemStack = itemFilterSlots.getStackInSlot(i); - if (!itemStack.isEmpty()) { - itemStack.setCount(Math.min(itemStack.getCount(), getMaxStackSize())); - } - } - } - - public ItemStackHandler getItemFilterSlots() { - return itemFilterSlots; + public SimpleItemFilterReader getFilterReader() { + return filterReader; } - public boolean isIgnoreDamage() { - return ignoreDamage; - } - - public boolean isIgnoreNBT() { - return ignoreNBT; - } - - protected void setIgnoreDamage(boolean ignoreDamage) { - this.ignoreDamage = ignoreDamage; - markDirty(); - } - - protected void setIgnoreNBT(boolean ignoreNBT) { - this.ignoreNBT = ignoreNBT; - markDirty(); + @Override + public MatchResult matchItem(ItemStack itemStack) { + int matchedSlot = itemFilterMatch(filterReader, filterReader.isIgnoreDamage(), filterReader.isIgnoreNBT(), + itemStack); + return MatchResult.create(matchedSlot != -1 == !isBlacklistFilter(), + filterReader.getStackInSlot(matchedSlot), matchedSlot); } @Override - public Integer matchItemStack(ItemStack itemStack) { - int itemFilterMatchIndex = itemFilterMatch(getItemFilterSlots(), isIgnoreDamage(), isIgnoreNBT(), itemStack); - return itemFilterMatchIndex == -1 ? null : itemFilterMatchIndex; + public boolean testItem(ItemStack toTest) { + int matchedSlot = itemFilterMatch(filterReader, filterReader.isIgnoreDamage(), filterReader.isIgnoreNBT(), + toTest); + return matchedSlot != -1; } @Override - public int getSlotTransferLimit(Object matchSlot, int globalTransferLimit) { - Integer matchSlotIndex = (Integer) matchSlot; - ItemStack stackInFilterSlot = itemFilterSlots.getStackInSlot(matchSlotIndex); - return Math.min(stackInFilterSlot.getCount(), globalTransferLimit); + public int getTransferLimit(int matchSlot, int transferSize) { + ItemStack stackInFilterSlot = filterReader.getStackInSlot(matchSlot); + return Math.min(stackInFilterSlot.getCount(), transferSize); } @Override - public boolean showGlobalTransferLimitSlider() { - return false; + public FilterType getType() { + return FilterType.ITEM; } @Override - public int getTotalOccupiedHeight() { - return 36; + public int getTransferLimit(ItemStack stack, int transferSize) { + int matchedSlot = itemFilterMatch(filterReader, filterReader.isIgnoreDamage(), filterReader.isIgnoreNBT(), + stack); + return getTransferLimit(matchedSlot, transferSize); } @Override - public void initUI(Consumer widgetGroup) { + public void initUI(Consumer widgetGroup) { for (int i = 0; i < 9; i++) { - widgetGroup.accept(new PhantomSlotWidget(itemFilterSlots, i, 10 + 18 * (i % 3), 18 * (i / 3)) + widgetGroup.accept(new PhantomSlotWidget(filterReader, i, 10 + 18 * (i % 3), 18 * (i / 3)) .setBackgroundTexture(GuiTextures.SLOT)); } widgetGroup.accept(new ToggleButtonWidget(74, 0, 20, 20, GuiTextures.BUTTON_FILTER_DAMAGE, - () -> ignoreDamage, this::setIgnoreDamage).setTooltipText("cover.item_filter.ignore_damage")); + filterReader::isIgnoreDamage, filterReader::setIgnoreDamage) + .setTooltipText("cover.item_filter.ignore_damage")); widgetGroup.accept(new ToggleButtonWidget(99, 0, 20, 20, GuiTextures.BUTTON_FILTER_NBT, - () -> ignoreNBT, this::setIgnoreNBT).setTooltipText("cover.item_filter.ignore_nbt")); + filterReader::isIgnoreNBT, filterReader::setIgnoreNBT).setTooltipText("cover.item_filter.ignore_nbt")); } @Override - public void writeToNBT(NBTTagCompound tagCompound) { - tagCompound.setTag("ItemFilter", itemFilterSlots.serializeNBT()); - tagCompound.setBoolean("IgnoreDamage", ignoreDamage); - tagCompound.setBoolean("IgnoreNBT", ignoreNBT); + public @NotNull ModularPanel createPopupPanel(GuiSyncManager syncManager) { + return GTGuis.createPopupPanel("simple_item_filter", 98, 81) + .child(CoverWithUI.createTitleRow(getContainerStack())) + .child(createWidgets(syncManager).top(22).left(4)); } @Override - public void readFromNBT(NBTTagCompound tagCompound) { - this.itemFilterSlots.deserializeNBT(tagCompound.getCompoundTag("ItemFilter")); - this.ignoreDamage = tagCompound.getBoolean("IgnoreDamage"); - this.ignoreNBT = tagCompound.getBoolean("IgnoreNBT"); + public @NotNull ModularPanel createPanel(GuiSyncManager syncManager) { + return GTGuis.createPanel("simple_item_filter", 176, 166); } - public static int itemFilterMatch(IItemHandler filterSlots, boolean ignoreDamage, boolean ignoreNBTData, - ItemStack itemStack) { + @SuppressWarnings("UnstableApiUsage") + @Override + public @NotNull Widget createWidgets(GuiSyncManager syncManager) { + SlotGroup filterInventory = new SlotGroup("filter_inv", 3, 1000, true); + var ignoreDamage = new BooleanSyncValue(this.filterReader::isIgnoreDamage, this.filterReader::setIgnoreDamage); + var ignoreNBT = new BooleanSyncValue(this.filterReader::isIgnoreNBT, this.filterReader::setIgnoreNBT); + + syncManager.registerSlotGroup(filterInventory); + + return new Row().coverChildren() + .child(SlotGroupWidget.builder() + .matrix("XXX", + "XXX", + "XXX") + .key('X', index -> new ItemSlot() + .tooltip(tooltip -> { + tooltip.setAutoUpdate(true); + tooltip.textColor(Color.GREY.main); + }) + .tooltipBuilder(tooltip -> { + if (dirtyNotifiable instanceof CoverRoboticArm coverArm && + coverArm.getTransferMode() != TransferMode.TRANSFER_ANY || + dirtyNotifiable instanceof CoverItemVoidingAdvanced coverItem && + coverItem.getVoidingMode() != VoidingMode.VOID_ANY) { + tooltip.addLine(IKey.lang("cover.item_filter.config_amount")); + int count = this.filterReader.getTagAt(index) + .getInteger(SimpleItemFilterReader.COUNT); + if (count > 0) + tooltip.addLine( + IKey.format("Count: %s", TextFormattingUtil.formatNumbers(count))); + } + }) + .slot(SyncHandlers.phantomItemSlot(this.filterReader, index) + .ignoreMaxStackSize(true) + .slotGroup(filterInventory) + .changeListener((newItem, onlyAmountChanged, client, init) -> { + if (onlyAmountChanged && !init) { + markDirty(); + } + }))) + .build().marginRight(4)) + .child(new Column().width(18).coverChildren() + .child(createBlacklistUI()) + .child(new CycleButtonWidget() + .value(ignoreDamage) + .textureGetter(state -> GTGuiTextures.BUTTON_IGNORE_DAMAGE[state]) + .addTooltip(0, IKey.lang("cover.item_filter.ignore_damage.disabled")) + .addTooltip(1, IKey.lang("cover.item_filter.ignore_damage.enabled"))) + .child(new CycleButtonWidget() + .value(ignoreNBT) + .textureGetter(state -> GTGuiTextures.BUTTON_IGNORE_NBT[state]) + .addTooltip(0, IKey.lang("cover.item_filter.ignore_nbt.disabled")) + .addTooltip(1, IKey.lang("cover.item_filter.ignore_nbt.enabled")))); + } + + public static int itemFilterMatch(IItemHandler filterSlots, boolean ignoreDamage, + boolean ignoreNBTData, ItemStack itemStack) { for (int i = 0; i < filterSlots.getSlots(); i++) { ItemStack filterStack = filterSlots.getStackInSlot(i); if (!filterStack.isEmpty() && areItemsEqual(ignoreDamage, ignoreNBTData, filterStack, itemStack)) { @@ -123,8 +171,8 @@ public static int itemFilterMatch(IItemHandler filterSlots, boolean ignoreDamage return -1; } - private static boolean areItemsEqual(boolean ignoreDamage, boolean ignoreNBTData, ItemStack filterStack, - ItemStack itemStack) { + private static boolean areItemsEqual(boolean ignoreDamage, boolean ignoreNBTData, + ItemStack filterStack, ItemStack itemStack) { if (ignoreDamage) { if (!filterStack.isItemEqualIgnoreDurability(itemStack)) { return false; diff --git a/src/main/java/gregtech/common/covers/filter/SmartItemFilter.java b/src/main/java/gregtech/common/covers/filter/SmartItemFilter.java index a655d22f732..651c768e4dd 100644 --- a/src/main/java/gregtech/common/covers/filter/SmartItemFilter.java +++ b/src/main/java/gregtech/common/covers/filter/SmartItemFilter.java @@ -1,95 +1,144 @@ package gregtech.common.covers.filter; -import gregtech.api.gui.Widget; +import gregtech.api.cover.CoverWithUI; import gregtech.api.gui.widgets.CycleButtonWidget; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.RecipeMaps; import gregtech.api.recipes.ingredients.GTRecipeInput; import gregtech.api.unification.stack.ItemAndMetadata; +import gregtech.common.covers.filter.readers.SmartItemFilterReader; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.IStringSerializable; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.BoolValue; +import com.cleanroommc.modularui.value.sync.EnumSyncValue; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widget.Widget; +import com.cleanroommc.modularui.widgets.ToggleButton; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.jetbrains.annotations.NotNull; import java.util.Collections; -import java.util.Map; import java.util.function.Consumer; -public class SmartItemFilter extends ItemFilter { +public class SmartItemFilter extends BaseFilter { - private SmartFilteringMode filteringMode = SmartFilteringMode.ELECTROLYZER; + private final SmartItemFilterReader filterReader; - public SmartFilteringMode getFilteringMode() { - return filteringMode; + public SmartItemFilter(ItemStack stack) { + filterReader = new SmartItemFilterReader(stack); } - public void setFilteringMode(SmartFilteringMode filteringMode) { - this.filteringMode = filteringMode; - markDirty(); + @Override + public SmartItemFilterReader getFilterReader() { + return filterReader; } - @Override - public int getSlotTransferLimit(Object matchSlot, int globalTransferLimit) { - ItemAndMetadataAndStackSize itemAndMetadata = (ItemAndMetadataAndStackSize) matchSlot; - return itemAndMetadata.transferStackSize; + public SmartFilteringMode getFilteringMode() { + return this.filterReader.getFilteringMode(); } @Override - public Object matchItemStack(ItemStack itemStack) { - ItemAndMetadata itemAndMetadata = new ItemAndMetadata(itemStack); - Integer cachedTransferRateValue = filteringMode.transferStackSizesCache.get(itemAndMetadata); + public int getTransferLimit(ItemStack stack, int globalTransferLimit) { + ItemAndMetadata itemAndMetadata = new ItemAndMetadata(stack); + var filterMode = this.filterReader.getFilteringMode(); + int cachedTransferRateValue = filterMode.transferStackSizesCache.getOrDefault(itemAndMetadata, -1); - if (cachedTransferRateValue == null) { - ItemStack infinitelyBigStack = itemStack.copy(); + if (cachedTransferRateValue == -1) { + ItemStack infinitelyBigStack = stack.copy(); infinitelyBigStack.setCount(Integer.MAX_VALUE); - Recipe recipe = filteringMode.recipeMap.findRecipe(Long.MAX_VALUE, + Recipe recipe = filterMode.recipeMap.findRecipe(Long.MAX_VALUE, Collections.singletonList(infinitelyBigStack), Collections.emptyList()); if (recipe == null) { - filteringMode.transferStackSizesCache.put(itemAndMetadata, 0); + filterMode.transferStackSizesCache.put(itemAndMetadata, 0); cachedTransferRateValue = 0; } else { GTRecipeInput inputIngredient = recipe.getInputs().iterator().next(); - filteringMode.transferStackSizesCache.put(itemAndMetadata, inputIngredient.getAmount()); + filterMode.transferStackSizesCache.put(itemAndMetadata, inputIngredient.getAmount()); cachedTransferRateValue = inputIngredient.getAmount(); } } - if (cachedTransferRateValue == 0) { - return null; - } - return new ItemAndMetadataAndStackSize(itemAndMetadata, cachedTransferRateValue); + return cachedTransferRateValue; + } + + @Override + public MatchResult matchItem(ItemStack itemStack) { + var stack = itemStack.copy(); + stack.setCount(getTransferLimit(itemStack, Integer.MAX_VALUE)); + return MatchResult.create(stack.getCount() > 0 != isBlacklistFilter(), stack, + this.getFilteringMode().ordinal()); + } + + @Override + public boolean testItem(ItemStack toTest) { + return getTransferLimit(toTest, Integer.MAX_VALUE) > 0; } @Override - public void initUI(Consumer widgetGroup) { + public FilterType getType() { + return FilterType.ITEM; + } + + @Override + public void initUI(Consumer widgetGroup) { widgetGroup.accept(new CycleButtonWidget(10, 0, 75, 20, - SmartFilteringMode.class, this::getFilteringMode, this::setFilteringMode) + SmartFilteringMode.class, filterReader::getFilteringMode, filterReader::setFilteringMode) .setTooltipHoverString("cover.smart_item_filter.filtering_mode.description")); } @Override - public int getTotalOccupiedHeight() { - return 20; + public @NotNull ModularPanel createPopupPanel(GuiSyncManager syncManager) { + return GTGuis.createPopupPanel("smart_item_filter", 98 + 27, 81) + .child(CoverWithUI.createTitleRow(getContainerStack())) + .child(createWidgets(syncManager).top(22).left(4)); } @Override - public boolean showGlobalTransferLimitSlider() { - return true; + public @NotNull ModularPanel createPanel(GuiSyncManager syncManager) { + return GTGuis.createPanel("smart_item_filter", 100, 100).padding(7); } @Override - public void writeToNBT(NBTTagCompound tagCompound) { - tagCompound.setInteger("FilterMode", filteringMode.ordinal()); + public @NotNull Widget createWidgets(GuiSyncManager syncManager) { + var filterMode = new EnumSyncValue<>(SmartFilteringMode.class, filterReader::getFilteringMode, + filterReader::setFilteringMode); + syncManager.syncValue("filter_mode", filterMode); + + return new Row().coverChildren() + .child(new Column().coverChildren().marginRight(4) + .child(createFilterModeButton(filterMode, SmartFilteringMode.ELECTROLYZER)) + .child(createFilterModeButton(filterMode, SmartFilteringMode.CENTRIFUGE)) + .child(createFilterModeButton(filterMode, SmartFilteringMode.SIFTER))) + .child(createBlacklistUI()); + } + + private Widget createFilterModeButton(EnumSyncValue value, + SmartFilteringMode mode) { + return new ToggleButton().height(18).width(18 * 5) + .value(boolValueOf(value, mode)) + .background(GTGuiTextures.MC_BUTTON) + .selectedBackground(GTGuiTextures.MC_BUTTON_DISABLED) + .overlay(IKey.lang(mode.getName()).color(Color.WHITE.darker(1))); + } + + protected > BoolValue.Dynamic boolValueOf(EnumSyncValue syncValue, T value) { + return new BoolValue.Dynamic(() -> syncValue.getValue() == value, $ -> syncValue.setValue(value)); } @Override - public void readFromNBT(NBTTagCompound tagCompound) { - this.filteringMode = SmartFilteringMode.values()[tagCompound.getInteger("FilterMode")]; + public boolean showGlobalTransferLimitSlider() { + return true; } private static class ItemAndMetadataAndStackSize { @@ -122,7 +171,8 @@ public enum SmartFilteringMode implements IStringSerializable { CENTRIFUGE("cover.smart_item_filter.filtering_mode.centrifuge", RecipeMaps.CENTRIFUGE_RECIPES), SIFTER("cover.smart_item_filter.filtering_mode.sifter", RecipeMaps.SIFTER_RECIPES); - private final Map transferStackSizesCache = new Object2IntOpenHashMap<>(); + public static final SmartFilteringMode[] VALUES = values(); + private final Object2IntOpenHashMap transferStackSizesCache = new Object2IntOpenHashMap<>(); public final String localeName; public final RecipeMap recipeMap; diff --git a/src/main/java/gregtech/common/covers/filter/WidgetGroupFluidFilter.java b/src/main/java/gregtech/common/covers/filter/WidgetGroupFluidFilter.java index f2c08f856b3..c43d7487467 100644 --- a/src/main/java/gregtech/common/covers/filter/WidgetGroupFluidFilter.java +++ b/src/main/java/gregtech/common/covers/filter/WidgetGroupFluidFilter.java @@ -1,19 +1,29 @@ package gregtech.common.covers.filter; import gregtech.api.gui.widgets.AbstractWidgetGroup; +import gregtech.api.util.GTLog; import gregtech.api.util.Position; +import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; +import org.jetbrains.annotations.ApiStatus; + +import java.io.IOException; import java.util.function.Supplier; +/** + * @deprecated in favor of new MUI + */ +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.10") public class WidgetGroupFluidFilter extends AbstractWidgetGroup { - private final Supplier fluidFilterSupplier; + private final Supplier fluidFilterSupplier; private final Supplier showTipSupplier; - private FluidFilter fluidFilter; + private BaseFilter fluidFilter; - public WidgetGroupFluidFilter(int yPosition, Supplier fluidFilterSupplier, + public WidgetGroupFluidFilter(int yPosition, Supplier fluidFilterSupplier, Supplier showTipSupplier) { super(new Position(18 + 5, yPosition)); this.fluidFilterSupplier = fluidFilterSupplier; @@ -23,7 +33,7 @@ public WidgetGroupFluidFilter(int yPosition, Supplier fluidFilterSu @Override public void detectAndSendChanges() { super.detectAndSendChanges(); - FluidFilter newFluidFilter = fluidFilterSupplier.get(); + BaseFilter newFluidFilter = fluidFilterSupplier.get(); if (fluidFilter != newFluidFilter) { clearAllWidgets(); this.fluidFilter = newFluidFilter; @@ -33,17 +43,16 @@ public void detectAndSendChanges() { writeUpdateInfo(2, buffer -> { if (fluidFilter != null) { buffer.writeBoolean(true); - int filterId = FilterTypeRegistry.getIdForFluidFilter(fluidFilter); - buffer.writeVarInt(filterId); + buffer.writeItemStack(fluidFilter.getContainerStack()); } else { buffer.writeBoolean(false); } }); } - if (fluidFilter != null && showTipSupplier != null && fluidFilter.showTip != showTipSupplier.get()) { - fluidFilter.showTip = showTipSupplier.get(); - writeUpdateInfo(3, buffer -> buffer.writeBoolean(fluidFilter.showTip)); - } + // if (fluidFilter != null && showTipSupplier != null && fluidFilter.showTip != showTipSupplier.get()) { + // fluidFilter.showTip = showTipSupplier.get(); + // writeUpdateInfo(3, buffer -> buffer.writeBoolean(fluidFilter.showTip)); + // } } @Override @@ -52,12 +61,18 @@ public void readUpdateInfo(int id, PacketBuffer buffer) { if (id == 2) { clearAllWidgets(); if (buffer.readBoolean()) { - int filterId = buffer.readVarInt(); - this.fluidFilter = FilterTypeRegistry.createFluidFilterById(filterId); + ItemStack stack; + try { + stack = buffer.readItemStack(); + } catch (IOException e) { + GTLog.logger.warn(e); + return; + } + this.fluidFilter = BaseFilter.getFilterFromStack(stack); this.fluidFilter.initUI(this::addWidget); } } else if (id == 3) { - fluidFilter.showTip = buffer.readBoolean(); + // fluidFilter.showTip = buffer.readBoolean(); } } } diff --git a/src/main/java/gregtech/common/covers/filter/WidgetGroupItemFilter.java b/src/main/java/gregtech/common/covers/filter/WidgetGroupItemFilter.java index d5601f2b2ab..9f26302fb2f 100644 --- a/src/main/java/gregtech/common/covers/filter/WidgetGroupItemFilter.java +++ b/src/main/java/gregtech/common/covers/filter/WidgetGroupItemFilter.java @@ -5,15 +5,23 @@ import net.minecraft.network.PacketBuffer; +import org.jetbrains.annotations.ApiStatus; + +import java.io.IOException; import java.util.function.Supplier; +/** + * @deprecated in favor of new MUI + */ +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.10") public class WidgetGroupItemFilter extends AbstractWidgetGroup { - private final Supplier itemFilterSupplier; - private ItemFilter itemFilter; + private final Supplier itemFilterSupplier; + private BaseFilter itemFilter; private int maxStackSize = 1; - public WidgetGroupItemFilter(int yPosition, Supplier itemFilterSupplier) { + public WidgetGroupItemFilter(int yPosition, Supplier itemFilterSupplier) { super(new Position(0, yPosition)); this.itemFilterSupplier = itemFilterSupplier; } @@ -21,7 +29,7 @@ public WidgetGroupItemFilter(int yPosition, Supplier itemFilterSuppl @Override public void detectAndSendChanges() { super.detectAndSendChanges(); - ItemFilter newItemFilter = itemFilterSupplier.get(); + BaseFilter newItemFilter = itemFilterSupplier.get(); if (itemFilter != newItemFilter) { clearAllWidgets(); this.itemFilter = newItemFilter; @@ -31,14 +39,13 @@ public void detectAndSendChanges() { writeUpdateInfo(2, buffer -> { if (itemFilter != null) { buffer.writeBoolean(true); - int filterId = FilterTypeRegistry.getIdForItemFilter(itemFilter); - buffer.writeVarInt(filterId); + buffer.writeItemStack(itemFilter.getContainerStack()); } else { buffer.writeBoolean(false); } }); } - int newMaxStackSize = itemFilter == null ? 1 : itemFilter.getMaxStackSize(); + int newMaxStackSize = itemFilter == null ? 1 : itemFilter.getMaxTransferSize(); if (maxStackSize != newMaxStackSize) { this.maxStackSize = newMaxStackSize; writeUpdateInfo(3, buffer -> buffer.writeVarInt(maxStackSize)); @@ -51,15 +58,19 @@ public void readUpdateInfo(int id, PacketBuffer buffer) { if (id == 2) { clearAllWidgets(); if (buffer.readBoolean()) { - int filterId = buffer.readVarInt(); - this.itemFilter = FilterTypeRegistry.createItemFilterById(filterId); - this.itemFilter.initUI(this::addWidget); - this.itemFilter.setMaxStackSize(maxStackSize); + // int filterId = buffer.readVarInt(); + try { + this.itemFilter = BaseFilter.getFilterFromStack(buffer.readItemStack()); + this.itemFilter.initUI(this::addWidget); + this.itemFilter.setMaxTransferSize(maxStackSize); + } catch (IOException e) { + throw new RuntimeException(e); + } } } else if (id == 3) { this.maxStackSize = buffer.readVarInt(); if (itemFilter != null) { - itemFilter.setMaxStackSize(maxStackSize); + itemFilter.setMaxTransferSize(maxStackSize); } } } diff --git a/src/main/java/gregtech/common/covers/filter/readers/BaseFilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/BaseFilterReader.java new file mode 100644 index 00000000000..eee6a16a52a --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/BaseFilterReader.java @@ -0,0 +1,124 @@ +package gregtech.common.covers.filter.readers; + +import gregtech.api.util.IDirtyNotifiable; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.common.util.INBTSerializable; + +import org.jetbrains.annotations.NotNull; + +public class BaseFilterReader implements FilterReader, INBTSerializable { + + protected ItemStack container; + private IDirtyNotifiable dirtyNotifiable; + private final int size; + private int maxTransferRate = 1; + protected static final String BLACKLIST = "IsBlacklist"; + protected static final String FILTER_CONTENTS = "FilterSlots"; + protected static final String KEY_LEGACY_FILTER = "Filter"; + + public BaseFilterReader(ItemStack container, int slots) { + this.container = container; + this.size = slots; + } + + @Override + public ItemStack getContainer() { + return this.container; + } + + @Override + public void readStack(@NotNull ItemStack stack) { + this.container = stack; + } + + public @NotNull NBTTagList getInventoryNbt() { + var nbt = getStackTag(); + if (!nbt.hasKey(FILTER_CONTENTS)) { + NBTTagList list = new NBTTagList(); + for (int i = 0; i < getSize(); i++) { + list.appendTag(new NBTTagCompound()); + } + nbt.setTag(FILTER_CONTENTS, list); + } + return nbt.getTagList(FILTER_CONTENTS, Constants.NBT.TAG_COMPOUND); + } + + public @NotNull NBTTagCompound getStackTag() { + NBTTagCompound nbt = this.container.getTagCompound(); + if (nbt == null) { + nbt = new NBTTagCompound(); + this.container.setTagCompound(nbt); + } + return nbt; + } + + @Override + public int getSize() { + return this.size; + } + + public final void setDirtyNotifiable(IDirtyNotifiable dirtyNotifiable) { + this.dirtyNotifiable = dirtyNotifiable; + } + + public final void markDirty() { + if (dirtyNotifiable != null) { + dirtyNotifiable.markAsDirty(); + } + } + + public void onTransferRateChange() {} + + public final void setBlacklistFilter(boolean blacklistFilter) { + if (getStackTag().getBoolean(BLACKLIST) != blacklistFilter) { + if (blacklistFilter) + getStackTag().setBoolean(BLACKLIST, true); + else + getStackTag().removeTag(BLACKLIST); + onTransferRateChange(); + markDirty(); + } + } + + public final boolean isBlacklistFilter() { + return getStackTag().getBoolean(BLACKLIST); + } + + public void setMaxTransferRate(int transferRate) { + transferRate = MathHelper.clamp(transferRate, 1, Integer.MAX_VALUE); + if (this.maxTransferRate != transferRate) { + this.maxTransferRate = transferRate; + onTransferRateChange(); + } + } + + public int getMaxTransferRate() { + return isBlacklistFilter() ? 1 : this.maxTransferRate; + } + + @Override + public boolean validateSlotIndex(int slot) { + return slot >= 0 && slot < getSize(); + } + + @Override + public NBTTagCompound serializeNBT() { + return getStackTag(); + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + if (nbt.hasKey(BLACKLIST)) + setBlacklistFilter(nbt.getBoolean(BLACKLIST)); + } + + public void handleLegacyNBT(NBTTagCompound tag) { + if (tag.hasKey(BLACKLIST)) + setBlacklistFilter(tag.getBoolean(BLACKLIST)); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/readers/FilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/FilterReader.java new file mode 100644 index 00000000000..34efe945268 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/FilterReader.java @@ -0,0 +1,32 @@ +package gregtech.common.covers.filter.readers; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + +import org.jetbrains.annotations.NotNull; + +public interface FilterReader { + + ItemStack getContainer(); + + void readStack(ItemStack stack); + + @NotNull + NBTTagList getInventoryNbt(); + + @NotNull + NBTTagCompound getStackTag(); + + int getSize(); + + boolean validateSlotIndex(int slot); + + @NotNull + default NBTTagCompound getTagAt(int i) { + if (validateSlotIndex(i)) { + return getInventoryNbt().getCompoundTagAt(i); + } + return new NBTTagCompound(); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/readers/OreDictFilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/OreDictFilterReader.java new file mode 100644 index 00000000000..070ec7fe764 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/OreDictFilterReader.java @@ -0,0 +1,123 @@ +package gregtech.common.covers.filter.readers; + +import gregtech.api.util.oreglob.OreGlob; +import gregtech.api.util.oreglob.OreGlobCompileResult; +import gregtech.common.covers.filter.oreglob.impl.ImpossibleOreGlob; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import org.jetbrains.annotations.NotNull; + +public class OreDictFilterReader extends SimpleItemFilterReader { + + private static final String EXPRESSION = "OreDictionaryFilter"; + private static final String CASE_SENSITIVE = "caseSensitive"; + private static final String MATCH_ALL = "matchAll"; + + private OreGlob glob = ImpossibleOreGlob.getInstance(); + private OreGlobCompileResult result; + + public OreDictFilterReader(ItemStack container) { + super(container, 0); + } + + public void setExpression(String expression) { + if (getStackTag().getString(EXPRESSION).equals(expression)) + return; + + getStackTag().setString(EXPRESSION, expression); + recompile(); + markDirty(); + } + + public String getExpression() { + return getStackTag().getString(EXPRESSION); + } + + public void setCaseSensitive(boolean caseSensitive) { + if (isCaseSensitive() == caseSensitive) + return; + + if (!caseSensitive) + getStackTag().setBoolean(CASE_SENSITIVE, false); + else + getStackTag().removeTag(CASE_SENSITIVE); + recompile(); + markDirty(); + } + + public boolean isCaseSensitive() { + return !getStackTag().hasKey(CASE_SENSITIVE); + } + + public void setMatchAll(boolean matchAll) { + if (shouldMatchAll() == matchAll) + return; + + if (!matchAll) + getStackTag().setBoolean(MATCH_ALL, false); + else + getStackTag().removeTag(MATCH_ALL); + + markDirty(); + } + + /** + * {@code false} requires any of the entry to be match in order for the match to be success, {@code true} + * requires + * all entries to match + */ + public boolean shouldMatchAll() { + return !getStackTag().hasKey(MATCH_ALL); + } + + @NotNull + public OreGlob getGlob() { + return this.glob; + } + + public OreGlobCompileResult getResult() { + return this.result; + } + + public void recompile() { + String expr = getExpression(); + if (!expr.isEmpty()) { + result = OreGlob.compile(expr, !isCaseSensitive()); + this.glob = result.getInstance(); + } else { + this.glob = ImpossibleOreGlob.getInstance(); + result = null; + } + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt); + + if (nbt.hasKey(EXPRESSION)) + this.setExpression(nbt.getString(EXPRESSION)); + + if (nbt.hasKey(CASE_SENSITIVE)) + this.setCaseSensitive(nbt.getBoolean(CASE_SENSITIVE)); + + if (nbt.hasKey(MATCH_ALL)) + this.setMatchAll(nbt.getBoolean(MATCH_ALL)); + } + + @Override + public void handleLegacyNBT(NBTTagCompound tag) { + super.handleLegacyNBT(tag); + + var legacyFilter = tag.getCompoundTag(KEY_LEGACY_FILTER); + if (legacyFilter.hasKey(EXPRESSION)) + this.setExpression(legacyFilter.getString(EXPRESSION)); + + if (legacyFilter.hasKey(CASE_SENSITIVE)) + this.setCaseSensitive(legacyFilter.getBoolean(CASE_SENSITIVE)); + + if (legacyFilter.hasKey(MATCH_ALL)) + this.setMatchAll(legacyFilter.getBoolean(MATCH_ALL)); + } +} diff --git a/src/main/java/gregtech/common/covers/filter/readers/SimpleFluidFilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/SimpleFluidFilterReader.java new file mode 100644 index 00000000000..ea38dafd569 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/SimpleFluidFilterReader.java @@ -0,0 +1,181 @@ +package gregtech.common.covers.filter.readers; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; + +import org.jetbrains.annotations.Nullable; + +public class SimpleFluidFilterReader extends BaseFilterReader { + + protected WritableFluidTank[] fluidTanks; + protected static final String CAPACITY = "Capacity"; + + protected static final String LEGACY_FLUIDFILTER_KEY = "FluidFilter"; + + public SimpleFluidFilterReader(ItemStack container, int slots) { + super(container, slots); + fluidTanks = new WritableFluidTank[slots]; + for (int i = 0; i < fluidTanks.length; i++) { + fluidTanks[i] = new WritableFluidTank(this, getInventoryNbt().getCompoundTagAt(i)); + } + setCapacity(getStackTag().hasKey(CAPACITY) ? getCapacity() : 1000); + } + + public final boolean shouldShowAmount() { + return getMaxTransferRate() > 1; + } + + @Nullable + public FluidStack getFluidStack(int i) { + return getFluidTank(i).getFluid(); + } + + public void setCapacity(int capacity) { + getStackTag().setInteger(CAPACITY, capacity); + markDirty(); + } + + public int getCapacity() { + return getStackTag().getInteger(CAPACITY); + } + + public WritableFluidTank getFluidTank(int i) { + return fluidTanks[i]; + } + + public void setFluidAmounts(int amount) { + for (int i = 0; i < getSize(); i++) { + getFluidTank(i).setFluidAmount(amount); + } + } + + @Override + public void onTransferRateChange() { + for (int i = 0; i < getSize(); i++) { + var stack = getFluidStack(i); + if (stack == null) continue; + getFluidTank(i).setFluidAmount(Math.min(stack.amount, getMaxTransferRate())); + } + setCapacity(getMaxTransferRate()); + } + + @Override + public void handleLegacyNBT(NBTTagCompound tag) { + super.handleLegacyNBT(tag); + NBTTagCompound legacyFilter = tag.getCompoundTag(KEY_LEGACY_FILTER); + + NBTTagList filterSlots = legacyFilter.getTagList(LEGACY_FLUIDFILTER_KEY, Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < filterSlots.tagCount(); i++) { + NBTTagCompound stackTag = filterSlots.getCompoundTagAt(i); + FluidStack fluidStack = FluidStack.loadFluidStackFromNBT(stackTag); + if (fluidStack == null) continue; + int slot = stackTag.getInteger("Slot"); + getFluidTank(slot).setFluid(fluidStack); + } + } + + public class WritableFluidTank extends FluidTank { + + private final NBTTagCompound fluidTank; + private final SimpleFluidFilterReader filterReader; + protected static final String FLUID_AMOUNT = "Amount"; + protected static final String FLUID = "Fluid"; + protected static final String EMPTY = "Empty"; + + protected WritableFluidTank(SimpleFluidFilterReader filterReader, NBTTagCompound fluidTank) { + super(0); + this.filterReader = filterReader; + this.fluidTank = fluidTank; + } + + public void setFluidAmount(int amount) { + if (amount <= 0) { + setFluid(null); + } else if (this.fluidTank.hasKey(FLUID)) { + this.fluidTank + .getCompoundTag(FLUID) + .setInteger(FLUID_AMOUNT, amount); + markDirty(); + } + } + + public boolean isEmpty() { + return !this.fluidTank.hasKey(FLUID); + } + + protected @Nullable NBTTagCompound getFluidTag() { + if (isEmpty()) { + return null; + } + + return this.fluidTank.getCompoundTag(FLUID); + } + + @Override + public @Nullable FluidStack getFluid() { + return FluidStack.loadFluidStackFromNBT(getFluidTag()); + } + + @Override + public void setFluid(@Nullable FluidStack stack) { + if (stack == null) { + this.fluidTank.removeTag(FLUID); + } else { + this.fluidTank.setTag(FLUID, stack.writeToNBT(new NBTTagCompound())); + } + markDirty(); + } + + public boolean showAmount() { + return this.filterReader.shouldShowAmount(); + } + + @Override + public int getFluidAmount() { + return this.fluidTank + .getCompoundTag(FLUID) + .getInteger(FLUID_AMOUNT); + } + + @Override + public int getCapacity() { + return this.filterReader.getCapacity(); + } + + // getFluid() is checked for nullability, suppress + @SuppressWarnings("DataFlowIssue") + @Override + public int fill(FluidStack resource, boolean doFill) { + if (isEmpty() || !getFluid().isFluidEqual(resource)) { + setFluid(resource); + if (!showAmount()) setFluidAmount(1); + return resource.amount; + } else if (showAmount()) { + var fluid = getFluid(); + int accepted = Math.min(resource.amount, getCapacity() - fluid.amount); + fluid.amount += accepted; + setFluid(fluid); + return accepted; + } + return 0; + } + + // getFluid() is checked for nullability, suppress + @SuppressWarnings("DataFlowIssue") + @Override + public FluidStack drain(int maxDrain, boolean doDrain) { + if (isEmpty()) return null; + FluidStack fluid = getFluid(); + + fluid.amount -= Math.min(fluid.amount, maxDrain); + + setFluidAmount(fluid.amount); + markDirty(); + return fluid; + } + } +} diff --git a/src/main/java/gregtech/common/covers/filter/readers/SimpleItemFilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/SimpleItemFilterReader.java new file mode 100644 index 00000000000..7e9ea677b3e --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/SimpleItemFilterReader.java @@ -0,0 +1,193 @@ +package gregtech.common.covers.filter.readers; + +import gregtech.api.util.GTUtility; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; + +import org.jetbrains.annotations.NotNull; + +public class SimpleItemFilterReader extends BaseFilterReader implements IItemHandlerModifiable { + + public static final String COUNT = "Count"; + protected static final String LEGACY_ITEM_KEY = "ItemFilter"; + protected static final String LEGACY_STACK_SIZE = "BigStackSize"; + public static final String RESPECT_NBT = "IgnoreNBT"; + public static final String RESPECT_DAMAGE = "IgnoreDamage"; + + public SimpleItemFilterReader(ItemStack container, int slots) { + super(container, slots); + } + + public void setIgnoreDamage(boolean ignoreDamage) { + if (!getStackTag().getBoolean(RESPECT_DAMAGE) == ignoreDamage) + return; + + if (ignoreDamage) + getStackTag().removeTag(RESPECT_DAMAGE); + else + getStackTag().setBoolean(RESPECT_DAMAGE, true); + markDirty(); + } + + @Override + public int getSlots() { + return getSize(); + } + + public void setIgnoreNBT(boolean ignoreNBT) { + if (!getStackTag().getBoolean(RESPECT_NBT) == ignoreNBT) + return; + + if (ignoreNBT) + getStackTag().removeTag(RESPECT_NBT); + else + getStackTag().setBoolean(RESPECT_NBT, true); + markDirty(); + } + + public boolean isIgnoreDamage() { + return !getStackTag().getBoolean(RESPECT_DAMAGE); + } + + public boolean isIgnoreNBT() { + return !getStackTag().getBoolean(RESPECT_NBT); + } + + @Override + public int getSlotLimit(int slot) { + return getMaxTransferRate(); + } + + @NotNull + @Override + public ItemStack getStackInSlot(int slot) { + if (validateSlotIndex(slot)) { + NBTTagCompound item = getTagAt(slot); + return item.isEmpty() ? ItemStack.EMPTY : new ItemStack(item); + } + return ItemStack.EMPTY; + } + + @Override + public void setStackInSlot(int slot, ItemStack stack) { + if (validateSlotIndex(slot)) { + if (!stack.isEmpty()) { + stack.setCount(Math.min(stack.getCount(), isBlacklistFilter() ? 1 : getMaxTransferRate())); + } + NBTTagList list = getInventoryNbt(); + list.set(slot, stack.isEmpty() ? new NBTTagCompound() : stack.serializeNBT()); + } + } + + @NotNull + @Override + public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + if (stack.isEmpty()) return stack; + ItemStack existing = getStackInSlot(slot); + + int limit = getStackLimit(slot, stack); + + if (!existing.isEmpty()) { + if (!ItemHandlerHelper.canItemStacksStack(stack, existing)) + return stack; + + limit -= existing.getCount(); + } + + if (limit <= 0) return stack; + + boolean reachedLimit = stack.getCount() > limit; + + if (!simulate) { + if (existing.isEmpty()) { + setStackInSlot(slot, reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, limit) : stack); + } else { + existing.grow(reachedLimit ? limit : stack.getCount()); + setStackInSlot(slot, existing); + } + } + + return reachedLimit ? GTUtility.copy(stack.getCount() - limit, stack) : ItemStack.EMPTY; + } + + @NotNull + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (amount == 0) return ItemStack.EMPTY; + + ItemStack existing = getStackInSlot(slot); + if (existing.isEmpty()) return ItemStack.EMPTY; + + int toExtract = Math.min(amount, existing.getMaxStackSize()); + + if (existing.getCount() <= toExtract) { + if (!simulate) { + setStackInSlot(slot, ItemStack.EMPTY); + } + return existing; + } else { + if (!simulate) { + setStackInSlot(slot, ItemHandlerHelper.copyStackWithSize(existing, existing.getCount() - toExtract)); + } + + return GTUtility.copy(toExtract, existing); + } + } + + protected int getStackLimit(int slot, @NotNull ItemStack stack) { + return Math.min(getSlotLimit(slot), stack.getMaxStackSize()); + } + + @Override + public void onTransferRateChange() { + for (int i = 0; i < getSlots(); i++) { + ItemStack itemStack = getStackInSlot(i); + if (!itemStack.isEmpty()) { + itemStack.setCount(Math.min(itemStack.getCount(), isBlacklistFilter() ? 1 : getMaxTransferRate())); + setStackInSlot(i, itemStack); + } + } + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt); + + if (nbt.hasKey(RESPECT_DAMAGE)) + this.setIgnoreDamage(nbt.getBoolean(RESPECT_DAMAGE)); + + if (nbt.hasKey(RESPECT_NBT)) + this.setIgnoreNBT(nbt.getBoolean(RESPECT_NBT)); + } + + @Override + public void handleLegacyNBT(NBTTagCompound tag) { + super.handleLegacyNBT(tag); + NBTTagCompound legacyFilter = tag.getCompoundTag(KEY_LEGACY_FILTER); + + if (legacyFilter.hasKey(LEGACY_ITEM_KEY)) { + var temp = new ItemStackHandler(); + var legacyTag = legacyFilter.getCompoundTag(LEGACY_ITEM_KEY); + var stackSizes = legacyTag.getCompoundTag(LEGACY_STACK_SIZE); + + temp.deserializeNBT(legacyTag); + for (int i = 0; i < temp.getSlots(); i++) { + var stack = temp.getStackInSlot(i); + if (stack.isEmpty()) + continue; + + if (stackSizes.hasKey(String.valueOf(i))) + stack.setCount(stackSizes.getInteger(String.valueOf(i))); + + var stackTag = stack.serializeNBT(); + stackTag.setInteger(COUNT, stack.getCount()); + getInventoryNbt().set(i, stackTag); + } + } + } +} diff --git a/src/main/java/gregtech/common/covers/filter/readers/SmartItemFilterReader.java b/src/main/java/gregtech/common/covers/filter/readers/SmartItemFilterReader.java new file mode 100644 index 00000000000..ca96ed549c2 --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/readers/SmartItemFilterReader.java @@ -0,0 +1,40 @@ +package gregtech.common.covers.filter.readers; + +import gregtech.common.covers.filter.SmartItemFilter; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +public class SmartItemFilterReader extends SimpleItemFilterReader { + + private static final String FILTER_MODE = "FilterMode"; + + public SmartItemFilterReader(ItemStack container) { + super(container, 0); + } + + public SmartItemFilter.SmartFilteringMode getFilteringMode() { + if (!getStackTag().hasKey(FILTER_MODE)) + setFilteringMode(SmartItemFilter.SmartFilteringMode.ELECTROLYZER); + + return SmartItemFilter.SmartFilteringMode.VALUES[getStackTag().getInteger(FILTER_MODE)]; + } + + public void setFilteringMode(SmartItemFilter.SmartFilteringMode filteringMode) { + getStackTag().setInteger(FILTER_MODE, filteringMode.ordinal()); + markDirty(); + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt); + this.setFilteringMode(SmartItemFilter.SmartFilteringMode.VALUES[nbt.getInteger(FILTER_MODE)]); + } + + @Override + public void handleLegacyNBT(NBTTagCompound tag) { + super.handleLegacyNBT(tag); + var legacyFilter = tag.getCompoundTag(KEY_LEGACY_FILTER); + this.setFilteringMode(SmartItemFilter.SmartFilteringMode.VALUES[legacyFilter.getInteger(FILTER_MODE)]); + } +} diff --git a/src/main/java/gregtech/common/gui/widget/HighlightedTextField.java b/src/main/java/gregtech/common/gui/widget/HighlightedTextField.java deleted file mode 100644 index 8acea5527f7..00000000000 --- a/src/main/java/gregtech/common/gui/widget/HighlightedTextField.java +++ /dev/null @@ -1,127 +0,0 @@ -package gregtech.common.gui.widget; - -import gregtech.api.gui.widgets.TextFieldWidget2; - -import net.minecraft.util.text.TextFormatting; - -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; -import java.util.function.Supplier; - -public class HighlightedTextField extends TextFieldWidget2 { - - @Nullable - private Consumer highlightRule; - @Nullable - private TextHighlighter formatResult; - - public HighlightedTextField(int x, int y, int width, int height, Supplier supplier, - Consumer setter) { - super(x, y, width, height, supplier, setter); - } - - /** - * Text highlighter applied only in rendering text. Only formatting characters can be inserted. - * - * @param highlightRule Consumer for text highlighter - * @return This - */ - public HighlightedTextField setHighlightRule(Consumer highlightRule) { - this.highlightRule = highlightRule; - return this; - } - - @Override - public void setText(String text) { - super.setText(text); - this.formatResult = null; - } - - @Override - protected String getRenderText() { - if (this.formatResult == null) { - if (this.highlightRule == null) { - return getText(); - } - TextHighlighter highlighter = new TextHighlighter(getText()); - this.highlightRule.accept(highlighter); - this.formatResult = highlighter; - return highlighter.getFormattedText(); - } - return this.formatResult.getFormattedText(); - } - - @Override - protected int toOriginalTextIndex(int renderTextIndex) { - return formatResult != null ? formatResult.toOriginalTextIndex(renderTextIndex) : renderTextIndex; - } - - @Override - protected int toRenderTextIndex(int originalTextIndex) { - return formatResult != null ? formatResult.toFormattedTextIndex(originalTextIndex) : originalTextIndex; - } - - public static final class TextHighlighter { - - private final String originalText; - private final StringBuilder formattedTextBuilder; - - private final IntList formatOriginalIndices = new IntArrayList(); - - @Nullable - private String formattedTextCache; - - public TextHighlighter(String originalText) { - this.originalText = originalText; - this.formattedTextBuilder = new StringBuilder(originalText); - } - - public String getOriginalText() { - return this.originalText; - } - - public String getFormattedText() { - if (this.formattedTextCache == null) { - return this.formattedTextCache = this.formattedTextBuilder.toString(); - } - return this.formattedTextCache; - } - - public int toFormattedTextIndex(int originalTextIndex) { - int i = 0; - for (; i < formatOriginalIndices.size(); i++) { - if (formatOriginalIndices.getInt(i) > originalTextIndex) { - break; - } - } - return originalTextIndex + i * 2; - } - - public int toOriginalTextIndex(int formattedTextIndex) { - int i = 0; - for (; i < formatOriginalIndices.size(); i++) { - if (formatOriginalIndices.getInt(i) + i * 2 >= formattedTextIndex) { - break; - } - } - return formattedTextIndex - i * 2; - } - - public void format(int index, TextFormatting format) { - if (index < 0) index = 0; - else if (index > originalText.length()) return; - formattedTextBuilder.insert(toFormattedTextIndex(index), format.toString()); - formattedTextCache = null; - for (int i = 0; i < formatOriginalIndices.size(); i++) { - if (formatOriginalIndices.getInt(i) > index) { - formatOriginalIndices.add(i, index); - return; - } - } - formatOriginalIndices.add(index); - } - } -} diff --git a/src/main/java/gregtech/common/gui/widget/orefilter/ItemOreFilterTestSlot.java b/src/main/java/gregtech/common/gui/widget/orefilter/ItemOreFilterTestSlot.java deleted file mode 100644 index b30a48cd25d..00000000000 --- a/src/main/java/gregtech/common/gui/widget/orefilter/ItemOreFilterTestSlot.java +++ /dev/null @@ -1,111 +0,0 @@ -package gregtech.common.gui.widget.orefilter; - -import gregtech.api.gui.IRenderContext; -import gregtech.api.gui.ingredient.IGhostIngredientTarget; -import gregtech.api.unification.OreDictUnifier; -import gregtech.api.util.Position; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.RenderItem; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import com.google.common.collect.Lists; -import mezz.jei.api.gui.IGhostIngredientHandler; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.awt.*; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -public class ItemOreFilterTestSlot extends OreFilterTestSlot implements IGhostIngredientTarget { - - @NotNull - private ItemStack testStack = ItemStack.EMPTY; - - public ItemOreFilterTestSlot(int xPosition, int yPosition) { - super(xPosition, yPosition); - } - - @NotNull - public ItemStack getTestStack() { - return testStack; - } - - public void setTestStack(@NotNull ItemStack testStack) { - this.testStack = testStack; - updatePreview(); - } - - @Nullable - @Override - protected Set getTestCandidates() { - return this.testStack.isEmpty() ? null : OreDictUnifier.getOreDictionaryNames(this.testStack); - } - - @Override - protected void renderSlotContents(float partialTicks, IRenderContext context) { - Position pos = getPosition(); - if (!testStack.isEmpty()) { - GlStateManager.enableDepth(); - RenderHelper.enableGUIStandardItemLighting(); - GlStateManager.pushMatrix(); - RenderItem itemRender = Minecraft.getMinecraft().getRenderItem(); - itemRender.renderItemAndEffectIntoGUI(testStack, pos.x + 1, pos.y + 1); - itemRender.renderItemOverlayIntoGUI(Minecraft.getMinecraft().fontRenderer, testStack, pos.x + 1, pos.y + 1, - null); - GlStateManager.popMatrix(); - RenderHelper.disableStandardItemLighting(); - } - } - - @Override - @SideOnly(Side.CLIENT) - public boolean mouseClicked(int mouseX, int mouseY, int button) { - if (isMouseOverElement(mouseX, mouseY)) { - EntityPlayer player = Minecraft.getMinecraft().player; - putItem(player.inventory.getItemStack()); - return true; - } - return false; - } - - private void putItem(ItemStack stack) { - ItemStack testStack = getTestStack(); - if ((stack.isEmpty() ^ testStack.isEmpty()) || !testStack.isItemEqual(stack) || - !ItemStack.areItemStackTagsEqual(testStack, stack)) { - ItemStack copy = stack.copy(); - copy.setCount(1); - setTestStack(copy); - } - } - - @Override - public List> getPhantomTargets(Object ingredient) { - if (!(ingredient instanceof ItemStack)) { - return Collections.emptyList(); - } - Rectangle rectangle = toRectangleBox(); - return Lists.newArrayList(new IGhostIngredientHandler.Target() { - - @NotNull - @Override - public Rectangle getArea() { - return rectangle; - } - - @Override - public void accept(@NotNull Object ingredient) { - if (ingredient instanceof ItemStack) { - putItem((ItemStack) ingredient); - } - } - }); - } -} diff --git a/src/main/java/gregtech/common/gui/widget/orefilter/OreFilterTestSlot.java b/src/main/java/gregtech/common/gui/widget/orefilter/OreFilterTestSlot.java deleted file mode 100644 index fd81e80bcd7..00000000000 --- a/src/main/java/gregtech/common/gui/widget/orefilter/OreFilterTestSlot.java +++ /dev/null @@ -1,202 +0,0 @@ -package gregtech.common.gui.widget.orefilter; - -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.IRenderContext; -import gregtech.api.gui.resources.TextureArea; -import gregtech.api.gui.widgets.ImageWidget; -import gregtech.api.gui.widgets.WidgetGroup; -import gregtech.api.util.LocalizationUtils; -import gregtech.api.util.Position; -import gregtech.api.util.function.BooleanConsumer; -import gregtech.api.util.oreglob.OreGlob; - -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import it.unimi.dsi.fastutil.objects.Object2BooleanAVLTreeMap; -import it.unimi.dsi.fastutil.objects.Object2BooleanMap; -import it.unimi.dsi.fastutil.objects.Object2BooleanMaps; -import org.jetbrains.annotations.Nullable; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * @author brachy84 - */ -public abstract class OreFilterTestSlot extends WidgetGroup { - - private final ImageWidget match; - private final ImageWidget noMatch; - - @Nullable - private OreGlob glob; - private boolean expectedResult = true; - - @Nullable - private TextureArea slotIcon = GuiTextures.SLOT; - - @Nullable - private BooleanConsumer onMatchChange; - - private Object2BooleanMap testResult; - private MatchType matchType = MatchType.INVALID; - private boolean matchSuccess; - - private boolean initialized = false; - - private boolean matchAll; - - public OreFilterTestSlot(int xPosition, int yPosition) { - super(xPosition, yPosition, 18, 18); - this.match = new ImageWidget(18 - 5, -3, 9, 6, GuiTextures.ORE_FILTER_MATCH); - this.noMatch = new ImageWidget(18 - 5, -3, 7, 7, GuiTextures.ORE_FILTER_NO_MATCH); - addWidget(this.match); - addWidget(this.noMatch); - } - - @Override - public void initWidget() { - this.initialized = true; - updatePreview(); - super.initWidget(); - } - - public boolean isMatchSuccess() { - return matchSuccess; - } - - public OreFilterTestSlot setSlotIcon(@Nullable TextureArea slotIcon) { - this.slotIcon = slotIcon; - return this; - } - - public OreFilterTestSlot setExpectedResult(boolean expectedResult) { - this.expectedResult = expectedResult; - return this; - } - - public OreFilterTestSlot onMatchChange(@Nullable BooleanConsumer onMatchChange) { - this.onMatchChange = onMatchChange; - return this; - } - - public void setGlob(@Nullable OreGlob glob) { - if (this.glob == glob) return; - this.glob = glob; - updatePreview(); - } - - public void setMatchAll(boolean matchAll) { - if (this.matchAll == matchAll) return; - this.matchAll = matchAll; - updatePreview(); - } - - protected void updatePreview() { - if (!this.initialized) return; - Set oreDicts = getTestCandidates(); - if (oreDicts != null) { - OreGlob glob = this.glob; - if (oreDicts.isEmpty()) { - // no oredict entries - this.testResult = Object2BooleanMaps.singleton("", glob != null && glob.matches("")); - this.matchType = MatchType.NO_ORE_DICT_MATCH; - } else { - this.testResult = new Object2BooleanAVLTreeMap<>(); - for (String oreDict : oreDicts) { - boolean matches = glob != null && glob.matches(oreDict); - this.testResult.put(oreDict, matches); - } - this.matchType = MatchType.ORE_DICT_MATCH; - } - boolean success = this.matchAll; - for (var e : testResult.object2BooleanEntrySet()) { - boolean result = e.getBooleanValue(); - if (result == !this.matchAll) { - success = !this.matchAll; - break; - } - } - updateAndNotifyMatchSuccess(this.expectedResult == success); - this.match.setVisible(this.expectedResult == success); - this.noMatch.setVisible(this.expectedResult != success); - return; - } - this.testResult = Object2BooleanMaps.emptyMap(); - this.matchType = MatchType.INVALID; - updateAndNotifyMatchSuccess(false); - this.match.setVisible(false); - this.noMatch.setVisible(false); - } - - private void updateAndNotifyMatchSuccess(boolean newValue) { - if (this.matchSuccess == newValue) return; - this.matchSuccess = newValue; - if (this.onMatchChange != null) { - this.onMatchChange.apply(newValue); - } - } - - /** - * Get each test candidate for current state of test slot. An empty collection indicates that the match is for items - * without any ore dictionary entry. A {@code null} value indicates that the input state is invalid or empty. - * - * @return each test candidate for current state of test slot - */ - @Nullable - protected abstract Set getTestCandidates(); - - @Override - @SideOnly(Side.CLIENT) - public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { - Position pos = getPosition(); - if (this.slotIcon != null) { - this.slotIcon.draw(pos.x, pos.y, 18, 18); - } - - renderSlotContents(partialTicks, context); - - if (isActive() && isMouseOverElement(mouseX, mouseY)) { - GlStateManager.disableDepth(); - GlStateManager.colorMask(true, true, true, false); - drawSolidRect(getPosition().x + 1, getPosition().y + 1, 16, 16, 0x80ffffff); - GlStateManager.colorMask(true, true, true, true); - GlStateManager.enableBlend(); - } - - GlStateManager.disableDepth(); - super.drawInBackground(mouseX, mouseY, partialTicks, context); - GlStateManager.enableDepth(); - } - - protected abstract void renderSlotContents(float partialTicks, IRenderContext context); - - @Override - public void drawInForeground(int mouseX, int mouseY) { - if (isActive() && isMouseOverElement(mouseX, mouseY)) { - drawHoveringText(ItemStack.EMPTY, switch (this.matchType) { - case NO_ORE_DICT_MATCH -> Collections.singletonList(I18n.format(this.matchSuccess ? - "cover.ore_dictionary_filter.test_slot.no_oredict.matches" : - "cover.ore_dictionary_filter.test_slot.no_oredict.matches_not")); - case ORE_DICT_MATCH -> this.testResult.object2BooleanEntrySet().stream().map( - e -> I18n.format(e.getBooleanValue() ? - "cover.ore_dictionary_filter.test_slot.matches" : - "cover.ore_dictionary_filter.test_slot.matches_not", e.getKey())) - .collect(Collectors.toList()); - default -> Arrays.asList(LocalizationUtils.formatLines("cover.ore_dictionary_filter.test_slot.info")); - }, 300, mouseX, mouseY); - } - } - - private enum MatchType { - NO_ORE_DICT_MATCH, - ORE_DICT_MATCH, - INVALID - } -} diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index d194fedd4f5..23c6f54c761 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -26,6 +26,11 @@ import gregtech.api.util.RandomPotionEffect; import gregtech.common.ConfigHolder; import gregtech.common.blocks.MetaBlocks; +import gregtech.common.covers.filter.IFilter; +import gregtech.common.covers.filter.OreDictionaryItemFilter; +import gregtech.common.covers.filter.SimpleFluidFilter; +import gregtech.common.covers.filter.SimpleItemFilter; +import gregtech.common.covers.filter.SmartItemFilter; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.entities.GTBoatEntity.GTBoatType; import gregtech.common.items.behaviors.ClipboardBehavior; @@ -47,6 +52,10 @@ import gregtech.common.items.behaviors.TooltipBehavior; import gregtech.common.items.behaviors.TricorderBehavior; import gregtech.common.items.behaviors.TurbineRotorBehavior; +import gregtech.common.items.behaviors.filter.OreDictFilterUIManager; +import gregtech.common.items.behaviors.filter.SimpleFilterUIManager; +import gregtech.common.items.behaviors.filter.SimpleFluidFilterUIManager; +import gregtech.common.items.behaviors.filter.SmartFilterUIManager; import gregtech.common.items.behaviors.monitorplugin.AdvancedMonitorPluginBehavior; import gregtech.common.items.behaviors.monitorplugin.FakeGuiPluginBehavior; import gregtech.common.items.behaviors.monitorplugin.OnlinePicPluginBehavior; @@ -579,14 +588,18 @@ public void registerSubItems() { // Filters: ID 290-300 FLUID_FILTER = addItem(290, "fluid_filter") - .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 2))); + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 2))) + .addComponents(new SimpleFluidFilterUIManager(), IFilter.factory(SimpleFluidFilter::new)); ITEM_FILTER = addItem(291, "item_filter") .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 2), - new MaterialStack(Materials.Steel, M))); + new MaterialStack(Materials.Steel, M))) + .addComponents(new SimpleFilterUIManager(), IFilter.factory(SimpleItemFilter::new)); ORE_DICTIONARY_FILTER = addItem(292, "ore_dictionary_filter") - .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 2))); + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 2))) + .addComponents(new OreDictFilterUIManager(), IFilter.factory(OreDictionaryItemFilter::new)); SMART_FILTER = addItem(293, "smart_item_filter") - .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 3 / 2))); + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Zinc, M * 3 / 2))) + .addComponents(new SmartFilterUIManager(), IFilter.factory(SmartItemFilter::new)); // Functional Covers: ID 301-330 COVER_MACHINE_CONTROLLER = addItem(301, "cover.controller"); diff --git a/src/main/java/gregtech/common/items/behaviors/filter/BaseFilterUIManager.java b/src/main/java/gregtech/common/items/behaviors/filter/BaseFilterUIManager.java new file mode 100644 index 00000000000..64fa36e7118 --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/filter/BaseFilterUIManager.java @@ -0,0 +1,55 @@ +package gregtech.common.items.behaviors.filter; + +import gregtech.api.cover.CoverWithUI; +import gregtech.api.items.gui.ItemUIFactory; +import gregtech.api.items.metaitem.stats.IItemBehaviour; +import gregtech.api.mui.GTGuiTheme; +import gregtech.api.mui.GTGuis; +import gregtech.api.mui.factory.MetaItemGuiFactory; + +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; + +import java.util.List; + +public abstract class BaseFilterUIManager implements IItemBehaviour, ItemUIFactory { + + @Override + public final ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { + ItemStack heldItem = player.getHeldItem(hand); + if (!world.isRemote && !player.isSneaking()) { + MetaItemGuiFactory.open(player, hand); + } + if (player.isSneaking() && heldItem.hasTagCompound()) { + heldItem.setTagCompound(null); + } + return ActionResult.newResult(EnumActionResult.SUCCESS, heldItem); + } + + @Override + public abstract ModularPanel buildUI(HandGuiData guiData, GuiSyncManager guiSyncManager); + + protected final ModularPanel createBasePanel(ItemStack stack) { + return GTGuis.createPanel(stack, 176, 188) + .child(CoverWithUI.createTitleRow(stack)); + } + + @Override + public GTGuiTheme getUITheme() { + return GTGuiTheme.COVER; + } + + @Override + public void addInformation(ItemStack itemStack, List lines) { + lines.add(I18n.format("behaviour.filter_ui_manager")); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/filter/OreDictFilterUIManager.java b/src/main/java/gregtech/common/items/behaviors/filter/OreDictFilterUIManager.java new file mode 100644 index 00000000000..2656db4758a --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/filter/OreDictFilterUIManager.java @@ -0,0 +1,19 @@ +package gregtech.common.items.behaviors.filter; + +import gregtech.common.covers.filter.BaseFilter; + +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; + +public class OreDictFilterUIManager extends BaseFilterUIManager { + + @Override + public ModularPanel buildUI(HandGuiData guiData, GuiSyncManager guiSyncManager) { + var filter = BaseFilter.getFilterFromStack(guiData.getUsedItemStack()); + return createBasePanel(filter.getContainerStack()).height(160) + .child(filter.createWidgets(guiSyncManager).top(22).margin(7, 0)) + .child(SlotGroupWidget.playerInventory().bottom(7).left(7)); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/filter/SimpleFilterUIManager.java b/src/main/java/gregtech/common/items/behaviors/filter/SimpleFilterUIManager.java new file mode 100644 index 00000000000..2c3b5da39cd --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/filter/SimpleFilterUIManager.java @@ -0,0 +1,19 @@ +package gregtech.common.items.behaviors.filter; + +import gregtech.common.covers.filter.BaseFilter; + +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; + +public class SimpleFilterUIManager extends BaseFilterUIManager { + + @Override + public ModularPanel buildUI(HandGuiData guiData, GuiSyncManager guiSyncManager) { + var filter = BaseFilter.getFilterFromStack(guiData.getUsedItemStack()); + return createBasePanel(filter.getContainerStack()).padding(4).height(166) + .child(filter.createWidgets(guiSyncManager).top(22).left(7)) + .child(SlotGroupWidget.playerInventory().left(7)); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/filter/SimpleFluidFilterUIManager.java b/src/main/java/gregtech/common/items/behaviors/filter/SimpleFluidFilterUIManager.java new file mode 100644 index 00000000000..df66b9c5bca --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/filter/SimpleFluidFilterUIManager.java @@ -0,0 +1,19 @@ +package gregtech.common.items.behaviors.filter; + +import gregtech.common.covers.filter.BaseFilter; + +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; + +public class SimpleFluidFilterUIManager extends BaseFilterUIManager { + + @Override + public ModularPanel buildUI(HandGuiData guiData, GuiSyncManager guiSyncManager) { + var filter = BaseFilter.getFilterFromStack(guiData.getUsedItemStack()); + return createBasePanel(filter.getContainerStack()).padding(4).height(166) + .child(filter.createWidgets(guiSyncManager).top(22).left(7)) + .child(SlotGroupWidget.playerInventory().left(7)); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/filter/SmartFilterUIManager.java b/src/main/java/gregtech/common/items/behaviors/filter/SmartFilterUIManager.java new file mode 100644 index 00000000000..033fbb2e109 --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/filter/SmartFilterUIManager.java @@ -0,0 +1,19 @@ +package gregtech.common.items.behaviors.filter; + +import gregtech.common.covers.filter.BaseFilter; + +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.GuiSyncManager; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; + +public class SmartFilterUIManager extends BaseFilterUIManager { + + @Override + public ModularPanel buildUI(HandGuiData guiData, GuiSyncManager guiSyncManager) { + var filter = BaseFilter.getFilterFromStack(guiData.getUsedItemStack()); + return createBasePanel(filter.getContainerStack()).height(166) + .child(filter.createWidgets(guiSyncManager).left(7).top(22)) + .child(SlotGroupWidget.playerInventory().bottom(7).left(7)); + } +} diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityItemCollector.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityItemCollector.java index d49fb520bf1..1128819ff6d 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityItemCollector.java +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityItemCollector.java @@ -144,7 +144,7 @@ protected void moveItemsInEffectRange() { double distanceX = (areaCenterPos.getX() + 0.5) - entityItem.posX; double distanceZ = (areaCenterPos.getZ() + 0.5) - entityItem.posZ; double distance = MathHelper.sqrt(distanceX * distanceX + distanceZ * distanceZ); - if (!itemFilter.testItemStack(entityItem.getItem())) { + if (!itemFilter.test(entityItem.getItem())) { continue; } if (distance >= 0.7) { diff --git a/src/main/java/gregtech/common/mui/widget/HighlightedTextField.java b/src/main/java/gregtech/common/mui/widget/HighlightedTextField.java new file mode 100644 index 00000000000..3bb6a3e652b --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/HighlightedTextField.java @@ -0,0 +1,95 @@ +package gregtech.common.mui.widget; + +import com.cleanroommc.modularui.api.value.IStringValue; +import com.cleanroommc.modularui.screen.viewport.GuiContext; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widgets.textfield.TextFieldHandler; +import com.cleanroommc.modularui.widgets.textfield.TextFieldRenderer; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import java.util.Map; +import java.util.function.Function; + +public class HighlightedTextField extends TextFieldWidget { + + private StringSyncValue stringSyncValue; + + private final TextHighlighter highlighter; + private Runnable onUnfocus; + + public HighlightedTextField() { + this.highlighter = new TextHighlighter(this.handler); + this.renderer = this.highlighter; + this.handler.setRenderer(this.renderer); + } + + @Override + public void afterInit() { + this.highlighter.runHighlighter(getText()); + } + + /** + * Text highlighter applied only in rendering text. Only formatting characters can be inserted. + * + * @param highlightRule Consumer for text highlighter + * @return This + */ + public HighlightedTextField setHighlightRule(Function highlightRule) { + this.highlighter.setHighlightRule(highlightRule); + return getThis(); + } + + @Override + public HighlightedTextField value(IStringValue stringValue) { + this.stringSyncValue = (StringSyncValue) stringValue; + super.value(stringValue); + return getThis(); + } + + @Override + public HighlightedTextField getThis() { + return this; + } + + @Override + public void onRemoveFocus(GuiContext context) { + super.onRemoveFocus(context); + highlighter.runHighlighter(getText()); + if (isSynced()) + this.stringSyncValue.setStringValue(getText(), true, true); + onUnfocus.run(); + } + + public HighlightedTextField onUnfocus(Runnable onUnfocus) { + this.onUnfocus = onUnfocus; + return getThis(); + } + + public static final class TextHighlighter extends TextFieldRenderer { + + private Function highlightRule = string -> string; + + private Map cacheMap = new Object2ObjectOpenHashMap<>(); + + public TextHighlighter(TextFieldHandler handler) { + super(handler); + } + + public void setHighlightRule(Function highlightRule) { + this.highlightRule = highlightRule; + } + + @Override + protected float draw(String text, float x, float y) { + return super.draw(this.cacheMap.getOrDefault(text, text), x, y); + } + + public void runHighlighter(String text) { + if (this.highlightRule == null) { + return; + } + this.cacheMap.computeIfAbsent(text, string -> this.highlightRule.apply(string)); + } + } +} diff --git a/src/main/java/gregtech/common/mui/widget/orefilter/ItemOreFilterTestSlot.java b/src/main/java/gregtech/common/mui/widget/orefilter/ItemOreFilterTestSlot.java new file mode 100644 index 00000000000..9e16df34dfb --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/orefilter/ItemOreFilterTestSlot.java @@ -0,0 +1,42 @@ +package gregtech.common.mui.widget.orefilter; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.ItemStackHandler; + +import com.cleanroommc.modularui.widgets.slot.ModularSlot; +import org.jetbrains.annotations.NotNull; + +public class ItemOreFilterTestSlot extends ModularSlot { + + OreFilterTestSlot parent; + + public ItemOreFilterTestSlot() { + super(new ItemStackHandler(1), 0, true); + } + + void setParent(OreFilterTestSlot parent) { + this.parent = parent; + } + + @Override + public void putStack(ItemStack stack) { + ItemStack testStack = getStack(); + if ((stack.isEmpty() ^ testStack.isEmpty()) || !testStack.isItemEqual(stack) || + !ItemStack.areItemStackTagsEqual(testStack, stack)) { + ItemStack copy = stack.copy(); + copy.setCount(1); + super.putStack(copy); + this.parent.updatePreview(); + } + } + + @Override + public int getSlotStackLimit() { + return 1; + } + + @Override + public int getItemStackLimit(@NotNull ItemStack stack) { + return 1; + } +} diff --git a/src/main/java/gregtech/common/mui/widget/orefilter/OreFilterTestSlot.java b/src/main/java/gregtech/common/mui/widget/orefilter/OreFilterTestSlot.java new file mode 100644 index 00000000000..1948364bbec --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/orefilter/OreFilterTestSlot.java @@ -0,0 +1,144 @@ +package gregtech.common.mui.widget.orefilter; + +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.unification.OreDictUnifier; +import gregtech.api.util.function.BooleanConsumer; +import gregtech.api.util.oreglob.OreGlob; +import gregtech.common.covers.filter.oreglob.impl.ImpossibleOreGlob; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.screen.viewport.GuiContext; +import com.cleanroommc.modularui.theme.WidgetTheme; +import com.cleanroommc.modularui.widgets.ItemSlot; +import it.unimi.dsi.fastutil.objects.Object2BooleanAVLTreeMap; +import it.unimi.dsi.fastutil.objects.Object2BooleanMap; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +/** + * @author brachy84 + */ +public class OreFilterTestSlot extends ItemSlot { + + private final ItemOreFilterTestSlot slot; + private Supplier globSupplier = ImpossibleOreGlob::getInstance; + @Nullable + private BooleanConsumer onMatchChange; + private final Object2BooleanMap testResult = new Object2BooleanAVLTreeMap<>(); + private MatchType matchType = MatchType.INVALID; + private boolean matchSuccess; + private boolean matchAll; + + public OreFilterTestSlot() { + this.slot = new ItemOreFilterTestSlot(); + this.slot.setParent(this); + slot(this.slot); + tooltipBuilder(tooltip -> { + if (!isEnabled()) return; + tooltip.addDrawableLines(switch (this.matchType) { + case NO_ORE_DICT_MATCH -> Collections.singletonList(IKey.lang(this.matchSuccess ? + "cover.ore_dictionary_filter.test_slot.no_oredict.matches" : + "cover.ore_dictionary_filter.test_slot.no_oredict.matches_not")); + case ORE_DICT_MATCH -> this.testResult.object2BooleanEntrySet() + .stream().map(e -> IKey.lang(e.getBooleanValue() ? + "cover.ore_dictionary_filter.test_slot.matches" : + "cover.ore_dictionary_filter.test_slot.matches_not", e.getKey())) + .collect(Collectors.toList()); + default -> Collections.singletonList(IKey.lang("cover.ore_dictionary_filter.test_slot.info")); + }); + }); + } + + public OreFilterTestSlot setGlobSupplier(Supplier supplier) { + this.globSupplier = supplier; + this.updatePreview(); + return getThis(); + } + + @Override + public OreFilterTestSlot getThis() { + return this; + } + + public boolean isMatchSuccess() { + return matchSuccess; + } + + public OreFilterTestSlot onMatchChange(@Nullable BooleanConsumer onMatchChange) { + this.onMatchChange = onMatchChange; + return getThis(); + } + + public void setMatchAll(boolean matchAll) { + if (this.matchAll == matchAll) return; + this.matchAll = matchAll; + updatePreview(); + } + + public void updatePreview() { + Set oreDicts = getTestCandidates(); + this.testResult.clear(); + if (oreDicts == null) { + this.matchType = MatchType.INVALID; + updateAndNotifyMatchSuccess(false); + return; + } + OreGlob glob = this.globSupplier.get(); + int success = 0; + if (oreDicts.isEmpty()) { + // no oredict entries + this.testResult.put("", glob != null && glob.matches("")); + this.matchType = MatchType.NO_ORE_DICT_MATCH; + } else { + for (String oreDict : oreDicts) { + boolean matches = glob != null && glob.matches(oreDict); + if (matches) success++; + this.testResult.put(oreDict, matches); + } + this.matchType = MatchType.ORE_DICT_MATCH; + } + updateAndNotifyMatchSuccess(this.matchAll ? success == testResult.size() : success > 0); + this.tooltip().markDirty(); + } + + @Override + public void draw(GuiContext context, WidgetTheme widgetTheme) { + super.draw(context, widgetTheme); + if (this.matchSuccess) { + GTGuiTextures.OREDICT_MATCH + .draw(context, 12, -2, 9, 6, widgetTheme); + } else if (testResult.size() > 0) { + GTGuiTextures.OREDICT_NO_MATCH + .draw(context, 12, -3, 7, 7, widgetTheme); + } + } + + private void updateAndNotifyMatchSuccess(boolean newValue) { + if (this.matchSuccess == newValue) return; + this.matchSuccess = newValue; + if (this.onMatchChange != null) { + this.onMatchChange.apply(newValue); + } + } + + /** + * Get each test candidate for current state of test slot. An empty collection indicates that the match is for items + * without any ore dictionary entry. A {@code null} value indicates that the input state is invalid or empty. + * + * @return each test candidate for current state of test slot + */ + @Nullable + protected Set getTestCandidates() { + return this.slot.getStack().isEmpty() ? null : OreDictUnifier.getOreDictionaryNames(this.slot.getStack()); + } + + private enum MatchType { + NO_ORE_DICT_MATCH, + ORE_DICT_MATCH, + INVALID + } +} diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index a2313f82398..20967af87e4 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -6,7 +6,11 @@ import gregtech.api.util.FacingPos; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.ItemStackHashStrategy; -import gregtech.common.covers.*; +import gregtech.common.covers.CoverConveyor; +import gregtech.common.covers.CoverItemFilter; +import gregtech.common.covers.CoverRoboticArm; +import gregtech.common.covers.DistributionMode; +import gregtech.common.covers.ItemFilterMode; import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; import net.minecraft.item.ItemStack; @@ -364,15 +368,18 @@ public Cover getCoverOnNeighbour(TileEntityItemPipe itemPipe, EnumFacing facing) public ItemStack insertOverRobotArm(IItemHandler handler, CoverRoboticArm arm, ItemStack stack, boolean simulate, int allowed, boolean ignoreLimit) { - int rate; + var matched = arm.getItemFilterContainer().match(stack); boolean isStackSpecific = false; - Object index = arm.getItemFilterContainer().matchItemStack(stack); - if (index instanceof Integer) { - rate = arm.getItemFilterContainer().getSlotTransferLimit(index); + int rate, count; + + if (matched.isMatched()) { + int index = matched.getFilterIndex(); + rate = arm.getItemFilterContainer().getTransferLimit(index); isStackSpecific = true; - } else - rate = arm.getItemFilterContainer().getTransferStackSize(); - int count; + } else { + rate = arm.getItemFilterContainer().getTransferSize(); + } + switch (arm.getTransferMode()) { case TRANSFER_ANY: return insert(handler, stack, simulate, allowed, ignoreLimit); @@ -405,7 +412,7 @@ public static int countStack(IItemHandler handler, ItemStack stack, CoverRobotic ItemStack slot = handler.getStackInSlot(i); if (slot.isEmpty()) continue; if (isStackSpecific ? ItemStackHashStrategy.comparingAllButCount().equals(stack, slot) : - arm.getItemFilterContainer().testItemStack(slot)) { + arm.getItemFilterContainer().test(slot)) { count += slot.getCount(); } } diff --git a/src/main/java/gregtech/core/CoreModule.java b/src/main/java/gregtech/core/CoreModule.java index 46eeb3e8335..c05116355f7 100644 --- a/src/main/java/gregtech/core/CoreModule.java +++ b/src/main/java/gregtech/core/CoreModule.java @@ -43,7 +43,6 @@ import gregtech.common.command.CommandShaders; import gregtech.common.command.worldgen.CommandWorldgen; import gregtech.common.covers.CoverBehaviors; -import gregtech.common.covers.filter.FilterTypeRegistry; import gregtech.common.covers.filter.oreglob.impl.OreGlobParser; import gregtech.common.items.MetaItems; import gregtech.common.items.ToolItems; @@ -255,7 +254,6 @@ public void init(FMLInitializationEvent event) { WorldGenRegistry.INSTANCE.initializeRegistry(); LootTableHelper.initialize(); - FilterTypeRegistry.init(); /* Start Cover Definition Registration */ COVER_REGISTRY.unfreeze(); diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/CoverInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/CoverInfoProvider.java index 6656fcc9d7e..0aebf88036a 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/CoverInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/CoverInfoProvider.java @@ -10,6 +10,7 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.IStringSerializable; import net.minecraft.util.text.TextFormatting; import net.minecraftforge.common.capabilities.Capability; @@ -57,22 +58,25 @@ protected void addProbeInfo(@NotNull CoverHolder capability, @NotNull IProbeInfo * @param conveyor the conveyor to get data from */ private static void conveyorInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverConveyor conveyor) { - String rateUnit = " {*cover.conveyor.transfer_rate*}"; + String rateUnit = lang("cover.conveyor.transfer_rate"); if (conveyor instanceof CoverItemVoiding) { itemVoidingInfo(probeInfo, (CoverItemVoiding) conveyor); - } else if (!(conveyor instanceof CoverRoboticArm) || - ((CoverRoboticArm) conveyor).getTransferMode() == TransferMode.TRANSFER_ANY) { + } else if (!(conveyor instanceof CoverRoboticArm arm) || + arm.getTransferMode() == TransferMode.TRANSFER_ANY) { // only display the regular rate if the cover does not have a specialized rate - transferRateText(probeInfo, conveyor.getConveyorMode(), rateUnit, conveyor.getTransferRate()); + transferRateText(probeInfo, conveyor.getConveyorMode(), " " + rateUnit, conveyor.getTransferRate()); } ItemFilterContainer filter = conveyor.getItemFilterContainer(); if (conveyor instanceof CoverRoboticArm roboticArm) { - transferModeText(probeInfo, roboticArm.getTransferMode(), rateUnit, filter.getTransferStackSize(), - filter.getFilterWrapper().getItemFilter() != null); + if (roboticArm.getTransferMode() != TransferMode.TRANSFER_ANY) + rateUnit = lang("cover.robotic_arm.exact"); + + transferModeText(probeInfo, roboticArm.getTransferMode(), rateUnit, + filter.getTransferSize(), filter.hasFilter()); } - itemFilterText(probeInfo, filter.getFilterWrapper().getItemFilter()); + itemFilterText(probeInfo, filter.getFilter()); } /** @@ -82,13 +86,13 @@ private static void conveyorInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverCo * @param voiding the voiding cover to get data from */ private static void itemVoidingInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverItemVoiding voiding) { - String unit = " {*gregtech.top.unit.items*}"; + String unit = lang("gregtech.top.unit.items"); ItemFilterContainer container = voiding.getItemFilterContainer(); if (voiding instanceof CoverItemVoidingAdvanced advanced) { VoidingMode mode = advanced.getVoidingMode(); - voidingText(probeInfo, mode, unit, container.getTransferStackSize(), - container.getFilterWrapper().getItemFilter() != null); + voidingText(probeInfo, mode, unit, container.getTransferSize(), + container.hasFilter() && !container.isBlacklistFilter()); } } @@ -99,12 +103,14 @@ private static void itemVoidingInfo(@NotNull IProbeInfo probeInfo, @NotNull Cove * @param pump the pump to get data from */ private static void pumpInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverPump pump) { - String rateUnit = IProbeInfo.STARTLOC + pump.getBucketMode().getName() + IProbeInfo.ENDLOC; + String rateUnit = lang(pump.getBucketMode() == CoverPump.BucketMode.BUCKET ? + "cover.bucket.mode.bucket_rate" : + "cover.bucket.mode.milli_bucket_rate"); if (pump instanceof CoverFluidVoiding) { fluidVoidingInfo(probeInfo, (CoverFluidVoiding) pump); - } else if (!(pump instanceof CoverFluidRegulator) || - ((CoverFluidRegulator) pump).getTransferMode() == TransferMode.TRANSFER_ANY) { + } else if (!(pump instanceof CoverFluidRegulator regulator) || + regulator.getTransferMode() == TransferMode.TRANSFER_ANY) { // do not display the regular rate if the cover has a specialized rate transferRateText(probeInfo, pump.getPumpMode(), " " + rateUnit, pump.getBucketMode() == CoverPump.BucketMode.BUCKET ? pump.getTransferRate() / 1000 : @@ -113,10 +119,15 @@ private static void pumpInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverPump p FluidFilterContainer filter = pump.getFluidFilterContainer(); if (pump instanceof CoverFluidRegulator regulator) { - transferModeText(probeInfo, regulator.getTransferMode(), rateUnit, regulator.getTransferAmount(), - filter.getFilterWrapper().getFluidFilter() != null); + if (regulator.getTransferMode() != TransferMode.TRANSFER_ANY) + rateUnit = lang(regulator.getBucketMode() == CoverPump.BucketMode.BUCKET ? + "gregtech.top.unit.fluid_buckets" : + "gregtech.top.unit.fluid_milibuckets"); + + transferModeText(probeInfo, regulator.getTransferMode(), rateUnit, regulator + .getFluidFilterContainer().getTransferSize(), filter.hasFilter() && !filter.isBlacklistFilter()); } - fluidFilterText(probeInfo, filter.getFilterWrapper().getFluidFilter()); + fluidFilterText(probeInfo, filter.getFilter()); } /** @@ -126,8 +137,10 @@ private static void pumpInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverPump p * @param voiding the voiding cover to get data from */ private static void fluidVoidingInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverFluidVoiding voiding) { - String unit = voiding.getBucketMode() == CoverPump.BucketMode.BUCKET ? " {*gregtech.top.unit.fluid_buckets*}" : - " {*gregtech.top.unit.fluid_milibuckets*}"; + String unit = lang(voiding.getBucketMode() == CoverPump.BucketMode.BUCKET ? + "gregtech.top.unit.fluid_buckets" : + "gregtech.top.unit.fluid_milibuckets"); + var container = voiding.getFluidFilterContainer(); if (voiding instanceof CoverFluidVoidingAdvanced advanced) { VoidingMode mode = advanced.getVoidingMode(); @@ -135,7 +148,7 @@ private static void fluidVoidingInfo(@NotNull IProbeInfo probeInfo, @NotNull Cov voidingText(probeInfo, mode, unit, voiding.getBucketMode() == CoverPump.BucketMode.BUCKET ? advanced.getTransferAmount() / 1000 : advanced.getTransferAmount(), - voiding.getFluidFilterContainer().getFilterWrapper().getFluidFilter() != null); + container.hasFilter() && !container.isBlacklistFilter()); } } @@ -147,7 +160,7 @@ private static void fluidVoidingInfo(@NotNull IProbeInfo probeInfo, @NotNull Cov */ private static void itemFilterInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverItemFilter itemFilter) { filterModeText(probeInfo, itemFilter.getFilterMode()); - itemFilterText(probeInfo, itemFilter.getItemFilter().getItemFilter()); + itemFilterText(probeInfo, itemFilter.getFilter()); } /** @@ -158,7 +171,7 @@ private static void itemFilterInfo(@NotNull IProbeInfo probeInfo, @NotNull Cover */ private static void fluidFilterInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverFluidFilter fluidFilter) { filterModeText(probeInfo, fluidFilter.getFilterMode()); - fluidFilterText(probeInfo, fluidFilter.getFluidFilter().getFluidFilter()); + fluidFilterText(probeInfo, fluidFilter.getFilter()); } /** @@ -168,12 +181,13 @@ private static void fluidFilterInfo(@NotNull IProbeInfo probeInfo, @NotNull Cove * @param enderFluidLink the ender fluid link cover to get data from */ private static void enderFluidLinkInfo(@NotNull IProbeInfo probeInfo, @NotNull CoverEnderFluidLink enderFluidLink) { - transferRateText(probeInfo, enderFluidLink.getPumpMode(), " {*cover.bucket.mode.milli_bucket*}", + transferRateText(probeInfo, enderFluidLink.getPumpMode(), " " + lang("cover.bucket.mode.milli_bucket_rate"), enderFluidLink.isIOEnabled() ? CoverEnderFluidLink.TRANSFER_RATE : 0); - fluidFilterText(probeInfo, enderFluidLink.getFluidFilterContainer().getFilterWrapper().getFluidFilter()); + fluidFilterText(probeInfo, enderFluidLink.getFluidFilterContainer().getFilter()); if (!enderFluidLink.getColorStr().isEmpty()) { - probeInfo.text(TextStyleClass.INFO + "{*gregtech.top.link_cover.color*} " + enderFluidLink.getColorStr()); + probeInfo.text( + TextStyleClass.INFO + lang("gregtech.top.link_cover.color") + " " + enderFluidLink.getColorStr()); } } @@ -187,7 +201,8 @@ private static void enderFluidLinkInfo(@NotNull IProbeInfo probeInfo, @NotNull C */ private static void transferRateText(@NotNull IProbeInfo probeInfo, @NotNull IIOMode mode, @NotNull String rateUnit, int rate) { - String modeText = mode.isImport() ? "{*gregtech.top.mode.import*} " : "{*gregtech.top.mode.export*} "; + String modeText = mode.isImport() ? lang("gregtech.top.mode.import") : lang("gregtech.top.mode.export"); + modeText += " "; probeInfo.text(TextStyleClass.OK + modeText + TextStyleClass.LABEL + TextFormattingUtil.formatNumbers(rate) + rateUnit); } @@ -197,15 +212,15 @@ private static void transferRateText(@NotNull IProbeInfo probeInfo, @NotNull IIO * * @param probeInfo the info to add the text to * @param mode the transfer mode of the cover - * @param rateUnit the unit of what is transferred * @param rate the transfer rate of the mode * @param hasFilter whether the cover has a filter installed */ private static void transferModeText(@NotNull IProbeInfo probeInfo, @NotNull TransferMode mode, @NotNull String rateUnit, int rate, boolean hasFilter) { - String text = TextStyleClass.OK + IProbeInfo.STARTLOC + mode.getName() + IProbeInfo.ENDLOC; + String text = TextStyleClass.OK + lang(mode.getName()); if (!hasFilter && mode != TransferMode.TRANSFER_ANY) - text += TextStyleClass.LABEL + " " + TextFormattingUtil.formatNumbers(rate) + rateUnit; + text += TextStyleClass.LABEL + " " + TextFormattingUtil.formatNumbers(rate) + " " + rateUnit; + probeInfo.text(text); } @@ -220,45 +235,49 @@ private static void transferModeText(@NotNull IProbeInfo probeInfo, @NotNull Tra */ private static void voidingText(@NotNull IProbeInfo probeInfo, @NotNull VoidingMode mode, @NotNull String unit, int amount, boolean hasFilter) { - String text = TextFormatting.RED + IProbeInfo.STARTLOC + mode.getName() + IProbeInfo.ENDLOC; - if (mode != VoidingMode.VOID_ANY && !hasFilter) text += " " + TextFormattingUtil.formatNumbers(amount) + unit; + String text = TextFormatting.RED + lang(mode.getName()); + if (mode != VoidingMode.VOID_ANY && !hasFilter) + text += " " + TextFormattingUtil.formatNumbers(amount) + " " + unit; probeInfo.text(text); } /** - * Displays text for {@link IFilterMode} covers + * Displays text for {@link net.minecraft.util.IStringSerializable} covers * * @param probeInfo the info to add the text to * @param mode the filter mode of the cover */ - private static void filterModeText(@NotNull IProbeInfo probeInfo, @NotNull IFilterMode mode) { - probeInfo.text(TextStyleClass.WARNING + IProbeInfo.STARTLOC + mode.getName() + IProbeInfo.ENDLOC); + private static void filterModeText(@NotNull IProbeInfo probeInfo, @NotNull IStringSerializable mode) { + probeInfo.text(TextStyleClass.WARNING + lang(mode.getName())); } /** - * Displays text for {@link ItemFilter} covers + * Displays text for {@link BaseFilter} item covers * * @param probeInfo the info to add the text to * @param filter the filter to display info from */ - private static void itemFilterText(@NotNull IProbeInfo probeInfo, @Nullable ItemFilter filter) { - String label = TextStyleClass.INFO + "{*gregtech.top.filter.label*} "; + private static void itemFilterText(@NotNull IProbeInfo probeInfo, @Nullable BaseFilter filter) { + String label = TextStyleClass.INFO + lang("gregtech.top.filter.label"); if (filter instanceof OreDictionaryItemFilter) { String expression = ((OreDictionaryItemFilter) filter).getExpression(); if (!expression.isEmpty()) probeInfo.text(label + expression); - } else if (filter instanceof SmartItemFilter) { - probeInfo.text(label + IProbeInfo.STARTLOC + ((SmartItemFilter) filter).getFilteringMode().getName() + - IProbeInfo.ENDLOC); + } else if (filter instanceof SmartItemFilter smartItemFilter) { + probeInfo.text(label + lang(smartItemFilter.getFilteringMode().getName())); } } /** - * Displays text for {@link FluidFilter} covers + * Displays text for {@link BaseFilter} fluid covers * * @param probeInfo the info to add the text to * @param filter the filter to display info from */ - private static void fluidFilterText(@NotNull IProbeInfo probeInfo, @Nullable FluidFilter filter) { + private static void fluidFilterText(@NotNull IProbeInfo probeInfo, @Nullable BaseFilter filter) { // TODO If more unique fluid filtration is added, providers for it go here } + + private static String lang(String lang) { + return IProbeInfo.STARTLOC + lang + IProbeInfo.ENDLOC; + } } diff --git a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java index cd7b866c272..67a29315718 100644 --- a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java @@ -1405,6 +1405,16 @@ private static void registerNBTRemoval() { ModHandler.addShapelessNBTClearingRecipe("data_module_nbt", TOOL_DATA_MODULE.getStackForm(), TOOL_DATA_MODULE.getStackForm()); + // Filters + ModHandler.addShapelessNBTClearingRecipe("clear_item_filter", + ITEM_FILTER.getStackForm(), ITEM_FILTER); + ModHandler.addShapelessNBTClearingRecipe("clear_fluid_filter", + FLUID_FILTER.getStackForm(), FLUID_FILTER); + ModHandler.addShapelessNBTClearingRecipe("clear_smart_filter", + SMART_FILTER.getStackForm(), SMART_FILTER); + ModHandler.addShapelessNBTClearingRecipe("clear_oredict_filter", + ORE_DICTIONARY_FILTER.getStackForm(), ORE_DICTIONARY_FILTER); + // Jetpacks ModHandler.addShapelessRecipe("fluid_jetpack_clear", SEMIFLUID_JETPACK.getStackForm(), SEMIFLUID_JETPACK.getStackForm()); diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 5d1adf35389..d041e2f0126 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -822,6 +822,7 @@ metaitem.fluid_filter.name=Fluid Filter metaitem.fluid_filter.tooltip=Filters §fFluid§7 I/O as §fCover§7./nCan be used as an §fElectric Pump§7 and §fFluid Regulator§7 upgrade. metaitem.smart_item_filter.name=Smart Item Filter metaitem.smart_item_filter.tooltip=Filters §fItem§7 I/O with §fMachine Recipes§7 as §fCover§7./nCan be used as a §fConveyor Module§7 and §fRobotic Arm§7 upgrade. +behaviour.filter_ui_manager=§fRight-Click§7 to configure, §fShift Right-Click§7 to clear configuration metaitem.cover.controller.name=Machine Controller metaitem.cover.controller.tooltip=Turns Machines §fON/OFF§7 as §fCover§7. @@ -1178,7 +1179,9 @@ cover.filter.blacklist.disabled=Whitelist cover.filter.blacklist.enabled=Blacklist cover.ore_dictionary_filter.title=Ore Dictionary Filter -cover.ore_dictionary_filter.info=§bAccepts complex expressions/n§6a & b§r = AND/n§6a | b§r = OR/n§6a ^ b§r = XOR/n§6! abc§r = NOT/n§6( abc )§r for grouping/n§6*§r for wildcard (i.e. 0 or more characters)/n§6?§r for any 1 character/n§6()§r for matching empty entry (including items with no ore dictionary)/n§bExample:/n§6dust*Gold | (plate* & !*Double*)/nWill match all gold dusts of all sizes or all plates, but not double plates +cover.ore_dictionary_filter.info=§bAccepts complex expressions\n§6a & b§r = AND\n§6a | b§r = OR\n§6a ^ b§r = XOR\n§6! abc§r = NOT\n§6( abc )§r for grouping\n§6*§r for wildcard (i.e. 0 or more characters)\n§6?§r for any 1 character\n§6()§r for matching empty entry (including items with no ore dictionary)\n§bExample:\n§6dust*Gold | (plate* & !*Double*)\nWill match all gold dusts of all sizes or all plates, but not double plates +cover.ore_dictionary_filter.match_all=Match All: %s +cover.ore_dictionary_filter.case_sensitive=Case Sensitive: %s cover.ore_dictionary_filter.test_slot.info=Insert a item to test if it matches the filter expression cover.ore_dictionary_filter.test_slot.matches=§a* %s cover.ore_dictionary_filter.test_slot.matches_not=§c* %s @@ -1243,6 +1246,7 @@ cover.fluid_filter.mode.filter_drain=Filter Drain cover.fluid_filter.mode.filter_both=Filter Fill & Drain cover.item_filter.title=Item Filter +cover.filter.mode.title=Filter Mode cover.filter.mode.filter_insert=Filter Insert cover.filter.mode.filter_extract=Filter Extract cover.filter.mode.filter_both=Filter Insert/Extract @@ -1250,9 +1254,11 @@ cover.item_filter.ignore_damage.enabled=Ignore Damage cover.item_filter.ignore_damage.disabled=Respect Damage cover.item_filter.ignore_nbt.enabled=Ignore NBT cover.item_filter.ignore_nbt.disabled=Respect NBT +cover.item_filter.config_amount=Scroll wheel up increases amount, down decreases.\nShift[§6x4§r], Ctrl[§ex16§r], Alt[§ax64§r]\nRight click increases amount, left click decreases.\nShift Left-Click to clear cover.voiding.voiding_mode.void_any=Void Matching cover.voiding.voiding_mode.void_overflow=Void Overflow +cover.voiding.voiding_mode=Voiding Mode cover.voiding.voiding_mode.description=§eVoid Matching§r will void anything matching the filter. /n§eVoid Overflow§r will void anything matching the filter, up to the specified amount. cover.fluid.voiding.title=Fluid Voiding Settings cover.fluid.voiding.advanced.title=Advanced Fluid Voiding Settings @@ -1273,13 +1279,18 @@ cover.smart_item_filter.filtering_mode.centrifuge=Centrifuge cover.smart_item_filter.filtering_mode.sifter=Sifter cover.smart_item_filter.filtering_mode.description=Select Machine this Smart Filter will use for filtering./nIt will automatically pick right portions of items for robotic arm. +cover.generic.transfer_mode=Transfer Mode +cover.generic.manual_io=Manual IO Mode +cover.generic.io=IO Mode +cover.pump.mode=Pump Mode cover.conveyor.title=Conveyor Cover Settings (%s) cover.conveyor.transfer_rate=§7items/sec cover.conveyor.mode.export=Mode: Export cover.conveyor.mode.import=Mode: Import -cover.conveyor.distribution.round_robin_enhanced=Distribution Mode/n§bEnhanced Round Robin§r/n§7Splits items equally to all inventories -cover.conveyor.distribution.round_robin=Distribution Mode/n§bRound Robin§r with Priority/n§7Tries to split items equally to inventories -cover.conveyor.distribution.first_insert=Distribution Mode/n§bFirst Insert§r/n§7Will insert into the first inventory it finds +cover.conveyor.distribution.name=Distribution Mode +cover.conveyor.distribution.round_robin_enhanced=§bEnhanced Round Robin§r\n§7Splits items equally to all inventories +cover.conveyor.distribution.round_robin=§bRound Robin§r with Priority\n§7Tries to split items equally to inventories +cover.conveyor.distribution.first_insert=§bFirst Insert§r\n§7Will insert into the first inventory it finds cover.conveyor.blocks_input.enabled=If enabled, items will not be inserted when cover is set to pull items from the inventory into pipe./n§aEnabled cover.conveyor.blocks_input.disabled=If enabled, items will not be inserted when cover is set to pull items from the inventory into pipe./n§cDisabled cover.universal.manual_import_export.mode.disabled=Manual I/O: Disabled @@ -1290,6 +1301,7 @@ cover.conveyor.item_filter.title=Item Filter cover.conveyor.ore_dictionary.title=Ore Dictionary Name cover.conveyor.ore_dictionary.title2=(use * for wildcard) cover.robotic_arm.title=Robotic Arm Settings (%s) +cover.robotic_arm.exact=§7items cover.robotic_arm.transfer_mode.transfer_any=Transfer Any cover.robotic_arm.transfer_mode.transfer_exact=Supply Exact cover.robotic_arm.transfer_mode.keep_exact=Keep Exact @@ -1300,8 +1312,12 @@ cover.pump.transfer_rate=%s cover.pump.mode.export=Mode: Export cover.pump.mode.import=Mode: Import cover.pump.fluid_filter.title=Fluid Filter -cover.bucket.mode.bucket=kL/s -cover.bucket.mode.milli_bucket=L/s +cover.bucket.mode.bucket=Bucket Mode: kL +cover.bucket.mode.milli_bucket=Bucket Mode: L +cover.bucket.mode.bucket_rate=kL/s +cover.bucket.mode.bucket_exact=kL +cover.bucket.mode.milli_bucket_rate=L/s +cover.bucket.mode.milli_bucket_exact=L cover.fluid_regulator.title=Fluid Regulator Settings (%s) cover.fluid_regulator.transfer_mode.description=§eTransfer Any§r - in this mode, cover will transfer as many fluids matching its filter as possible./n§eSupply Exact§r - in this mode, cover will supply fluids in portions specified in the window underneath this button. If amount of fluids is less than portion size, fluids won't be moved./n§eKeep Exact§r - in this mode, cover will keep specified amount of fluids in the destination inventory, supplying additional amount of fluids if required./n§7Tip: shift click will multiply increase/decrease amounts by 10 and ctrl click will multiply by 100. cover.fluid_regulator.supply_exact=Supply Exact: %s @@ -1324,7 +1340,7 @@ cover.machine_controller.disable_with_redstone=Disable with Redstone cover.ender_fluid_link.title=Ender Fluid Link cover.ender_fluid_link.iomode.enabled=I/O Enabled cover.ender_fluid_link.iomode.disabled=I/O Disabled -cover.ender_fluid_link.private.tooltip.disabled=Switch to private tank mode/nPrivate mode uses the player who originally placed the cover +cover.ender_fluid_link.private.tooltip.disabled=Switch to private tank mode\nPrivate mode uses the player who originally placed the cover cover.ender_fluid_link.private.tooltip.enabled=Switch to public tank mode cover.ender_fluid_link.incomplete_hex=Inputted color is incomplete!/nIt will be applied once complete (all 8 hex digits)/nClosing the gui will lose edits! diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay/conveyor_mode_overlay.png b/src/main/resources/assets/gregtech/textures/gui/overlay/conveyor_mode_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..0c2a1ac6212f08fcf18c1e225ab71fb63aff4cfc GIT binary patch literal 514 zcmV+d0{#7oP)Px$yh%hsR7i>Kl)p+NQ5431G2srRN@H<_zy=1=*`*M)v64JNQUs4dGFLy{yVn^jnALe?(y@lgfV zn2=HE*x-mBf5T&qixl?0I*kcQc-WrRIoQW1B+#5g`P3|zR&Hn*y`Z&bI-N2ajhM}5 zZ!bITRSuGY$_bfQ?f6TOile54tdw07a{DLb4#?-!A94zOBsl}}=Kufz07*qoM6N<$ Ef??$9QUCw| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay/filter_mode_overlay.png b/src/main/resources/assets/gregtech/textures/gui/overlay/filter_mode_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..0f9c95e8b68cf28a146da948f4ce681b99a1b120 GIT binary patch literal 230 zcmeAS@N?(olHy`uVBq!ia0vp^0zhoQ!3HEH;(vt$DaPU;cPEB*=VV?2ISV{p978-h z--bH!9Z=vnytnfFgY$0|aW2R^uxMttuZ`p?2Tg|ktWQ68EbelNPMCZ^T8G1{z)G=_ zW75~Ba)qJI1{{qy{LjP++)paaxVK#)=!4h?zCy*^8jj>!H>9k#^OPx$2T4RhR5*>bQ!$RjAPk(KE7GB$R0zorh?F{y;3s)N-jFg~#0%*2B2eBDt~i;6 ztg=_FD}z1ucnrWdjffHvrB69OcK`r{5E>#%(=>4?@g2wC3J_5m$1wxg>H9v%t+g=5 zVBhz|MJfht+?m1FT4=2ygn*Q?%5BO+Nt?j{pta7vbFLae+~+UBF-F7~A;e!=*L82X z%~R(XBaY)}0AQZyGz>##p_Ib1EC?YqnZcd*lPRUDbDo81m4cn;2>{^k+!=VSGH-$R z%z|Clg*)vsm;FjaYweq0CAe){Y};0eSZQF4fs_)?Ijrki(Pru&t$h1Ll)U%JdtcrC f_ctC3e$9RXLCPx$fJsC_R7i>KmN84iKp2LfNPdAshn8;6MZ~2`=?@5Wb14p8>z{GawS%~13v_TP zxMh)23vS}j(he3J#Jvt_a(Bsh*IFzhqYBeyF>nxjhIb<`OI}3D%;`Nes`fREuF1TRgbnMSUocL( zz$R?EvVK>CAYKtS*nXhmJ#pQy z&lffRdV_I4^O+Uxg4XxPEfwih%xe{@_t%@`S!o+p`9=uHbR1DY>wXnYy6U~wNvf)} zVHU#iIgI-nY6r2G?UBCO!F&xGqtj*0LSxF@Z0WQlp53ak_6w9Mbr@MF z=+c1*xrKs&m7sD(77DruD)&bc1zo%v#Gc%YN|m?>N{U*&8C^tha;2*Jc!K9k;Lh1s w$~|PdEFEArf^K9#eu086g4&zWl7hdkZ`&=b6JY2k-2eap07*qoM6N<$g6=8K&j0`b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay/manual_io_overlay.png b/src/main/resources/assets/gregtech/textures/gui/overlay/manual_io_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..a8f8bef7a54b4ea90ce60cff3339f09c17c52c82 GIT binary patch literal 593 zcmV-X0Px%3rR#lR7i>KlreA9Kp2J}r*}=Hv{`7Es#6eRWABi?0|P&S{)=p7%girGN5ns1 zMj~Q`9fb-7DjH%ZDgG=KT?fZ*oZg+|AXwU0vQGBhJ^t?X=NImmUbYWS)w!B&;fr9~ zy1_SBvn>>$GnT>z-yA?-duwMbH1}FuT~2xbr~yC*$)25k`4)IVHW*L{@nl;&Q`YH}v4*{jAv`lWn6DH~+GFu1UxeP}w1%8nQJF28cv zo5yYAYDm|d6Sm3RgZ`5OfG7%07)DGc6NbYfB68>IcDwGL$@Jsm!T{_vcML$iQ7??I zPESiexdKQ;s5k0HYn_f;n%4fViGK^N{aqtTQd&$6AdUsCG)gP9(r8`0Vi7nw@>W#? z5E16{d7!jfj9ZLG-}CWx^l`n4l0*QQMKb`Vv!(Im$nfl-6r=!Rheto3KcN6|9j`wK z6oAC>tw+}ytu%KauBtwbZjWa3sH)P6BnDPI>JNf~KZ`e)fD(Hjz5UF5`B?pdv%B+( zRz1>MbFKey@NS5|mQ;B|`ugbUhhL?j0HD|FnJ|n9L;Ft~$HMvf*YcnCL0Z#Ji|cLi$uGA$_WxkXBVq$h9ErBxEUM-GuyG6%w+bO%u|pRhTCsYtD+6VI|e% fpt6R%=LvZOC-1g#3@g|b00000NkvXXu0mjfs#XxA literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/overlay/transfer_mode_overlay.png b/src/main/resources/assets/gregtech/textures/gui/overlay/transfer_mode_overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..9364d84544d7df924d3ff3b2d05f8624158a2d44 GIT binary patch literal 455 zcmV;&0XY7NP)Px$fk{L`R7i>Kma$I5Fc5}6R}2*^8%Qi2k-AnHv+)K6hDe=I1_qvjM_`P^5YeGC zyn)rVV(r4vM_@HW>e#O13k)Dt$}d@oe3xHmJN|Sq=*VSWFu}wkGl|qFcjO0_YcHY4 zB*+DnAF#Ul%3yj9n_X;@Yy8~#3{-(?jR2Nw&m>jN*$SIGpY5wDQ0>xe;Pq6yN;bQA zc)5OM%3pUoS)kfIsI3 zbRYXq@b}0!tF*GC9&7X#vI*#I6Bbb$?9~BY>(ZUj-7~5ewUT@@7*IRtAC;n@qzG&h z1%GVRM?oM7zo;UKf)YX7n_HI{k%9t2sdUpr)+NTWri+4oeI<`8*F#DaGoeG@}MJYXGI&rUMXSW7(f@>5vbJ0aMPxt064w8v% dJT;XJ48pbA6{mI6(txgI@O1TaS?83{1OQZeP(T0x literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/button_distribution_mode.png b/src/main/resources/assets/gregtech/textures/gui/widget/button_distribution_mode.png index 86f6a27bd53c097af0603de0d7e45f4651dc6408..9dbdac4862fbc84eaac41230d29aeb409b504195 100644 GIT binary patch delta 262 zcmV+h0r~#@1&jqDiBL{Q4GJ0x0000DNk~Le0000G0000m2nGNE02p8TSFs_H0e{6w zL_t(YiS3p>62c%5h2N@2$Vt+8lUSzbD51Ac>rH5KlAJ+o3e&E!hm_NvNdPeS9kBtnjyNk$+c?CHBkskS5EpgsJCbUlF)pjm2S_w} zev&~RAgLDCU~mS5Gf90CEm_1ps9Q_WCeT3h1EAJX{u4j&0Ohyqofi8+*oBKT9sq9V zDERLtq(y+(hJy`Arj^YK+o(8^v7Rl-+uens8w6L> zPca2baTa()7BevL9RXp+soH$fKtc8rPhVH|r#u`?+UilyD}{kVe>`0rLn02poo>k2 zWFXR3KjHC?^5TztZ`Qr3;D}2PFTbo^(V*7Hmp9MlbqG_?#wkp_-&9r3&i_>L{%_`f z1|Pvw&H@ve>KlC2pU&ym^5S4*@Te_+ZJYS)*Q3(i)$ec4*|52A9arg^^X?1>-bOp^ z-59ymbF)!u>vH+&U&G}+UYBm3WOsJPhMSY(ZfDJ1?Czq)7n@tM@d7%{(F zHtJ80@D*HTP`GIPrSP_g=H$$%XLGK9zd7F}#Vf_D!{_6(O}h5Jbv>G*f?7)2XOB$j zJ3alZ?7AqBY|5!5AI{~6{Czm@PbpcWxYtM0YWs$no9@(~+NYDa*maqYxPHCE)n#+% SGOPoJ1cRrmpUXO@geCylK9-gM From 7e01d339fb2370eef00ad86b252a3dd00473a338 Mon Sep 17 00:00:00 2001 From: ALongStringOfNumbers <31759736+ALongStringOfNumbers@users.noreply.github.com> Date: Thu, 4 Apr 2024 16:07:25 -0700 Subject: [PATCH 23/25] Allow ITNT and PowderBarrels to make AE singularities (#2442) --- src/main/java/gregtech/common/EventHandlers.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/gregtech/common/EventHandlers.java b/src/main/java/gregtech/common/EventHandlers.java index 588909961e5..8fa23091b99 100644 --- a/src/main/java/gregtech/common/EventHandlers.java +++ b/src/main/java/gregtech/common/EventHandlers.java @@ -12,6 +12,7 @@ import gregtech.api.util.BlockUtility; import gregtech.api.util.CapesRegistry; import gregtech.api.util.GTUtility; +import gregtech.api.util.Mods; import gregtech.api.util.VirtualTankRegistry; import gregtech.api.worldgen.bedrockFluids.BedrockFluidVeinSaveData; import gregtech.common.entities.EntityGTExplosive; @@ -23,6 +24,7 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.attributes.AttributeModifier; @@ -63,6 +65,8 @@ import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.ItemHandlerHelper; +import appeng.entity.EntitySingularity; + @Mod.EventBusSubscriber(modid = GTValues.MODID) public class EventHandlers { @@ -381,8 +385,12 @@ public static void onFurnaceFuelBurnTime(FurnaceFuelBurnTimeEvent event) { public static void onExplosionDetonate(ExplosionEvent.Detonate event) { if (event.getExplosion().exploder instanceof EntityGTExplosive explosive) { if (explosive.dropsAllBlocks()) { - event.getAffectedEntities().removeIf(entity -> entity instanceof EntityItem); + event.getAffectedEntities().removeIf(entity -> entity instanceof EntityItem && !checkAEEntity(entity)); } } } + + private static boolean checkAEEntity(Entity entity) { + return Mods.AppliedEnergistics2.isModLoaded() && entity instanceof EntitySingularity; + } } From 251a9ac7306f76205d3505c8febea18066ce5a15 Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Thu, 4 Apr 2024 19:17:36 -0400 Subject: [PATCH 24/25] adjust recipe input expected cache size dynamically (#2331) --- src/main/java/gregtech/GregTechMod.java | 2 + .../api/persistence/PersistentData.java | 108 +++++++++++++++ .../api/recipes/GTRecipeInputCache.java | 124 ++++++++++++++---- 3 files changed, 210 insertions(+), 24 deletions(-) create mode 100644 src/main/java/gregtech/api/persistence/PersistentData.java diff --git a/src/main/java/gregtech/GregTechMod.java b/src/main/java/gregtech/GregTechMod.java index f76989a97d5..7e55e60b889 100644 --- a/src/main/java/gregtech/GregTechMod.java +++ b/src/main/java/gregtech/GregTechMod.java @@ -3,6 +3,7 @@ import gregtech.api.GTValues; import gregtech.api.GregTechAPI; import gregtech.api.modules.ModuleContainerRegistryEvent; +import gregtech.api.persistence.PersistentData; import gregtech.client.utils.BloomEffectUtil; import gregtech.modules.GregTechModules; import gregtech.modules.ModuleManager; @@ -50,6 +51,7 @@ public GregTechMod() { @EventHandler public void onConstruction(FMLConstructionEvent event) { + PersistentData.instance().init(); moduleManager = ModuleManager.getInstance(); GregTechAPI.moduleManager = moduleManager; moduleManager.registerContainer(new GregTechModules()); diff --git a/src/main/java/gregtech/api/persistence/PersistentData.java b/src/main/java/gregtech/api/persistence/PersistentData.java new file mode 100644 index 00000000000..dc88872d9a3 --- /dev/null +++ b/src/main/java/gregtech/api/persistence/PersistentData.java @@ -0,0 +1,108 @@ +package gregtech.api.persistence; + +import gregtech.api.GTValues; +import gregtech.api.util.GTLog; + +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fml.common.Loader; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +public final class PersistentData { + + private static final PersistentData INSTANCE = new PersistentData(); + + private @Nullable Path path; + private @Nullable NBTTagCompound tag; + + public static @NotNull PersistentData instance() { + return INSTANCE; + } + + private PersistentData() {} + + @ApiStatus.Internal + public void init() { + this.path = Loader.instance().getConfigDir().toPath() + .resolve(GTValues.MODID) + .resolve("persistent_data.dat"); + } + + /** + * @return the stored persistent data + */ + public synchronized @NotNull NBTTagCompound getTag() { + if (this.tag == null) { + this.tag = read(); + } + return this.tag; + } + + /** + * @return the read NBTTagCompound from disk + */ + private @NotNull NBTTagCompound read() { + GTLog.logger.debug("Reading persistent data from path {}", path); + if (this.path == null) { + throw new IllegalStateException("Persistent data path cannot be null"); + } + + if (!Files.exists(path)) { + return new NBTTagCompound(); + } + + try (InputStream inputStream = Files.newInputStream(this.path)) { + return CompressedStreamTools.readCompressed(inputStream); + } catch (IOException e) { + GTLog.logger.error("Failed to read persistent data", e); + return new NBTTagCompound(); + } + } + + /** + * Save the GT Persistent data to disk + */ + public synchronized void save() { + if (this.tag != null) { + write(this.tag); + } + } + + /** + * @param tagCompound the tag compound to save to disk + */ + private void write(@NotNull NBTTagCompound tagCompound) { + GTLog.logger.debug("Writing persistent data to path {}", path); + if (tagCompound.isEmpty()) { + return; + } + + if (this.path == null) { + throw new IllegalStateException("Persistent data path cannot be null"); + } + + if (!Files.exists(path)) { + try { + Files.createDirectories(path.getParent()); + } catch (IOException e) { + GTLog.logger.error("Could not create persistent data dir", e); + return; + } + } + + try (OutputStream outputStream = Files.newOutputStream(path)) { + CompressedStreamTools.writeCompressed(tagCompound, outputStream); + } catch (IOException e) { + GTLog.logger.error("Failed to write persistent data", e); + } + } +} diff --git a/src/main/java/gregtech/api/recipes/GTRecipeInputCache.java b/src/main/java/gregtech/api/recipes/GTRecipeInputCache.java index f72fb572f6e..4e9a68fdf03 100644 --- a/src/main/java/gregtech/api/recipes/GTRecipeInputCache.java +++ b/src/main/java/gregtech/api/recipes/GTRecipeInputCache.java @@ -1,11 +1,18 @@ package gregtech.api.recipes; import gregtech.api.GTValues; +import gregtech.api.persistence.PersistentData; import gregtech.api.recipes.ingredients.GTRecipeInput; import gregtech.api.util.GTLog; import gregtech.common.ConfigHolder; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.MathHelper; + +import it.unimi.dsi.fastutil.Hash; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collections; @@ -14,54 +21,77 @@ /** * Cache of GTRecipeInput instances for deduplication. *

    - * Each GTRecipeInput is cached by an internal hashtable, and any duplicative - * instances will be replaced by identical object previously created. + * Each GTRecipeInput is cached by an internal hashtable, and any duplicative instances will be replaced by identical + * object previously created. *

    - * Caching and duplication is only available during recipe registration; once - * recipe registration is over, the cache will be discarded and no further entries - * will be put into cache. + * Caching and duplication is only available during recipe registration; once recipe registration is over, the cache + * will be discarded and no further entries will be put into cache. */ -public class GTRecipeInputCache { +public final class GTRecipeInputCache { + + private static final int MINIMUM_CACHE_SIZE = 1 << 13; + private static final int MAXIMUM_CACHE_SIZE = 1 << 30; + + private static ObjectOpenHashSet instances; - private static final int EXPECTED_CACHE_SIZE = 16384; - private static ObjectOpenHashSet INSTANCES; + private static final String DATA_NAME = "expectedIngredientInstances"; + + private GTRecipeInputCache() {} public static boolean isCacheEnabled() { - return INSTANCES != null; + return instances != null; } + @ApiStatus.Internal public static void enableCache() { if (!isCacheEnabled()) { - INSTANCES = new ObjectOpenHashSet<>(EXPECTED_CACHE_SIZE, 1); - if (ConfigHolder.misc.debug || GTValues.isDeobfEnvironment()) - GTLog.logger.info("GTRecipeInput cache enabled"); + int size = calculateOptimalExpectedSize(); + instances = new ObjectOpenHashSet<>(size); + + if (ConfigHolder.misc.debug || GTValues.isDeobfEnvironment()) { + GTLog.logger.info("GTRecipeInput cache enabled with expected size {}", size); + } } } + @ApiStatus.Internal public static void disableCache() { if (isCacheEnabled()) { - if (ConfigHolder.misc.debug || GTValues.isDeobfEnvironment()) - GTLog.logger.info("GTRecipeInput cache disabled; releasing {} unique instances", INSTANCES.size()); - INSTANCES = null; + int size = instances.size(); + if (ConfigHolder.misc.debug || GTValues.isDeobfEnvironment()) { + GTLog.logger.info("GTRecipeInput cache disabled; releasing {} unique instances", size); + } + instances = null; + + if (size >= MINIMUM_CACHE_SIZE && size < MAXIMUM_CACHE_SIZE) { + NBTTagCompound tagCompound = PersistentData.instance().getTag(); + if (getExpectedInstanceAmount(tagCompound) != size) { + tagCompound.setInteger(DATA_NAME, size); + PersistentData.instance().save(); + } + } } } + private static int getExpectedInstanceAmount(@NotNull NBTTagCompound tagCompound) { + return MathHelper.clamp(tagCompound.getInteger(DATA_NAME), MINIMUM_CACHE_SIZE, MAXIMUM_CACHE_SIZE); + } + /** - * Tries to deduplicate the instance with previously cached instances. - * If there is no identical GTRecipeInput present in cache, the - * {@code recipeInput} will be put into cache, marked as cached, and returned subsequently. + * Tries to deduplicate the instance with previously cached instances. If there is no identical GTRecipeInput + * present in cache, the {@code recipeInput} will be put into cache, marked as cached, and returned subsequently. *

    * This operation returns {@code recipeInput} without doing anything if cache is disabled. * * @param recipeInput ingredient instance to be deduplicated - * @return Either previously cached instance, or {@code recipeInput} marked cached; - * or unmodified {@code recipeInput} instance if the cache is disabled + * @return Either previously cached instance, or {@code recipeInput} marked cached; or unmodified + * {@code recipeInput} instance if the cache is disabled */ public static GTRecipeInput deduplicate(GTRecipeInput recipeInput) { if (!isCacheEnabled() || recipeInput.isCached()) { return recipeInput; } - GTRecipeInput cached = INSTANCES.addOrGet(recipeInput); + GTRecipeInput cached = instances.addOrGet(recipeInput); if (cached == recipeInput) { // If recipeInput is cached just now... cached.setCached(); } @@ -69,9 +99,9 @@ public static GTRecipeInput deduplicate(GTRecipeInput recipeInput) { } /** - * Tries to deduplicate each instance in the list with previously cached instances. - * If there is no identical GTRecipeInput present in cache, the - * {@code recipeInput} will be put into cache, marked as cached, and returned subsequently. + * Tries to deduplicate each instance in the list with previously cached instances. If there is no identical + * GTRecipeInput present in cache, the {@code recipeInput} will be put into cache, marked as cached, and returned + * subsequently. *

    * This operation returns {@code inputs} without doing anything if cache is disabled. * @@ -91,4 +121,50 @@ public static List deduplicateInputs(List inputs) } return list; } + + /** + * Calculates the optimal expected size for the input cache: + *

      + *
    1. Pick a Load Factor to test: i.e. {@code 0.75f} (default).
    2. + *
    3. Pick a Size to test: i.e. {@code 8192}.
    4. + *
    5. Internal array's size: next highest power of 2 for {@code size / loadFactor}, + * {@code nextHighestPowerOf2(8192 / 0.75) = 16384}.
    6. + *
    7. The maximum amount of stored values before a rehash is required {@code arraySize * loadFactor}, + * {@code 16384 * 0.75 = 12288}.
    8. + *
    9. Compare with the known amount of values stored: {@code 12288 >= 11774}.
    10. + *
    11. If larger or equal, the initial capacity and load factor will not induce a rehash/resize.
    12. + *
    + * + * @return the optimal expected input cache size + */ + private static int calculateOptimalExpectedSize() { + int min = Math.max(getExpectedInstanceAmount(PersistentData.instance().getTag()), MINIMUM_CACHE_SIZE); + for (int i = 13; i < 31; i++) { + int sizeToTest = 1 << i; + int arraySize = nextHighestPowerOf2((int) (sizeToTest / Hash.DEFAULT_LOAD_FACTOR)); + int maxStoredBeforeRehash = (int) (arraySize * Hash.DEFAULT_LOAD_FACTOR); + + if (maxStoredBeforeRehash >= min) { + return sizeToTest; + } + } + return MINIMUM_CACHE_SIZE; + } + + /** + * Algorithm source. + * + * @param x the number to use + * @return the next highest power of 2 relative to the number + */ + private static int nextHighestPowerOf2(int x) { + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + return x; + } } From 16ed04a0d17f0341d85227e9e9f214ba9e02088f Mon Sep 17 00:00:00 2001 From: brachy84 <45517902+brachy84@users.noreply.github.com> Date: Fri, 5 Apr 2024 01:38:10 +0200 Subject: [PATCH 25/25] GroovyScript 1.0.0 (#2425) Co-authored-by: TechLord22 <37029404+TechLord22@users.noreply.github.com> --- dependencies.gradle | 2 +- src/main/java/gregtech/GregTechMod.java | 2 +- .../integration/groovy/GroovyExpansions.java | 27 ++ .../GroovyMaterialBuilderExpansion.java | 10 + .../groovy/GroovyScriptModule.java | 143 ++++--- .../integration/groovy/MaterialExpansion.java | 225 +++++++++++ .../groovy/MaterialPropertyExpansion.java | 355 ++++++++++++++++++ .../integration/groovy/PropertyContainer.java | 47 +++ .../groovy/VirtualizedRecipeMap.java | 2 +- 9 files changed, 760 insertions(+), 53 deletions(-) create mode 100644 src/main/java/gregtech/integration/groovy/MaterialExpansion.java create mode 100644 src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java create mode 100644 src/main/java/gregtech/integration/groovy/PropertyContainer.java diff --git a/dependencies.gradle b/dependencies.gradle index 49d93cc7bd5..4ab81db91bd 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -41,7 +41,7 @@ dependencies { // Published dependencies api("codechicken:codechickenlib:3.2.3.358") api("com.cleanroommc:modularui:2.4.3") { transitive = false } - api("com.cleanroommc:groovyscript:0.8.0") { transitive = false } + api("com.cleanroommc:groovyscript:1.0.1") { transitive = false } api("CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.684") api rfg.deobf("curse.maven:ae2-extended-life-570458:4402048") // AE2UEL 0.55.6 api rfg.deobf("curse.maven:ctm-267602:2915363") // CTM 1.0.2.31 diff --git a/src/main/java/gregtech/GregTechMod.java b/src/main/java/gregtech/GregTechMod.java index 7e55e60b889..883b581292c 100644 --- a/src/main/java/gregtech/GregTechMod.java +++ b/src/main/java/gregtech/GregTechMod.java @@ -33,7 +33,7 @@ dependencies = "required:forge@[14.23.5.2847,);" + "required-after:codechickenlib@[3.2.3,);" + "required-after:modularui@[2.3,);" + "required-after:mixinbooter@[8.0,);" + "after:appliedenergistics2;" + "after:forestry;" + "after:extrabees;" + "after:extratrees;" + "after:genetics;" + "after:magicbees;" + - "after:jei@[4.15.0,);" + "after:crafttweaker@[4.1.20,);" + "after:groovyscript@[0.7.0,);" + + "after:jei@[4.15.0,);" + "after:crafttweaker@[4.1.20,);" + "after:groovyscript@[1.0.1,);" + "after:theoneprobe;" + "after:hwyla;") public class GregTechMod { diff --git a/src/main/java/gregtech/integration/groovy/GroovyExpansions.java b/src/main/java/gregtech/integration/groovy/GroovyExpansions.java index 8c23fdf270f..e24191091e8 100644 --- a/src/main/java/gregtech/integration/groovy/GroovyExpansions.java +++ b/src/main/java/gregtech/integration/groovy/GroovyExpansions.java @@ -1,8 +1,13 @@ package gregtech.integration.groovy; +import gregtech.api.fluids.FluidBuilder; +import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.recipes.RecipeBuilder; +import gregtech.api.unification.Element; +import gregtech.api.unification.Elements; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.event.MaterialEvent; +import gregtech.api.unification.material.properties.ToolProperty; import net.minecraft.util.ResourceLocation; @@ -39,4 +44,26 @@ public static Material.Builder materialBuilder(MaterialEvent event, int id, Stri } return materialBuilder(event, id, new ResourceLocation(domain, path)); } + + public static ToolProperty.Builder toolBuilder(MaterialEvent event, float harvestSpeed, float attackDamage, + int durability, int harvestLevel) { + return ToolProperty.Builder.of(harvestSpeed, attackDamage, durability, harvestLevel); + } + + public static ToolProperty.Builder toolBuilder(MaterialEvent event) { + return toolBuilder(event, 1.0F, 1.0F, 100, 2); + } + + public static FluidBuilder fluidBuilder(MaterialEvent event) { + return new FluidBuilder(); + } + + public static Element addElement(MaterialEvent event, long protons, long neutrons, long halfLifeSeconds, + String decayTo, String name, String symbol, boolean isIsotope) { + return Elements.add(protons, neutrons, halfLifeSeconds, decayTo, name, symbol, isIsotope); + } + + public static FluidBuilder acidic(FluidBuilder builder) { + return builder.attributes(FluidAttributes.ACID); + } } diff --git a/src/main/java/gregtech/integration/groovy/GroovyMaterialBuilderExpansion.java b/src/main/java/gregtech/integration/groovy/GroovyMaterialBuilderExpansion.java index f4e30273435..2b67fa26844 100644 --- a/src/main/java/gregtech/integration/groovy/GroovyMaterialBuilderExpansion.java +++ b/src/main/java/gregtech/integration/groovy/GroovyMaterialBuilderExpansion.java @@ -8,6 +8,7 @@ import gregtech.api.unification.material.info.MaterialFlag; import gregtech.api.unification.material.info.MaterialIconSet; import gregtech.api.unification.material.properties.BlastProperty; +import gregtech.api.unification.material.properties.ToolProperty; import gregtech.api.unification.stack.MaterialStack; import net.minecraft.util.ResourceLocation; @@ -115,4 +116,13 @@ public static Material.Builder components(Material.Builder builder, Object... ob } return builder.components(materialStacks.toArray(new MaterialStack[0])); } + + public static Material.Builder toolStats(Material.Builder builder, ToolProperty.Builder toolBuilder) { + return builder.toolStats(toolBuilder.build()); + } + + public static Material.Builder toolStats(Material.Builder builder, float harvestSpeed, float attackDamage, + int durability, int harvestLevel) { + return builder.toolStats(ToolProperty.Builder.of(harvestSpeed, attackDamage, durability, harvestLevel).build()); + } } diff --git a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java index 571261241b2..e5082df1461 100644 --- a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java +++ b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java @@ -2,11 +2,14 @@ import gregtech.api.GTValues; import gregtech.api.GregTechAPI; +import gregtech.api.fluids.FluidBuilder; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.modules.GregTechModule; import gregtech.api.recipes.RecipeBuilder; import gregtech.api.recipes.RecipeMap; +import gregtech.api.unification.Element; +import gregtech.api.unification.Elements; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.event.MaterialEvent; import gregtech.api.unification.material.event.PostMaterialEvent; @@ -20,8 +23,6 @@ import gregtech.common.pipelike.fluidpipe.BlockFluidPipe; import gregtech.common.pipelike.itempipe.BlockItemPipe; import gregtech.integration.IntegrationSubmodule; -import gregtech.integration.crafttweaker.material.MaterialExpansion; -import gregtech.integration.crafttweaker.material.MaterialPropertyExpansion; import gregtech.modules.GregTechModules; import net.minecraft.item.ItemStack; @@ -35,24 +36,25 @@ import com.cleanroommc.groovyscript.GroovyScript; import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.api.GroovyPlugin; -import com.cleanroommc.groovyscript.api.IGameObjectHandler; +import com.cleanroommc.groovyscript.api.IGameObjectParser; +import com.cleanroommc.groovyscript.api.Result; import com.cleanroommc.groovyscript.compat.mods.GroovyContainer; import com.cleanroommc.groovyscript.compat.mods.ModPropertyContainer; -import com.cleanroommc.groovyscript.event.EventBusType; -import com.cleanroommc.groovyscript.event.GroovyEventManager; -import com.cleanroommc.groovyscript.gameobjects.GameObjectHandlerManager; +import com.cleanroommc.groovyscript.gameobjects.GameObjectHandler; import com.cleanroommc.groovyscript.helper.EnumHelper; -import com.cleanroommc.groovyscript.sandbox.LoadStage; import com.cleanroommc.groovyscript.sandbox.expand.ExpansionHelper; import com.google.common.collect.ImmutableList; -import groovy.lang.Closure; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.CompletionItemKind; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.Supplier; @@ -68,7 +70,7 @@ public class GroovyScriptModule extends IntegrationSubmodule implements GroovyPlugin { private static GroovyContainer modSupportContainer; - private static final Map> metaItems = new Object2ObjectOpenHashMap<>(); + private static final Object2ObjectOpenHashMap> metaItems = new Object2ObjectOpenHashMap<>(); @NotNull @Override @@ -87,12 +89,20 @@ public static boolean isCurrentlyRunning() { } public static > T parseAndValidateEnumValue(Class clazz, String raw, String type) { + return parseAndValidateEnumValue(clazz, raw, type, false); + } + + @Contract("_,_,_,true -> !null") + public static > T parseAndValidateEnumValue(Class clazz, String raw, String type, + boolean crash) { T t = EnumHelper.valueOfNullable(clazz, raw, false); if (t == null) { - GroovyLog.get().error("Can't find {} for {} in material builder. Valid values are {};", + String msg = GroovyLog.format("Can't find {} for {} in material builder. Valid values are {};", type, raw, Arrays.toString(clazz.getEnumConstants())); + if (crash) throw new NoSuchElementException(msg); + GroovyLog.get().error(msg); return null; } return t; @@ -216,57 +226,90 @@ public static void loadMetaItemBracketHandler() { return "GregTech"; } + @Optional.Method(modid = Mods.Names.GROOVY_SCRIPT) @Override public @Nullable ModPropertyContainer createModPropertyContainer() { - return new ModPropertyContainer() { - - public void materialEvent(EventPriority priority, Closure eventListener) { - if (isCurrentlyRunning() && GroovyScript.getSandbox().getCurrentLoader() != LoadStage.PRE_INIT) { - GroovyLog.get().error("GregTech's material event can only be used in pre init!"); - return; - } - GroovyEventManager.INSTANCE.listen(priority, EventBusType.FORGE, MaterialEvent.class, - eventListener); - } - - public void materialEvent(Closure eventListener) { - materialEvent(EventPriority.NORMAL, eventListener); - } - - public void lateMaterialEvent(EventPriority priority, Closure eventListener) { - if (isCurrentlyRunning() && GroovyScript.getSandbox().getCurrentLoader() != LoadStage.PRE_INIT) { - GroovyLog.get().error("GregTech's material event can only be used in pre init!"); - return; - } - GroovyEventManager.INSTANCE.listen(priority, EventBusType.FORGE, PostMaterialEvent.class, - eventListener); - } - - public void lateMaterialEvent(Closure eventListener) { - materialEvent(EventPriority.NORMAL, eventListener); - } - }; + return new PropertyContainer(); } @Override public void onCompatLoaded(GroovyContainer groovyContainer) { - modSupportContainer = groovyContainer; - GameObjectHandlerManager.registerGameObjectHandler(GTValues.MODID, "recipemap", - IGameObjectHandler.wrapStringGetter(RecipeMap::getByName)); - - GameObjectHandlerManager.registerGameObjectHandler(GTValues.MODID, "material", - IGameObjectHandler.wrapStringGetter(GregTechAPI.materialManager::getMaterial)); - - GameObjectHandlerManager.registerGameObjectHandler(GTValues.MODID, "oreprefix", - IGameObjectHandler.wrapStringGetter(OrePrefix::getPrefix)); - - GameObjectHandlerManager.registerGameObjectHandler(GTValues.MODID, "metaitem", - IGameObjectHandler.wrapStringGetter(GroovyScriptModule::getMetaItem), ItemStack.EMPTY); + GroovyScriptModule.modSupportContainer = groovyContainer; + GameObjectHandler.builder("recipemap", RecipeMap.class) + .mod(GTValues.MODID) + .parser(IGameObjectParser.wrapStringGetter(RecipeMap::getByName)) + .completerOfNamed(RecipeMap::getRecipeMaps, RecipeMap::getUnlocalizedName) + .register(); + GameObjectHandler.builder("material", Material.class) + .mod(GTValues.MODID) + .parser(IGameObjectParser.wrapStringGetter(GregTechAPI.materialManager::getMaterial)) + .completerOfNamed(GregTechAPI.materialManager::getRegisteredMaterials, + mat -> mat.getResourceLocation().toString()) + .register(); + + GameObjectHandler.builder("oreprefix", OrePrefix.class) + .mod(GTValues.MODID) + .parser(IGameObjectParser.wrapStringGetter(OrePrefix::getPrefix)) + .completerOfNamed(OrePrefix::values, v -> v.name) + .register(); + + GameObjectHandler.builder("metaitem", ItemStack.class) + .mod(GTValues.MODID) + .parser(IGameObjectParser.wrapStringGetter(GroovyScriptModule::getMetaItem)) + .completer((paramIndex, items) -> { + if (paramIndex != 0) return; + for (var iterator = metaItems.object2ObjectEntrySet().fastIterator(); iterator.hasNext();) { + var entry = iterator.next(); + String mod = entry.getKey(); + for (String key : entry.getValue().keySet()) { + var item = new CompletionItem(mod + ":" + key); + item.setKind(CompletionItemKind.Constant); + items.add(item); + } + } + }) + .register(); + + GameObjectHandler.builder("element", Element.class) + .mod(GTValues.MODID) + .parser((s, args) -> { + Element element = Elements.get(s); + if (element != null) return Result.some(element); + if (s.length() <= 6) { + for (Element element1 : Elements.getAllElements()) { + if (element1.symbol.equals(s)) { + return Result.some(element1); + } + } + } + return Result.error(); + }) + .completerOfNamed(Elements::getAllElements, Element::getName) + .register(); ExpansionHelper.mixinClass(Material.class, MaterialExpansion.class); ExpansionHelper.mixinClass(Material.class, MaterialPropertyExpansion.class); ExpansionHelper.mixinClass(Material.Builder.class, GroovyMaterialBuilderExpansion.class); ExpansionHelper.mixinMethod(RecipeBuilder.class, GroovyExpansions.class, "property"); ExpansionHelper.mixinMethod(MaterialEvent.class, GroovyExpansions.class, "materialBuilder"); + ExpansionHelper.mixinMethod(MaterialEvent.class, GroovyExpansions.class, "toolBuilder"); + ExpansionHelper.mixinMethod(MaterialEvent.class, GroovyExpansions.class, "fluidBuilder"); + ExpansionHelper.mixinMethod(PostMaterialEvent.class, GroovyExpansions.class, "toolBuilder"); + ExpansionHelper.mixinMethod(PostMaterialEvent.class, GroovyExpansions.class, "fluidBuilder"); + ExpansionHelper.mixinMethod(FluidBuilder.class, GroovyExpansions.class, "acidic"); + } + + protected static boolean checkFrozen(String description) { + if (!GregTechAPI.materialManager.canModifyMaterials()) { + GroovyLog.get().error("Cannot {} now, must be done in preInit loadStage and material event", description); + return true; + } + return false; + } + + protected static void logError(Material m, String cause, String type) { + GroovyLog.get().error( + "Cannot {0} of a Material with no {1}! Try calling \"add{1}\" in your late material event first if this is intentional. Material: {2}", + cause, type, m.getUnlocalizedName()); } } diff --git a/src/main/java/gregtech/integration/groovy/MaterialExpansion.java b/src/main/java/gregtech/integration/groovy/MaterialExpansion.java new file mode 100644 index 00000000000..70b92dd04d9 --- /dev/null +++ b/src/main/java/gregtech/integration/groovy/MaterialExpansion.java @@ -0,0 +1,225 @@ +package gregtech.integration.groovy; + +import gregtech.api.fluids.store.FluidStorageKeys; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.info.MaterialFlag; +import gregtech.api.unification.material.info.MaterialIconSet; +import gregtech.api.unification.material.properties.BlastProperty; +import gregtech.api.unification.material.properties.DustProperty; +import gregtech.api.unification.material.properties.FluidProperty; +import gregtech.api.unification.material.properties.OreProperty; +import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.unification.material.properties.ToolProperty; + +import net.minecraft.enchantment.Enchantment; + +import com.cleanroommc.groovyscript.api.GroovyLog; + +import static gregtech.integration.groovy.GroovyScriptModule.checkFrozen; +import static gregtech.integration.groovy.GroovyScriptModule.logError; + +@SuppressWarnings("unused") +public class MaterialExpansion { + + //////////////////////////////////// + // Material Methods // + //////////////////////////////////// + + public static void setFormula(Material m, String formula) { + setFormula(m, formula, false); + } + + public static void setFormula(Material m, String formula, boolean withFormatting) { + if (checkFrozen("set material chemical formula")) return; + m.setFormula(formula, withFormatting); + } + + public static boolean hasFlag(Material m, String flagName) { + return m.hasFlag(MaterialFlag.getByName(flagName)); + } + + public static void setIconSet(Material m, String iconSetName) { + if (checkFrozen("set material icon set")) return; + m.setMaterialIconSet(MaterialIconSet.getByName(iconSetName)); + } + + public static String getIconSet(Material m) { + return m.getMaterialIconSet().getName(); + } + + //////////////////////////////////// + // Fluid Property // + //////////////////////////////////// + + public static boolean isGaseous(Material m) { + FluidProperty prop = m.getProperty(PropertyKey.FLUID); + return prop != null && prop.getStorage().get(FluidStorageKeys.GAS) != null; + } + + /////////////////////////////////// + // Dust Property // + /////////////////////////////////// + + public static int harvestLevel(Material m) { + DustProperty prop = m.getProperty(PropertyKey.DUST); + if (prop != null) { + return prop.getHarvestLevel(); + } else logError(m, "get the harvest level", "Dust"); + return 0; + } + + public static int burnTime(Material m) { + DustProperty prop = m.getProperty(PropertyKey.DUST); + if (prop != null) { + return prop.getBurnTime(); + } else logError(m, "get the burn time", "Dust"); + return 0; + } + + public static void setHarvestLevel(Material m, int harvestLevel) { + if (checkFrozen("set harvest level")) return; + DustProperty prop = m.getProperty(PropertyKey.DUST); + if (prop != null) { + prop.setHarvestLevel(harvestLevel); + } else logError(m, "set the harvest level", "Dust"); + } + + public static void setBurnTime(Material m, int burnTime) { + if (checkFrozen("set burn time")) return; + DustProperty prop = m.getProperty(PropertyKey.DUST); + if (prop != null) { + prop.setBurnTime(burnTime); + } else logError(m, "set the burn time", "Dust"); + } + + /////////////////////////////////// + // Tool Property // + /////////////////////////////////// + public static float toolSpeed(Material m) { + ToolProperty prop = m.getProperty(PropertyKey.TOOL); + if (prop != null) { + return prop.getToolSpeed(); + } else logError(m, "get the tool speed", "Tool"); + return 0; + } + + public static float attackDamage(Material m) { + ToolProperty prop = m.getProperty(PropertyKey.TOOL); + if (prop != null) { + return prop.getToolAttackDamage(); + } else logError(m, "get the tool attack damage", "Tool"); + return 0; + } + + public static int toolDurability(Material m) { + ToolProperty prop = m.getProperty(PropertyKey.TOOL); + if (prop != null) { + return prop.getToolDurability(); + } else logError(m, "get the tool durability", "Tool"); + return 0; + } + + public static int toolHarvestLevel(Material m) { + ToolProperty prop = m.getProperty(PropertyKey.TOOL); + if (prop != null) { + return prop.getToolHarvestLevel(); + } else logError(m, "get the tool harvest level", "Tool"); + return 0; + } + + public static int toolEnchantability(Material m) { + ToolProperty prop = m.getProperty(PropertyKey.TOOL); + if (prop != null) { + return prop.getToolEnchantability(); + } else logError(m, "get the tool enchantability", "Tool"); + return 0; + } + + public static void addToolEnchantment(Material m, Enchantment enchantment, int level) { + addScaledToolEnchantment(m, enchantment, level, 0); + } + + public static void addScaledToolEnchantment(Material m, Enchantment enchantment, int level, double levelGrowth) { + if (checkFrozen("add tool enchantment")) return; + ToolProperty prop = m.getProperty(PropertyKey.TOOL); + if (prop != null) { + prop.addEnchantmentForTools(enchantment, level, levelGrowth); + } else logError(m, "change tool enchantments", "Tool"); + } + + public static void setToolStats(Material m, float toolSpeed, float toolAttackDamage, int toolDurability, + boolean shouldIngoreCraftingTools) { + setToolStats(m, toolSpeed, toolAttackDamage, toolDurability, 0, 0, shouldIngoreCraftingTools); + } + + public static void setToolStats(Material m, float toolSpeed, float toolAttackDamage, int toolDurability, + int enchantability, boolean shouldIngoreCraftingTools) { + setToolStats(m, toolSpeed, toolAttackDamage, toolDurability, enchantability, 0, shouldIngoreCraftingTools); + } + + public static void setToolStats(Material m, float toolSpeed, float toolAttackDamage, int toolDurability) { + setToolStats(m, toolSpeed, toolAttackDamage, toolDurability, 0, 0, false); + } + + public static void setToolStats(Material m, float toolSpeed, float toolAttackDamage, int toolDurability, + int enchantability) { + setToolStats(m, toolSpeed, toolAttackDamage, toolDurability, enchantability, 0, false); + } + + public static void setToolStats(Material m, float toolSpeed, float toolAttackDamage, int toolDurability, + int enchantability, int toolHarvestLevel) { + setToolStats(m, toolSpeed, toolAttackDamage, toolDurability, enchantability, toolHarvestLevel, false); + } + + public static void setToolStats(Material m, float toolSpeed, float toolAttackDamage, int toolDurability, + int enchantability, int toolHarvestLevel, + boolean shouldIngoreCraftingTools) { + if (checkFrozen("set tool stats")) return; + ToolProperty prop = m.getProperty(PropertyKey.TOOL); + if (prop != null) { + prop.setToolSpeed(toolSpeed); + prop.setToolAttackDamage(toolAttackDamage); + prop.setToolDurability(toolDurability); + prop.setToolHarvestLevel(toolHarvestLevel == 0 ? 2 : toolHarvestLevel); + prop.setToolEnchantability(enchantability == 0 ? 10 : enchantability); + prop.setShouldIgnoreCraftingTools(shouldIngoreCraftingTools); + } else logError(m, "change tool stats", "Tool"); + } + + // Wire/Item Pipe/Fluid Pipe stuff? + + //////////////////////////////////// + // Blast Property // + //////////////////////////////////// + + public static void setBlastTemp(Material m, int blastTemp) { + if (checkFrozen("set blast temperature")) return; + if (blastTemp <= 0) { + GroovyLog.get().error("Blast Temperature must be greater than zero! Material: " + m.getUnlocalizedName()); + return; + } + BlastProperty prop = m.getProperty(PropertyKey.BLAST); + if (prop != null) prop.setBlastTemperature(blastTemp); + else m.setProperty(PropertyKey.BLAST, new BlastProperty(blastTemp)); + } + + public static int blastTemp(Material m) { + BlastProperty prop = m.getProperty(PropertyKey.BLAST); + if (prop != null) { + return prop.getBlastTemperature(); + } else logError(m, "get blast temperature", "Blast"); + return 0; + } + + //////////////////////////////////// + // Ore Property // + //////////////////////////////////// + + public static int oreMultiplier(Material m) { + OreProperty prop = m.getProperty(PropertyKey.ORE); + if (prop != null) { + return prop.getOreMultiplier(); + } else logError(m, "get ore multiplier", "Ore"); + return 0; + } +} diff --git a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java new file mode 100644 index 00000000000..83ceb1b27a7 --- /dev/null +++ b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java @@ -0,0 +1,355 @@ +package gregtech.integration.groovy; + +import gregtech.api.fluids.FluidBuilder; +import gregtech.api.fluids.FluidState; +import gregtech.api.fluids.attribute.FluidAttributes; +import gregtech.api.fluids.store.FluidStorageKey; +import gregtech.api.fluids.store.FluidStorageKeys; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.properties.BlastProperty; +import gregtech.api.unification.material.properties.DustProperty; +import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.api.unification.material.properties.FluidProperty; +import gregtech.api.unification.material.properties.GemProperty; +import gregtech.api.unification.material.properties.IngotProperty; +import gregtech.api.unification.material.properties.ItemPipeProperties; +import gregtech.api.unification.material.properties.OreProperty; +import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.unification.material.properties.ToolProperty; +import gregtech.api.unification.material.properties.WireProperties; +import gregtech.api.unification.material.properties.WoodProperty; + +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; + +import static gregtech.integration.groovy.GroovyScriptModule.checkFrozen; + +@SuppressWarnings("unused") +public class MaterialPropertyExpansion { + + ///////////////////////////////////// + // Property Checkers // + ///////////////////////////////////// + + public static boolean hasBlastTemp(Material m) { + return m.hasProperty(PropertyKey.BLAST); + } + + public static boolean hasDust(Material m) { + return m.hasProperty(PropertyKey.DUST); + } + + public static boolean hasFluidPipes(Material m) { + return m.hasProperty(PropertyKey.FLUID_PIPE); + } + + public static boolean hasFluid(Material m) { + return m.hasProperty(PropertyKey.FLUID); + } + + public static boolean hasGem(Material m) { + return m.hasProperty(PropertyKey.GEM); + } + + public static boolean hasIngot(Material m) { + return m.hasProperty(PropertyKey.INGOT); + } + + public static boolean hasItemPipes(Material m) { + return m.hasProperty(PropertyKey.ITEM_PIPE); + } + + public static boolean hasOre(Material m) { + return m.hasProperty(PropertyKey.ORE); + } + + public static boolean hasTools(Material m) { + return m.hasProperty(PropertyKey.TOOL); + } + + public static boolean hasWires(Material m) { + return m.hasProperty(PropertyKey.WIRE); + } + + //////////////////////////////////// + // Property Setters // + //////////////////////////////////// + + public static void addBlastTemp(Material m, int blastTemp) { + if (checkFrozen("add blast temperature")) return; + if (m.hasProperty(PropertyKey.BLAST)) m.getProperty(PropertyKey.BLAST).setBlastTemperature(blastTemp); + else m.setProperty(PropertyKey.BLAST, new BlastProperty(blastTemp)); + } + + public static void addBlastProperty(Material m, int blastTemp) { + addBlastProperty(m, blastTemp, null, 0, 0, 0, 0); + } + + public static void addBlastProperty(Material m, int blastTemp, String gasTier) { + addBlastProperty(m, blastTemp, gasTier, 0, 0, 0, 0); + } + + public static void addBlastProperty(Material m, int blastTemp, String gasTier, + int durationOverride) { + addBlastProperty(m, blastTemp, gasTier, durationOverride, 0, 0, 0); + } + + public static void addBlastProperty(Material m, int blastTemp, String gasTier, + int durationOverride, int eutOverride) { + addBlastProperty(m, blastTemp, gasTier, durationOverride, eutOverride, 0, 0); + } + + public static void addBlastProperty(Material m, int blastTemp, String gasTier, + int durationOverride, int eutOverride, + int vacuumDurationOverride, int vacuumEUtOverride) { + if (checkFrozen("add blast property")) return; + if (m.hasProperty(PropertyKey.BLAST)) { + BlastProperty property = m.getProperty(PropertyKey.BLAST); + property.setBlastTemperature(blastTemp); + if (gasTier != null) property.setGasTier(BlastProperty.validateGasTier(gasTier)); + if (durationOverride != 0) property.setDurationOverride(durationOverride); + if (eutOverride != 0) property.setEutOverride(eutOverride); + if (vacuumDurationOverride != 0) property.setVacuumDurationOverride(vacuumDurationOverride); + if (vacuumEUtOverride != 0) property.setVacuumEutOverride(vacuumEUtOverride); + } else { + BlastProperty.Builder builder = new BlastProperty.Builder(); + builder.temp(blastTemp, + gasTier == null ? BlastProperty.GasTier.LOW : BlastProperty.validateGasTier(gasTier)); + builder.blastStats(durationOverride == 0 ? -1 : durationOverride, eutOverride == 0 ? -1 : eutOverride); + builder.vacuumStats(vacuumEUtOverride == 0 ? -1 : vacuumEUtOverride, + vacuumDurationOverride == 0 ? -1 : vacuumDurationOverride); + m.setProperty(PropertyKey.BLAST, builder.build()); + } + } + + public static void addDust(Material m) { + addDust(m, 0, 0); + } + + public static void addDust(Material m, int harvestLevel) { + addDust(m, harvestLevel, 0); + } + + public static void addDust(Material m, int harvestLevel, int burnTime) { + if (checkFrozen("add a dust to a material")) return; + if (harvestLevel == 0) harvestLevel = 2; + if (m.hasProperty(PropertyKey.DUST)) { + m.getProperty(PropertyKey.DUST).setHarvestLevel(harvestLevel); + m.getProperty(PropertyKey.DUST).setBurnTime(burnTime); + } else m.setProperty(PropertyKey.DUST, new DustProperty(harvestLevel, burnTime)); + } + + public static void addWood(Material m) { + if (checkFrozen("add a wood to a material")) return; + if (!m.hasProperty(PropertyKey.WOOD)) { + m.setProperty(PropertyKey.WOOD, new WoodProperty()); + } + } + + public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof) { + addFluidPipes(m, maxFluidTemperature, throughput, gasProof, false, false, false); + } + + public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof, + boolean acidProof, boolean cryoProof, boolean plasmaProof) { + if (checkFrozen("add fluid pipes to a material")) return; + if (m.hasProperty(PropertyKey.FLUID_PIPE)) { + m.getProperty(PropertyKey.FLUID_PIPE).setMaxFluidTemperature(maxFluidTemperature); + m.getProperty(PropertyKey.FLUID_PIPE).setThroughput(throughput); + m.getProperty(PropertyKey.FLUID_PIPE).setGasProof(gasProof); + m.getProperty(PropertyKey.FLUID_PIPE).setCanContain(FluidAttributes.ACID, acidProof); + m.getProperty(PropertyKey.FLUID_PIPE).setCryoProof(cryoProof); + m.getProperty(PropertyKey.FLUID_PIPE).setPlasmaProof(plasmaProof); + } else { + m.setProperty(PropertyKey.FLUID_PIPE, new FluidPipeProperties(maxFluidTemperature, throughput, gasProof, + acidProof, cryoProof, plasmaProof)); + } + } + + @GroovyBlacklist + private static void addFluidInternal(Material m, FluidStorageKey key, FluidBuilder builder) { + if (checkFrozen("add a Fluid to a material")) return; + FluidProperty property = m.getProperty(PropertyKey.FLUID); + if (property == null) { + property = new FluidProperty(); + m.setProperty(PropertyKey.FLUID, property); + } + property.getStorage().enqueueRegistration(key, builder); + } + + public static void addLiquid(Material m, FluidBuilder builder) { + addFluidInternal(m, FluidStorageKeys.LIQUID, builder.state(FluidState.LIQUID)); + } + + public static void addLiquid(Material m) { + addLiquid(m, new FluidBuilder()); + } + + public static void addFluid(Material m) { + addLiquid(m); + } + + @Deprecated + public static void addFluid(Material m, String fluidTypeName) { + addFluid(m, fluidTypeName, false); + } + + @Deprecated + public static void addFluid(Material m, String fluidTypeName, boolean hasBlock) { + GroovyLog.get().error("The usage of `material.addFluid(String, boolean)` is strongly discouraged. " + + "Please use `addLiquid()`, `addGas()` or `addPlasma()` with or without `FluidBuilder`."); + if (checkFrozen("add a Fluid to a material")) return; + FluidState type = GroovyScriptModule.parseAndValidateEnumValue(FluidState.class, fluidTypeName, "fluid type", + true); + FluidStorageKey storageKey = switch (type) { + case LIQUID -> FluidStorageKeys.LIQUID; + case GAS -> FluidStorageKeys.GAS; + case PLASMA -> FluidStorageKeys.PLASMA; + }; + FluidBuilder builder = new FluidBuilder(); + builder.state(type); + if (hasBlock) builder.block(); + addFluidInternal(m, storageKey, builder); + } + + public static void addGas(Material m, FluidBuilder builder) { + addFluidInternal(m, FluidStorageKeys.GAS, builder.state(FluidState.GAS)); + } + + public static void addGas(Material m) { + addGas(m, new FluidBuilder()); + } + + public static void addPlasma(Material m, FluidBuilder builder) { + addFluidInternal(m, FluidStorageKeys.PLASMA, builder.state(FluidState.PLASMA)); + } + + public static void addPlasma(Material m) { + addPlasma(m, new FluidBuilder()); + } + + public static void addGem(Material m) { + if (checkFrozen("add a Gem to a material")) return; + if (!m.hasProperty(PropertyKey.GEM)) m.setProperty(PropertyKey.GEM, new GemProperty()); + } + + public static void addIngot(Material m) { + if (checkFrozen("add an Ingot to a material")) return; + if (!m.hasProperty(PropertyKey.INGOT)) m.setProperty(PropertyKey.INGOT, new IngotProperty()); + } + + public static void addOre(Material m) { + addOre(m, false); + } + + public static void addOre(Material m, boolean emissive) { + addOre(m, 0, 0, emissive); + } + + public static void addOre(Material m, int oreMultiplier, int byproductMultiplier) { + addOre(m, oreMultiplier, byproductMultiplier, false); + } + + public static void addOre(Material m, int oreMultiplier, int byproductMultiplier, boolean emissive) { + if (checkFrozen("add an Ore to a material")) return; + oreMultiplier = oreMultiplier == 0 ? 1 : oreMultiplier; + byproductMultiplier = byproductMultiplier == 0 ? 1 : byproductMultiplier; + if (m.hasProperty(PropertyKey.ORE)) { + m.getProperty(PropertyKey.ORE).setOreMultiplier(oreMultiplier); + m.getProperty(PropertyKey.ORE).setByProductMultiplier(byproductMultiplier); + m.getProperty(PropertyKey.ORE).setEmissive(emissive); + } else m.setProperty(PropertyKey.ORE, new OreProperty(oreMultiplier, byproductMultiplier, emissive)); + } + + public static void addItemPipes(Material m, int priority, float transferRate) { + if (checkFrozen("add Item Pipes to a material")) return; + if (m.hasProperty(PropertyKey.ITEM_PIPE)) { + m.getProperty(PropertyKey.ITEM_PIPE).setPriority(priority); + m.getProperty(PropertyKey.ITEM_PIPE).setTransferRate(transferRate); + } else m.setProperty(PropertyKey.ITEM_PIPE, new ItemPipeProperties(priority, transferRate)); + } + + public static void addTools(Material m, ToolProperty.Builder builder) { + addTools(m, builder.build()); + } + + public static void addTools(Material m, ToolProperty prop) { + if (checkFrozen("add Tools to a material")) return; + ToolProperty property = m.getProperty(PropertyKey.TOOL); + if (property != null) { + property.setToolSpeed(prop.getToolSpeed()); + property.setToolAttackDamage(prop.getToolAttackDamage()); + property.setToolDurability(prop.getToolDurability()); + property.setToolHarvestLevel(prop.getToolHarvestLevel()); + property.setToolAttackSpeed(prop.getToolAttackSpeed()); + property.setToolEnchantability(prop.getToolEnchantability()); + property.setMagnetic(prop.isMagnetic()); + property.setUnbreakable(prop.getUnbreakable()); + property.setShouldIgnoreCraftingTools(prop.getShouldIgnoreCraftingTools()); + property.setDurabilityMultiplier(prop.getDurabilityMultiplier()); + } else { + m.setProperty(PropertyKey.TOOL, prop); + } + } + + public static void addTools(Material m, float toolSpeed, float toolAttackDamage, float toolAttackSpeed, + int toolDurability) { + addTools(m, toolSpeed, toolAttackDamage, toolAttackSpeed, toolDurability, 0, 10, 1); + } + + public static void addTools(Material m, float toolSpeed, float toolAttackDamage, float toolAttackSpeed, + int toolDurability, int toolHarvestLevel) { + addTools(m, toolSpeed, toolAttackDamage, toolAttackSpeed, toolDurability, toolHarvestLevel, 10, 1); + } + + public static void addTools(Material m, float toolSpeed, float toolAttackDamage, float toolAttackSpeed, + int toolDurability, int toolHarvestLevel, int toolEnchantability) { + addTools(m, toolSpeed, toolAttackDamage, toolAttackSpeed, toolDurability, toolHarvestLevel, toolEnchantability, + 1); + } + + public static void addTools(Material m, float toolSpeed, float toolAttackDamage, float toolAttackSpeed, + int toolDurability, int toolHarvestLevel, int toolEnchantability, + int durabilityMultiplier) { + if (toolEnchantability == 0) toolEnchantability = 10; + if (durabilityMultiplier <= 0) durabilityMultiplier = 1; + addTools(m, ToolProperty.Builder.of(toolSpeed, toolAttackDamage, toolDurability, toolHarvestLevel) + .attackSpeed(toolAttackSpeed) + .enchantability(toolEnchantability) + .durabilityMultiplier(durabilityMultiplier)); + } + + public static void addWires(Material m, int voltage, int baseAmperage, int lossPerBlock) { + addWires(m, voltage, baseAmperage, lossPerBlock, false, 0); + } + + public static void addWires(Material m, int voltage, int baseAmperage, int lossPerBlock, boolean isSuperCon) { + addWires(m, voltage, baseAmperage, lossPerBlock, isSuperCon, 0); + } + + public static void addWires(Material m, int voltage, int baseAmperage, int lossPerBlock, boolean isSuperCon, + int criticalTemp) { + if (checkFrozen("add Wires to a material")) return; + if (m.hasProperty(PropertyKey.WIRE)) { + m.getProperty(PropertyKey.WIRE).setVoltage(voltage); + m.getProperty(PropertyKey.WIRE).setAmperage(baseAmperage); + m.getProperty(PropertyKey.WIRE).setLossPerBlock(lossPerBlock); + m.getProperty(PropertyKey.WIRE).setSuperconductor(isSuperCon); + m.getProperty(PropertyKey.WIRE).setSuperconductorCriticalTemperature(criticalTemp); + } else m.setProperty(PropertyKey.WIRE, + new WireProperties(voltage, baseAmperage, lossPerBlock, isSuperCon, criticalTemp)); + } + + public static void addCables(Material m, int voltage, int baseAmperage, int lossPerBlock) { + addWires(m, voltage, baseAmperage, lossPerBlock, false, 0); + } + + public static void addCables(Material m, int voltage, int baseAmperage, int lossPerBlock, boolean isSuperCon) { + addWires(m, voltage, baseAmperage, lossPerBlock, isSuperCon, 0); + } + + public static void addCables(Material m, int voltage, int baseAmperage, int lossPerBlock, boolean isSuperCon, + int criticalTemp) { + addWires(m, voltage, baseAmperage, lossPerBlock, isSuperCon, criticalTemp); + } +} diff --git a/src/main/java/gregtech/integration/groovy/PropertyContainer.java b/src/main/java/gregtech/integration/groovy/PropertyContainer.java new file mode 100644 index 00000000000..35da8ce4905 --- /dev/null +++ b/src/main/java/gregtech/integration/groovy/PropertyContainer.java @@ -0,0 +1,47 @@ +package gregtech.integration.groovy; + +import gregtech.api.unification.material.event.MaterialEvent; +import gregtech.api.unification.material.event.PostMaterialEvent; + +import net.minecraftforge.fml.common.eventhandler.EventPriority; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.compat.mods.ModPropertyContainer; +import com.cleanroommc.groovyscript.event.EventBusType; +import com.cleanroommc.groovyscript.event.GroovyEventManager; +import com.cleanroommc.groovyscript.sandbox.ClosureHelper; +import com.cleanroommc.groovyscript.sandbox.LoadStage; +import groovy.lang.Closure; +import groovy.lang.DelegatesTo; + +public class PropertyContainer extends ModPropertyContainer { + + public void materialEvent(EventPriority priority, @DelegatesTo(MaterialEvent.class) Closure eventListener) { + if (GroovyScriptModule.isCurrentlyRunning() && + GroovyScript.getSandbox().getCurrentLoader() != LoadStage.PRE_INIT) { + GroovyLog.get().error("GregTech's material event can only be used in pre init!"); + return; + } + ClosureHelper.withEnvironment(eventListener, new MaterialEvent(), true); + GroovyEventManager.INSTANCE.listen(priority, EventBusType.MAIN, MaterialEvent.class, eventListener); + } + + public void materialEvent(Closure eventListener) { + materialEvent(EventPriority.NORMAL, eventListener); + } + + public void lateMaterialEvent(EventPriority priority, Closure eventListener) { + if (GroovyScriptModule.isCurrentlyRunning() && + GroovyScript.getSandbox().getCurrentLoader() != LoadStage.PRE_INIT) { + GroovyLog.get().error("GregTech's material event can only be used in pre init!"); + return; + } + GroovyEventManager.INSTANCE.listen(priority, EventBusType.MAIN, PostMaterialEvent.class, + eventListener); + } + + public void lateMaterialEvent(Closure eventListener) { + materialEvent(EventPriority.NORMAL, eventListener); + } +} diff --git a/src/main/java/gregtech/integration/groovy/VirtualizedRecipeMap.java b/src/main/java/gregtech/integration/groovy/VirtualizedRecipeMap.java index a2dbf7a3d55..6bd80f4db05 100644 --- a/src/main/java/gregtech/integration/groovy/VirtualizedRecipeMap.java +++ b/src/main/java/gregtech/integration/groovy/VirtualizedRecipeMap.java @@ -23,7 +23,7 @@ public class VirtualizedRecipeMap extends VirtualizedRegistry { public VirtualizedRecipeMap(RecipeMap recipeMap) { super(Alias.generateOf(recipeMap.unlocalizedName, CaseFormat.LOWER_UNDERSCORE)); this.recipeMap = recipeMap; - GroovyScriptModule.getInstance().getVirtualizedRegistrar().addRegistry(this); + GroovyScriptModule.getInstance().getRegistrar().addRegistry(this); } @Override