From 80e4728f98d4a9f528e3c0f58fbb4208318855bd Mon Sep 17 00:00:00 2001 From: Johannes Lundberg Date: Fri, 24 Nov 2023 10:06:05 -0700 Subject: [PATCH 1/5] Add simple thermostat tube module --- .../desht/pneumaticcraft/api/lib/Names.java | 1 + .../recipes/misc/thermostat_module.json | 35 +++ .../recipes/thermostat_module.json | 23 ++ .../pneumaticcraft/client/ClientSetup.java | 4 + .../tubemodule/ThermostatModuleScreen.java | 93 +++++++ .../client/model/PNCModelLayers.java | 1 + .../tube_module/ThermostatRenderer.java | 124 +++++++++ .../pneumaticcraft/common/core/ModItems.java | 2 + .../common/network/NetworkHandler.java | 4 + .../PacketSyncThermostatModuleToClient.java | 77 ++++++ .../PacketSyncThermostatModuleToServer.java | 78 ++++++ .../tubemodules/ModuleNetworkManager.java | 2 +- .../common/tubemodules/RedstoneModule.java | 6 + .../common/tubemodules/ThermostatModule.java | 211 +++++++++++++++ .../datagen/ModRecipeProvider.java | 7 + .../me/desht/pneumaticcraft/lib/Textures.java | 2 + .../assets/pneumaticcraft/lang/en_us.json | 6 + .../models/item/thermostat_module.json | 243 ++++++++++++++++++ .../pnc_model/modules/thermostat_module.png | Bin 0 -> 5533 bytes .../modules/thermostat_module_upgraded.png | Bin 0 -> 3522 bytes 20 files changed, 918 insertions(+), 1 deletion(-) create mode 100644 src/generated/resources/data/pneumaticcraft/advancements/recipes/misc/thermostat_module.json create mode 100644 src/generated/resources/data/pneumaticcraft/recipes/thermostat_module.json create mode 100644 src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java create mode 100644 src/main/java/me/desht/pneumaticcraft/client/render/tube_module/ThermostatRenderer.java create mode 100644 src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToClient.java create mode 100644 src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToServer.java create mode 100644 src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java create mode 100644 src/main/resources/assets/pneumaticcraft/models/item/thermostat_module.json create mode 100644 src/main/resources/assets/pneumaticcraft/textures/pnc_model/modules/thermostat_module.png create mode 100644 src/main/resources/assets/pneumaticcraft/textures/pnc_model/modules/thermostat_module_upgraded.png diff --git a/src/api/java/me/desht/pneumaticcraft/api/lib/Names.java b/src/api/java/me/desht/pneumaticcraft/api/lib/Names.java index 6f19c0535..aafac5044 100644 --- a/src/api/java/me/desht/pneumaticcraft/api/lib/Names.java +++ b/src/api/java/me/desht/pneumaticcraft/api/lib/Names.java @@ -34,6 +34,7 @@ public class Names { public static final ResourceLocation MODULE_LOGISTICS = RL("logistics_module"); public static final ResourceLocation MODULE_REDSTONE = RL("redstone_module"); public static final ResourceLocation MODULE_VACUUM = RL("vacuum_module"); + public static final ResourceLocation MODULE_THERMOSTAT = RL("thermostat_module"); public static final String PNEUMATIC_KEYBINDING_CATEGORY_MAIN = "key.pneumaticcraft.category.main"; public static final String PNEUMATIC_KEYBINDING_CATEGORY_UPGRADE_TOGGLES = "key.pneumaticcraft.category.upgrade_toggles"; diff --git a/src/generated/resources/data/pneumaticcraft/advancements/recipes/misc/thermostat_module.json b/src/generated/resources/data/pneumaticcraft/advancements/recipes/misc/thermostat_module.json new file mode 100644 index 000000000..08db87bf0 --- /dev/null +++ b/src/generated/resources/data/pneumaticcraft/advancements/recipes/misc/thermostat_module.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingot_iron_compressed": { + "conditions": { + "items": [ + { + "items": [ + "pneumaticcraft:ingot_iron_compressed" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "pneumaticcraft:thermostat_module" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingot_iron_compressed", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "pneumaticcraft:thermostat_module" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/pneumaticcraft/recipes/thermostat_module.json b/src/generated/resources/data/pneumaticcraft/recipes/thermostat_module.json new file mode 100644 index 000000000..8e916b3b5 --- /dev/null +++ b/src/generated/resources/data/pneumaticcraft/recipes/thermostat_module.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "D": { + "item": "minecraft:comparator" + }, + "R": { + "tag": "forge:dusts/redstone" + }, + "T": { + "item": "pneumaticcraft:pressure_tube" + } + }, + "pattern": [ + " R ", + "TDT" + ], + "result": { + "item": "pneumaticcraft:thermostat_module" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/main/java/me/desht/pneumaticcraft/client/ClientSetup.java b/src/main/java/me/desht/pneumaticcraft/client/ClientSetup.java index a46790f54..a70daaef8 100644 --- a/src/main/java/me/desht/pneumaticcraft/client/ClientSetup.java +++ b/src/main/java/me/desht/pneumaticcraft/client/ClientSetup.java @@ -12,6 +12,7 @@ import me.desht.pneumaticcraft.client.gui.tubemodule.LogisticsModuleScreen; import me.desht.pneumaticcraft.client.gui.tubemodule.PressureGaugeModuleScreen; import me.desht.pneumaticcraft.client.gui.tubemodule.RedstoneModuleScreen; +import me.desht.pneumaticcraft.client.gui.tubemodule.ThermostatModuleScreen; import me.desht.pneumaticcraft.client.gui.upgrademanager.*; import me.desht.pneumaticcraft.client.model.ModelMinigun; import me.desht.pneumaticcraft.client.model.PNCModelLayers; @@ -206,6 +207,7 @@ public static void registerLayerDefinitions(EntityRenderersEvent.RegisterLayerDe event.registerLayerDefinition(PNCModelLayers.REGULATOR_MODULE, RegulatorRenderer::createBodyLayer); event.registerLayerDefinition(PNCModelLayers.SAFETY_VALVE_MODULE, SafetyValveRenderer::createBodyLayer); event.registerLayerDefinition(PNCModelLayers.VACUUM_MODULE, VacuumRenderer::createBodyLayer); + event.registerLayerDefinition(PNCModelLayers.THERMOSTAT_MODULE, ThermostatRenderer::createBodyLayer); } private static void registerItemModelProperties() { @@ -416,6 +418,7 @@ private static void registerTubeModuleFactories() { TubeModuleClientRegistry.registerTubeModuleGUI(Names.MODULE_SAFETY_VALVE, PressureGaugeModuleScreen::createGUI); TubeModuleClientRegistry.registerTubeModuleGUI(Names.MODULE_REDSTONE, RedstoneModuleScreen::new); TubeModuleClientRegistry.registerTubeModuleGUI(Names.MODULE_LOGISTICS, LogisticsModuleScreen::new); + TubeModuleClientRegistry.registerTubeModuleGUI(Names.MODULE_THERMOSTAT, ThermostatModuleScreen::new); TubeModuleClientRegistry.registerTubeModuleRenderer(Names.MODULE_AIR_GRATE, AirGrateRenderer::new); TubeModuleClientRegistry.registerTubeModuleRenderer(Names.MODULE_REDSTONE, RedstoneRenderer::new); @@ -426,6 +429,7 @@ private static void registerTubeModuleFactories() { TubeModuleClientRegistry.registerTubeModuleRenderer(Names.MODULE_FLOW_DETECTOR, FlowDetectorRenderer::new); TubeModuleClientRegistry.registerTubeModuleRenderer(Names.MODULE_LOGISTICS, LogisticsRenderer::new); TubeModuleClientRegistry.registerTubeModuleRenderer(Names.MODULE_VACUUM, VacuumRenderer::new); + TubeModuleClientRegistry.registerTubeModuleRenderer(Names.MODULE_THERMOSTAT, ThermostatRenderer::new); } private static void registerArmorClientUpgradeHandlers() { diff --git a/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java b/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java new file mode 100644 index 000000000..5d6d32a27 --- /dev/null +++ b/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java @@ -0,0 +1,93 @@ +/* + * This file is part of pnc-repressurized. + * + * pnc-repressurized is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pnc-repressurized is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pnc-repressurized. If not, see . + */ + +package me.desht.pneumaticcraft.client.gui.tubemodule; + +import me.desht.pneumaticcraft.client.gui.widget.WidgetColorSelector; +import me.desht.pneumaticcraft.client.gui.widget.WidgetLabel; +import me.desht.pneumaticcraft.client.gui.widget.WidgetTextField; +import me.desht.pneumaticcraft.client.gui.widget.WidgetTextFieldNumber; +import me.desht.pneumaticcraft.common.network.NetworkHandler; +import me.desht.pneumaticcraft.common.network.PacketSyncThermostatModuleToServer; +import me.desht.pneumaticcraft.common.network.PacketTubeModuleColor; +import me.desht.pneumaticcraft.common.tubemodules.ThermostatModule; +import me.desht.pneumaticcraft.lib.Textures; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.DyeColor; + +import static me.desht.pneumaticcraft.common.util.PneumaticCraftUtils.xlate; + +public class ThermostatModuleScreen extends AbstractTubeModuleScreen { + private int color; + private int threshold; + private WidgetTextFieldNumber thresholdField; + + public ThermostatModuleScreen(ThermostatModule module) { + super(module); + + ySize = 57; + } + + @Override + public void init() { + super.init(); + + color = module.getColorChannel(); + threshold = module.getThreshold(); + + addLabel(getTitle(), guiLeft + xSize / 2, guiTop + 5, WidgetLabel.Alignment.CENTRE); + + int x = guiLeft + 10; + int y = guiTop + 24; + WidgetLabel colorLabel; + addRenderableWidget(colorLabel = new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.channel"))); + + x = guiLeft + 10 + colorLabel.getWidth() + 10; + addRenderableWidget(new WidgetColorSelector(x, y-4, w -> color = w.getColor().getId()) + .withInitialColor(DyeColor.byId(color))); + + x = guiLeft + 10; + y = guiTop + 22 + colorLabel.getHeight() + 10; + WidgetLabel thresholdLabel; + addRenderableWidget(thresholdLabel = new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.simpleConfig.threshold"))); + + x = guiLeft + 10 + thresholdLabel.getWidth() + 5; + thresholdField = new WidgetTextFieldNumber(font, x, y-1, 30, font.lineHeight + 2).setDecimals(0); + addRenderableWidget(thresholdField); + thresholdField.setWidth(40); + setInitialFocus(thresholdField); + thresholdField.setValue(threshold); + + x = guiLeft + 10 + thresholdLabel.getWidth() + thresholdField.getWidth() + 10; + addRenderableWidget(new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.celcius"))); + } + + @Override + protected ResourceLocation getTexture() { + return Textures.GUI_MODULE_SIMPLE; + } + + @Override + public void removed() { + super.removed(); + + module.setColorChannel(color); + module.setThreshold(thresholdField.getIntValue()); + // NetworkHandler.sendToServer(new PacketTubeModuleColor(module)); + NetworkHandler.sendToServer(new PacketSyncThermostatModuleToServer(module)); + } +} diff --git a/src/main/java/me/desht/pneumaticcraft/client/model/PNCModelLayers.java b/src/main/java/me/desht/pneumaticcraft/client/model/PNCModelLayers.java index 3a9ef0074..d70f9de90 100644 --- a/src/main/java/me/desht/pneumaticcraft/client/model/PNCModelLayers.java +++ b/src/main/java/me/desht/pneumaticcraft/client/model/PNCModelLayers.java @@ -48,6 +48,7 @@ public class PNCModelLayers { public static final ModelLayerLocation REGULATOR_MODULE = register("regulator_module"); public static final ModelLayerLocation SAFETY_VALVE_MODULE = register("safety_valve_module"); public static final ModelLayerLocation VACUUM_MODULE = register("vacuum_module"); + public static final ModelLayerLocation THERMOSTAT_MODULE = register("thermostat_module"); // ===================================================================== diff --git a/src/main/java/me/desht/pneumaticcraft/client/render/tube_module/ThermostatRenderer.java b/src/main/java/me/desht/pneumaticcraft/client/render/tube_module/ThermostatRenderer.java new file mode 100644 index 000000000..39ed92c40 --- /dev/null +++ b/src/main/java/me/desht/pneumaticcraft/client/render/tube_module/ThermostatRenderer.java @@ -0,0 +1,124 @@ +package me.desht.pneumaticcraft.client.render.tube_module; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import me.desht.pneumaticcraft.client.model.PNCModelLayers; +import me.desht.pneumaticcraft.client.util.RenderUtils; +import me.desht.pneumaticcraft.common.tubemodules.ThermostatModule; +import me.desht.pneumaticcraft.lib.Textures; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeListBuilder; +import net.minecraft.client.model.geom.builders.LayerDefinition; +import net.minecraft.client.model.geom.builders.MeshDefinition; +import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.item.DyeColor; + +public class ThermostatRenderer extends AbstractTubeModuleRenderer { + private final ModelPart faceplate; + private final ModelPart tubeConnector1; + private final ModelPart tubeConnector2; + private final ModelPart tubeConnector3; + private final ModelPart tubeConnector4; + private final ModelPart tubeConnector5; + private final ModelPart tubeConnector6; + private final ModelPart frame1; + private final ModelPart frame2; + private final ModelPart frame3; + private final ModelPart frame4; + + private static final String FACEPLATE = "faceplate"; + private static final String TUBECONNECTOR1 = "tubeConnector1"; + private static final String TUBECONNECTOR2 = "tubeConnector2"; + private static final String TUBECONNECTOR3 = "tubeConnector3"; + private static final String TUBECONNECTOR4 = "tubeConnector4"; + private static final String TUBECONNECTOR5 = "tubeConnector5"; + private static final String TUBECONNECTOR6 = "tubeConnector6"; + private static final String FRAME1 = "frame1"; + private static final String FRAME2 = "frame2"; + private static final String FRAME3 = "frame3"; + private static final String FRAME4 = "frame4"; + + public ThermostatRenderer(BlockEntityRendererProvider.Context ctx) { + ModelPart root = ctx.bakeLayer(PNCModelLayers.THERMOSTAT_MODULE); + faceplate = root.getChild(FACEPLATE); + tubeConnector1 = root.getChild(TUBECONNECTOR1); + tubeConnector2 = root.getChild(TUBECONNECTOR2); + tubeConnector3 = root.getChild(TUBECONNECTOR3); + tubeConnector4 = root.getChild(TUBECONNECTOR4); + tubeConnector5 = root.getChild(TUBECONNECTOR5); + tubeConnector6 = root.getChild(TUBECONNECTOR6); + frame1 = root.getChild(FRAME1); + frame2 = root.getChild(FRAME2); + frame3 = root.getChild(FRAME3); + frame4 = root.getChild(FRAME4); + } + + public static LayerDefinition createBodyLayer() { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); + + partdefinition.addOrReplaceChild(FACEPLATE, CubeListBuilder.create().texOffs(12, 0) + .addBox("faceplate_0", 0.0F, 0.0F, -1.0F, 8, 8, 2), + PartPose.offset(-4.0F, 12.0F, 5.0F)); + partdefinition.addOrReplaceChild(TUBECONNECTOR1, CubeListBuilder.create().texOffs(12, 10) + .addBox("tubeConnector1_0", -2.0F, -2.0F, 1.0F, 7, 7, 1), + PartPose.offset(-1.5F, 14.5F, 2.0F)); + partdefinition.addOrReplaceChild(TUBECONNECTOR2, CubeListBuilder.create().texOffs(12, 18) + .addBox("tubeConnector2_0", -1.0F, -1.0F, 0.0F, 5, 5, 1), + PartPose.offset(-1.5F, 14.5F, 2.0F)); + partdefinition.addOrReplaceChild(TUBECONNECTOR3, CubeListBuilder.create().texOffs(28, 12) + .addBox("tubeConnector3_0", 4.0F, 0.0F, 0.0F, 1, 3, 1), + PartPose.offset(-1.5F, 14.5F, 2.0F)); + partdefinition.addOrReplaceChild(TUBECONNECTOR4, CubeListBuilder.create().texOffs(28, 16) + .addBox("tubeConnector4_0", 0.0F, 4.0F, 0.0F, 3, 1, 1), + PartPose.offset(-1.5F, 14.5F, 2.0F)); + partdefinition.addOrReplaceChild(TUBECONNECTOR5, CubeListBuilder.create().texOffs(32, 12) + .addBox("tubeConnector5_0", -2.0F, 0.0F, 0.0F, 1, 3, 1), + PartPose.offset(-1.5F, 14.5F, 2.0F)); + partdefinition.addOrReplaceChild(TUBECONNECTOR6, CubeListBuilder.create().texOffs(28, 10) + .addBox("tubeConnector6_0", 0.0F, -2.0F, 0.0F, 3, 1, 1), + PartPose.offset(-1.5F, 14.5F, 2.0F)); + partdefinition.addOrReplaceChild(FRAME1, CubeListBuilder.create().texOffs(32, 0) + .addBox("frame1_0", 2.0F, 1.5F, -3.75F, 4, 1, 4), + PartPose.offset(-4.0F, 11.5F, 6.0F)); + partdefinition.addOrReplaceChild(FRAME2, CubeListBuilder.create().texOffs(32, 5) + .addBox("frame2_0", 2.0F, -1.5F, -3.75F, 4, 1, 4), + PartPose.offset(-4.0F, 19.5F, 6.0F)); + partdefinition.addOrReplaceChild(FRAME3, CubeListBuilder.create().texOffs(0, 6) + .addBox("frame3_0", -1.5F, 0.5F, -3.75F, 1, 6, 4), + PartPose.offset(3.5F, 12.5F, 6.0F)); + partdefinition.addOrReplaceChild(FRAME4, CubeListBuilder.create().texOffs(0, 16) + .addBox("frame4_0", 1.5F, 0.5F, -3.75F, 1, 6, 4), + PartPose.offset(-4.5F, 12.5F, 6.0F)); + + return LayerDefinition.create(meshdefinition, 64, 32); + } + + + @Override + protected void render(ThermostatModule module, PoseStack matrixStack, VertexConsumer builder, float partialTicks, int combinedLight, int combinedOverlay, float alpha) { + tubeConnector1.render(matrixStack, builder, combinedLight, combinedOverlay, 1f, 1f, 1f, alpha); + tubeConnector2.render(matrixStack, builder, combinedLight, combinedOverlay, 1f, 1f, 1f, alpha); + tubeConnector3.render(matrixStack, builder, combinedLight, combinedOverlay, 1f, 1f, 1f, alpha); + tubeConnector4.render(matrixStack, builder, combinedLight, combinedOverlay, 1f, 1f, 1f, alpha); + tubeConnector5.render(matrixStack, builder, combinedLight, combinedOverlay, 1f, 1f, 1f, alpha); + tubeConnector6.render(matrixStack, builder, combinedLight, combinedOverlay, 1f, 1f, 1f, alpha); + faceplate.render(matrixStack, builder, combinedLight, combinedOverlay, 1f, 1f, 1f, alpha); + + float[] cols = { 1f, 1f, 1f, 1f }; + cols = DyeColor.byId(module.getColorChannel()).getTextureDiffuseColors(); + frame1.render(matrixStack, builder, combinedLight, combinedOverlay, cols[0], cols[1], cols[2], alpha); + frame2.render(matrixStack, builder, combinedLight, combinedOverlay, cols[0], cols[1], cols[2], alpha); + frame3.render(matrixStack, builder, combinedLight, combinedOverlay, cols[0], cols[1], cols[2], alpha); + frame4.render(matrixStack, builder, combinedLight, combinedOverlay, cols[0], cols[1], cols[2], alpha); + } + + @Override + protected ResourceLocation getTexture(boolean isUpgraded) { + return isUpgraded ? Textures.MODEL_THERMOSTAT_MODULE_UPGRADED : Textures.MODEL_THERMOSTAT_MODULE; + } +} diff --git a/src/main/java/me/desht/pneumaticcraft/common/core/ModItems.java b/src/main/java/me/desht/pneumaticcraft/common/core/ModItems.java index 3236a80bf..0540cea53 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/core/ModItems.java +++ b/src/main/java/me/desht/pneumaticcraft/common/core/ModItems.java @@ -215,6 +215,8 @@ public class ModItems { () -> new TubeModuleItem(RedstoneModule::new)); public static final RegistryObject VACUUM_MODULE = register("vacuum_module", () -> new TubeModuleItem(VacuumModule::new)); + public static final RegistryObject THERMOSTAT_MODULE = register("thermostat_module", + () -> new TubeModuleItem(ThermostatModule::new)); public static final RegistryObject OIL_BUCKET = registerBucket("oil_bucket", ModFluids.OIL); diff --git a/src/main/java/me/desht/pneumaticcraft/common/network/NetworkHandler.java b/src/main/java/me/desht/pneumaticcraft/common/network/NetworkHandler.java index 79d91ed4e..a17f0a6d4 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/network/NetworkHandler.java +++ b/src/main/java/me/desht/pneumaticcraft/common/network/NetworkHandler.java @@ -143,6 +143,10 @@ public static void init() { PacketSyncRedstoneModuleToClient::toBytes, PacketSyncRedstoneModuleToClient::new, PacketSyncRedstoneModuleToClient::handle, PLAY_TO_CLIENT); registerMessage(PacketSyncRedstoneModuleToServer.class, PacketSyncRedstoneModuleToServer::toBytes, PacketSyncRedstoneModuleToServer::new, PacketSyncRedstoneModuleToServer::handle, PLAY_TO_SERVER); + registerMessage(PacketSyncThermostatModuleToClient.class, + PacketSyncThermostatModuleToClient::toBytes, PacketSyncThermostatModuleToClient::new, PacketSyncThermostatModuleToClient::handle, PLAY_TO_CLIENT); + registerMessage(PacketSyncThermostatModuleToServer.class, + PacketSyncThermostatModuleToServer::toBytes, PacketSyncThermostatModuleToServer::new, PacketSyncThermostatModuleToServer::handle, PLAY_TO_SERVER); registerMessage(PacketHackingBlockStart.class, PacketHackingBlockStart::toBytes, PacketHackingBlockStart::new, PacketHackingBlockStart::handle); registerMessage(PacketHackingBlockFinish.class, diff --git a/src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToClient.java b/src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToClient.java new file mode 100644 index 000000000..b8b94cda3 --- /dev/null +++ b/src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToClient.java @@ -0,0 +1,77 @@ +/* + * This file is part of pnc-repressurized. + * + * pnc-repressurized is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pnc-repressurized is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pnc-repressurized. If not, see . + */ + +package me.desht.pneumaticcraft.common.network; + +import me.desht.pneumaticcraft.client.util.ClientUtils; +import me.desht.pneumaticcraft.common.block.entity.PressureTubeBlockEntity; +import me.desht.pneumaticcraft.common.tubemodules.ThermostatModule; +import me.desht.pneumaticcraft.common.util.PneumaticCraftUtils; +import net.minecraft.core.Direction; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +import java.util.function.Supplier; + +/** + * Received on: CLIENT + * Sent by server to sync up the settings of a redstone module + */ +public class PacketSyncThermostatModuleToClient extends LocationIntPacket { + private final Direction side; + private final int channel; + private final int level; + private final double temperature; + + public PacketSyncThermostatModuleToClient(ThermostatModule module) { + super(module.getTube().getBlockPos()); + + this.channel = module.getColorChannel(); + this.side = module.getDirection(); + this.level = module.getLevel(); + this.temperature = module.getTemperature(); + } + + PacketSyncThermostatModuleToClient(FriendlyByteBuf buffer) { + super(buffer); + channel = buffer.readByte(); + side = buffer.readEnum(Direction.class); + level = buffer.readInt(); + temperature = buffer.readDouble(); + } + + @Override + public void toBytes(FriendlyByteBuf buf) { + super.toBytes(buf); + buf.writeByte(channel); + buf.writeEnum(side); + buf.writeInt(level); + buf.writeDouble(temperature); + } + + public void handle(Supplier ctx) { + ctx.get().enqueueWork(() -> + PneumaticCraftUtils.getTileEntityAt(ClientUtils.getClientLevel(), pos, PressureTubeBlockEntity.class).ifPresent(te -> { + if (te.getModule(side) instanceof ThermostatModule mr) { + mr.setColorChannel(channel); + mr.setLevel(level); + mr.setTemperature(temperature); + } + })); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToServer.java b/src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToServer.java new file mode 100644 index 000000000..142db2eab --- /dev/null +++ b/src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToServer.java @@ -0,0 +1,78 @@ +/* + * This file is part of pnc-repressurized. + * + * pnc-repressurized is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pnc-repressurized is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pnc-repressurized. If not, see . + */ + +package me.desht.pneumaticcraft.common.network; + +import me.desht.pneumaticcraft.common.block.entity.PressureTubeBlockEntity; +import me.desht.pneumaticcraft.common.tubemodules.ThermostatModule; +import me.desht.pneumaticcraft.common.util.PneumaticCraftUtils; +import net.minecraft.core.Direction; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.network.NetworkEvent; + +import java.util.function.Supplier; + +/** + * Received on: SERVER + * Sent by client to update server-side settings when redstone module GUI is closed + */ +public class PacketSyncThermostatModuleToServer extends LocationIntPacket { + private final Direction side; + private final byte channel; + private final int threshold; + + public PacketSyncThermostatModuleToServer(ThermostatModule module) { + super(module.getTube().getBlockPos()); + + this.side = module.getDirection(); + this.channel = (byte) module.getColorChannel(); + this.threshold = module.getThreshold(); + } + + PacketSyncThermostatModuleToServer(FriendlyByteBuf buffer) { + super(buffer); + side = buffer.readEnum(Direction.class); + channel = buffer.readByte(); + threshold = buffer.readInt(); + } + + @Override + public void toBytes(FriendlyByteBuf buf) { + super.toBytes(buf); + buf.writeEnum(side); + buf.writeByte(channel); + buf.writeInt(threshold); + } + + public void handle(Supplier ctx) { + ctx.get().enqueueWork(() -> { + Player player = ctx.get().getSender(); + if (PneumaticCraftUtils.canPlayerReach(player, pos)) { + PneumaticCraftUtils.getTileEntityAt(player.level(), pos, PressureTubeBlockEntity.class).ifPresent(tube -> { + if (tube.getModule(side) instanceof ThermostatModule mr) { + mr.setColorChannel(channel); + mr.setThreshold(threshold); + mr.updateNeighbors(); + mr.setUpdate(true); // Force recalc + } + }); + } + }); + ctx.get().setPacketHandled(true); + } +} diff --git a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ModuleNetworkManager.java b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ModuleNetworkManager.java index bd05430fe..dbfeab0f6 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ModuleNetworkManager.java +++ b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ModuleNetworkManager.java @@ -60,7 +60,7 @@ private Set computeConnections(AbstractTubeModule module) { while (!pendingPositions.isEmpty()) { BlockPos pos = pendingPositions.pop(); PneumaticCraftUtils.getTileEntityAt(level, pos, PressureTubeBlockEntity.class).ifPresent(tube -> tube.tubeModules() - .filter(tm -> tm instanceof INetworkedModule && module.getClass() == tm.getClass()) + .filter(tm -> tm instanceof INetworkedModule) .forEach(modules::add)); for (Direction dir : DirectionUtil.VALUES) { BlockPos pos1 = pos.relative(dir); diff --git a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/RedstoneModule.java b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/RedstoneModule.java index 3816dc8b1..6ce7f810a 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/RedstoneModule.java +++ b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/RedstoneModule.java @@ -23,8 +23,10 @@ import me.desht.pneumaticcraft.common.network.NetworkHandler; import me.desht.pneumaticcraft.common.network.PacketSyncRedstoneModuleToClient; import me.desht.pneumaticcraft.common.thirdparty.ModdedWrenchUtils; +import me.desht.pneumaticcraft.common.tubemodules.ThermostatModule; import me.desht.pneumaticcraft.common.util.ITranslatableEnum; import me.desht.pneumaticcraft.common.util.PneumaticCraftUtils; +import me.desht.pneumaticcraft.lib.Log; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -108,6 +110,10 @@ public void tickServer() { if (mr.getRedstoneDirection() == EnumRedstoneDirection.INPUT && mr.getInputLevel() > levels[mr.getColorChannel()]) levels[mr.getColorChannel()] = (byte) mr.inputLevel; } + if (module instanceof ThermostatModule mr) { + if (mr.getLevel() > levels[mr.getColorChannel()]) + levels[mr.getColorChannel()] = (byte) mr.getLevel(); + } } int out = computeOutputSignal(outputLevel, levels); diff --git a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java new file mode 100644 index 000000000..546d1eecb --- /dev/null +++ b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java @@ -0,0 +1,211 @@ +/* + * This file is part of pnc-repressurized. + * + * pnc-repressurized is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pnc-repressurized is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pnc-repressurized. If not, see . + */ + +package me.desht.pneumaticcraft.common.tubemodules; + +import me.desht.pneumaticcraft.common.block.entity.PressureTubeBlockEntity; +import me.desht.pneumaticcraft.common.config.ConfigHelper; +import me.desht.pneumaticcraft.common.core.ModItems; +import me.desht.pneumaticcraft.common.heat.HeatExchangerManager; +import me.desht.pneumaticcraft.common.heat.HeatUtil; +import me.desht.pneumaticcraft.common.heat.TemperatureData; +import me.desht.pneumaticcraft.common.network.NetworkHandler; +import me.desht.pneumaticcraft.common.network.PacketSyncThermostatModuleToClient; +import me.desht.pneumaticcraft.common.network.PacketSyncThermostatModuleToServer; +import me.desht.pneumaticcraft.common.thirdparty.ModdedWrenchUtils; +import me.desht.pneumaticcraft.common.util.DirectionUtil; +import me.desht.pneumaticcraft.common.util.ITranslatableEnum; +import me.desht.pneumaticcraft.common.util.PneumaticCraftUtils; +import me.desht.pneumaticcraft.lib.Log; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +import java.util.Comparator; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.stream.IntStream; + +public class ThermostatModule extends AbstractTubeModule implements INetworkedModule { + + private int colorChannel; + private double temperature = 0.0; + private int level; + private int threshold; + private boolean update = true; + + public ThermostatModule(Direction dir, PressureTubeBlockEntity pressureTube) { + super(dir, pressureTube); + } + + public double getTemperature() { + return this.temperature; + } + + public void setTemperature(double temperature) { + this.temperature = temperature; + } + + public int getThreshold() { + return this.threshold; + } + + public void setThreshold(int threshold) { + this.threshold = threshold; + } + + public int getLevel() { + return this.level; + } + + public void setLevel(int level) { + this.level = level; + } + + public void setUpdate(boolean update) { + this.update = update; + } + + @Override + public boolean hasGui() { + return true; + } + + @Override + public Item getItem() { + return ModItems.THERMOSTAT_MODULE.get(); + } + + @Override + public int getColorChannel() { + return colorChannel; + } + + @Override + public void setColorChannel(int channel) { + this.colorChannel = channel; + setChanged(); + } + + @Override + public double getWidth() { + return 9D; + } + + @Override + protected double getHeight() { + return 5D; + } + + @Override + public void addInfo(List curInfo) { + super.addInfo(curInfo); + curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.tubeModule.threshold_temp", PneumaticCraftUtils.roundNumberTo(getThreshold(), 1))); + curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.thermostatModule.temperature", temperature)); + curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.thermostatModule.level", level)); + } + + @Override + public boolean onActivated(Player player, InteractionHand hand) { + ItemStack heldStack = player.getItemInHand(hand); + DyeColor dyeColor = DyeColor.getColor(heldStack); + if (dyeColor != null) { + int colorId = dyeColor.getId(); + setColorChannel(colorId); + if (ConfigHelper.common().general.useUpDyesWhenColoring.get() && !player.isCreative()) { + heldStack.shrink(1); + } + return true; + } else { + return super.onActivated(player, hand); + } + } + + @Override + public void onNeighborBlockUpdate() { + updateInputLevel(); + } + + @Override + public void onNeighborTileUpdate() { + updateInputLevel(); + } + + @Override + public void tickServer() { + super.tickServer(); + + // Forced recalc when client GUI updated + if (this.update) { + this.update = false; + updateInputLevel(); + } + } + + private void updateInputLevel() { + Level world = Objects.requireNonNull(pressureTube.getLevel()); + + BlockPos pos = pressureTube.getBlockPos().relative(getDirection()); + + HeatExchangerManager.getInstance().getLogic(world, pos, null) + .ifPresent(logic -> setTemperature(logic.getTemperature() - 273)); + + int level = 0; + if (temperature >= threshold) { + level = 15; + } + + if (this.level != level) { + this.level = level; + NetworkHandler.sendToAllTracking(new PacketSyncThermostatModuleToClient(this), getTube()); + } + } + + @Override + public CompoundTag writeToNBT(CompoundTag tag) { + super.writeToNBT(tag); + + tag.putByte("channel", (byte) colorChannel); + tag.putByte("level", (byte) level); + tag.putDouble("temperature", temperature); + tag.putInt("threshold", threshold); + + return tag; + } + + @Override + public void readFromNBT(CompoundTag tag) { + super.readFromNBT(tag); + + colorChannel = tag.getByte("channel"); + level = tag.getByte("level"); + temperature = tag.getDouble("temperature"); + threshold = tag.getInt("threshold"); + } + +} diff --git a/src/main/java/me/desht/pneumaticcraft/datagen/ModRecipeProvider.java b/src/main/java/me/desht/pneumaticcraft/datagen/ModRecipeProvider.java index 878fc9c52..b9ed36532 100644 --- a/src/main/java/me/desht/pneumaticcraft/datagen/ModRecipeProvider.java +++ b/src/main/java/me/desht/pneumaticcraft/datagen/ModRecipeProvider.java @@ -652,6 +652,13 @@ protected void buildRecipes(Consumer consumer) { 'T', ModBlocks.PRESSURE_TUBE.get() ).save(consumer); + shaped(ModItems.THERMOSTAT_MODULE.get(), ModItems.COMPRESSED_IRON_INGOT.get(), + " R /TDT", + 'R', Tags.Items.DUSTS_REDSTONE, + 'T', ModBlocks.PRESSURE_TUBE.get(), + 'D', Blocks.COMPARATOR + ).save(consumer); + shaped(ModBlocks.PRESSURE_TUBE.get(), 8, ModItems.COMPRESSED_IRON_INGOT.get(), "IGI", 'G', Tags.Items.GLASS, diff --git a/src/main/java/me/desht/pneumaticcraft/lib/Textures.java b/src/main/java/me/desht/pneumaticcraft/lib/Textures.java index 8dbc80267..4d7777ef9 100644 --- a/src/main/java/me/desht/pneumaticcraft/lib/Textures.java +++ b/src/main/java/me/desht/pneumaticcraft/lib/Textures.java @@ -62,6 +62,8 @@ public class Textures { public static final ResourceLocation MODEL_REDSTONE_MODULE_UPGRADED = tubeModuleTexture("redstone_upgraded.png"); public static final ResourceLocation MODEL_VACUUM_MODULE = tubeModuleTexture("vacuum.png"); public static final ResourceLocation MODEL_VACUUM_MODULE_UPGRADED = tubeModuleTexture("vacuum_upgraded.png"); + public static final ResourceLocation MODEL_THERMOSTAT_MODULE = tubeModuleTexture("thermostat_module.png"); + public static final ResourceLocation MODEL_THERMOSTAT_MODULE_UPGRADED = tubeModuleTexture("thermostat_module_upgraded.png"); // Progwidget textures public static final ResourceLocation PROG_WIDGET_COMMENT = progWidgetTexture("comment_piece.png"); diff --git a/src/main/resources/assets/pneumaticcraft/lang/en_us.json b/src/main/resources/assets/pneumaticcraft/lang/en_us.json index 7eda27edc..2052f7645 100644 --- a/src/main/resources/assets/pneumaticcraft/lang/en_us.json +++ b/src/main/resources/assets/pneumaticcraft/lang/en_us.json @@ -355,6 +355,7 @@ "gui.tooltip.item.pneumaticcraft.programming_puzzle" : "Used by a Programmer when writing programs to a Drone or Network API. Either keep these pieces in your inventory or put them in an inventory adjacent to the Programmer.", "gui.tooltip.item.pneumaticcraft.raw_salmon_tempura" : "Needs some deep frying!", "gui.tooltip.item.pneumaticcraft.redstone_module" : "§bThis module transmits redstone signals to other Redstone Modules on connected tubes. Right-click with any dye to set the channel; right-click with a wrench to toggle between input and output.\n\nUpgrade with a Module Expansion Card for extra signal processing operations.", + "gui.tooltip.item.pneumaticcraft.thermostat_module" : "§bThis module transmits redstone signals on selected channel when temperature of facing block is above threshold.", "gui.tooltip.item.pneumaticcraft.regulator_tube_module" : "§bThis module limits the pressure allowed on its low side based on the redstone signal it receives. No signal = 4.9 bar, a full signal = 0 bar (no air allowed through), and other signal levels are interpolated. Air is always allowed to travel \"backwards\" through the Regulator, making it usable as a one-way valve.\nWhen upgraded with a Module Expansion Card, the threshold can be configured precisely via GUI.", "gui.tooltip.item.pneumaticcraft.reinforced_chest_kit" : "Sneak+Right-click on any wooden chest to upgrade it to a Reinforced Chest, keeping the contents intact.\nThe old chest will be returned to you as an item drop.", "gui.tooltip.item.pneumaticcraft.reinforced_air_canister" : "A stronger version of the basic Air Canister. In conjunction with a couple of Aerial Interfaces, Charging Modules and an Ender Chest, this could have some wireless pressure transfer possibilities...", @@ -496,6 +497,7 @@ "item.pneumaticcraft.radiation_shielding_upgrade" : "Radiation Shielding Upgrade", "item.pneumaticcraft.range_upgrade" : "Range Upgrade", "item.pneumaticcraft.redstone_module" : "Redstone Module", + "item.pneumaticcraft.thermostat_module" : "Thermostat Module", "item.pneumaticcraft.regulator_tube_module" : "Regulator Tube Module", "item.pneumaticcraft.reinforced_air_canister" : "Reinforced Air Canister", "item.pneumaticcraft.reinforced_chest_kit" : "Reinforced Chest Upgrade Kit", @@ -1812,6 +1814,7 @@ "pneumaticcraft.gui.tubeModule.simpleConfig.higherThan" : "Higher than", "pneumaticcraft.gui.tubeModule.simpleConfig.lowerThan" : "Lower than", "pneumaticcraft.gui.tubeModule.simpleConfig.threshold" : "Threshold:", + "pneumaticcraft.gui.tubeModule.celcius" : "°C", "pneumaticcraft.gui.tubeModule.simpleConfig.turn" : "Emit when", "pneumaticcraft.gui.universalSensor.desc.block_comparator" : "This sensor setting simulates a Redstone Comparator at the position(s) marked by the GPS (Area) Tool, so the output redstone signal is proportional to the contents of inventories at those positions. If the comparator output would be side dependant, the highest signal will be emitted.\nIn the case of multiple positions, the highest comparator value from any position will be emitted.", "pneumaticcraft.gui.universalSensor.desc.block_heat" : "The block position(s) marked by the GPS (Area) Tool are monitored for heat. When the temperature of the monitored block is higher than the temperature in the text box (in °C) the sensor will emit a redstone level of 15, and 0 if not.\nIf the textfield is empty, the output level is proportional to the temperature, scaling from 0°C (redstone=0) through 400°C (redstone=15).\nIn the case of multiple positions, the position with the highest temperature is used.", @@ -1940,6 +1943,8 @@ "pneumaticcraft.waila.redstoneModule.inverted" : "§cOutput inverted", "pneumaticcraft.waila.redstoneModule.op" : "Operation: §e%s", "pneumaticcraft.waila.redstoneModule.receiving" : "Receiving redstone: §e%d", + "pneumaticcraft.waila.thermostatModule.level" : "Redstone level: §e%d", + "pneumaticcraft.waila.thermostatModule.temperature" : "Temperature: §e%d °C", "pneumaticcraft.waila.tank" : "Tank #%d: %s", "pneumaticcraft.waila.temperature.down" : "Bottom Temperature: ", "pneumaticcraft.waila.temperature.east" : "East Temperature: ", @@ -1951,6 +1956,7 @@ "pneumaticcraft.waila.temperatureGain" : "§7Heat Absorption: §f%d%%", "pneumaticcraft.waila.temperatureLoss" : "§7Heat Extraction: §f%d%%", "pneumaticcraft.waila.tubeModule.threshold" : "Threshold: §e%d bar", + "pneumaticcraft.waila.tubeModule.threshold_temp" : "Threshold: §e%d °C", "programmingPuzzle.pneumaticcraft.area.name" : "Area", "programmingPuzzle.pneumaticcraft.block_right_click.name" : "Right Click", "programmingPuzzle.pneumaticcraft.comment.name" : "Comment", diff --git a/src/main/resources/assets/pneumaticcraft/models/item/thermostat_module.json b/src/main/resources/assets/pneumaticcraft/models/item/thermostat_module.json new file mode 100644 index 000000000..4129486e5 --- /dev/null +++ b/src/main/resources/assets/pneumaticcraft/models/item/thermostat_module.json @@ -0,0 +1,243 @@ +{ + "credit": "Made with Blockbench", + "texture_size": [64, 32], + "textures": { + "0": "pneumaticcraft:pnc_model/modules/thermostat_module" + }, + "elements": [ + { + "name": "faceplate", + "from": [4, 0, 8], + "to": [12, 8, 10], + "faces": { + "north": {"uv": [3.5, 1, 5.5, 5], "texture": "#0"}, + "east": {"uv": [3, 1, 3.5, 5], "texture": "#0"}, + "south": {"uv": [6, 1, 8, 5], "texture": "#0"}, + "west": {"uv": [5.5, 1, 6, 5], "texture": "#0"}, + "up": {"uv": [5.5, 1, 3.5, 0], "texture": "#0"}, + "down": {"uv": [7.5, 0, 5.5, 1], "texture": "#0"} + } + }, + { + "name": "tubeConnector1", + "from": [4.5, 0.5, 7], + "to": [11.5, 7.5, 8], + "faces": { + "north": {"uv": [3.25, 5.5, 5, 9], "texture": "#0"}, + "east": {"uv": [3, 5.5, 3.25, 9], "texture": "#0"}, + "south": {"uv": [5.25, 5.5, 7, 9], "texture": "#0"}, + "west": {"uv": [5, 5.5, 5.25, 9], "texture": "#0"}, + "up": {"uv": [5, 5.5, 3.25, 5], "texture": "#0"}, + "down": {"uv": [6.75, 5, 5, 5.5], "texture": "#0"} + } + }, + { + "name": "tubeConnector2", + "from": [5.5, 1.5, 6], + "to": [10.5, 6.5, 7], + "faces": { + "north": {"uv": [3.25, 9.5, 4.5, 12], "texture": "#0"}, + "east": {"uv": [3, 9.5, 3.25, 12], "texture": "#0"}, + "south": {"uv": [4.75, 9.5, 6, 12], "texture": "#0"}, + "west": {"uv": [4.5, 9.5, 4.75, 12], "texture": "#0"}, + "up": {"uv": [4.5, 9.5, 3.25, 9], "texture": "#0"}, + "down": {"uv": [5.75, 9, 4.5, 9.5], "texture": "#0"} + } + }, + { + "name": "tubeConnector3", + "from": [4.5, 2.5, 6], + "to": [5.5, 5.5, 7], + "faces": { + "north": {"uv": [7.25, 6.5, 7.5, 8], "texture": "#0"}, + "east": {"uv": [7, 6.5, 7.25, 8], "texture": "#0"}, + "south": {"uv": [7.75, 6.5, 8, 8], "texture": "#0"}, + "west": {"uv": [7.5, 6.5, 7.75, 8], "texture": "#0"}, + "up": {"uv": [7.5, 6.5, 7.25, 6], "texture": "#0"}, + "down": {"uv": [7.75, 6, 7.5, 6.5], "texture": "#0"} + } + }, + { + "name": "tubeConnector4", + "from": [6.5, 0.5, 6], + "to": [9.5, 1.5, 7], + "faces": { + "north": {"uv": [7.25, 8.5, 8, 9], "texture": "#0"}, + "east": {"uv": [7, 8.5, 7.25, 9], "texture": "#0"}, + "south": {"uv": [8.25, 8.5, 9, 9], "texture": "#0"}, + "west": {"uv": [8, 8.5, 8.25, 9], "texture": "#0"}, + "up": {"uv": [8, 8.5, 7.25, 8], "texture": "#0"}, + "down": {"uv": [8.75, 8, 8, 8.5], "texture": "#0"} + } + }, + { + "name": "tubeConnector5", + "from": [10.5, 2.5, 6], + "to": [11.5, 5.5, 7], + "faces": { + "north": {"uv": [8.25, 6.5, 8.5, 8], "texture": "#0"}, + "east": {"uv": [8, 6.5, 8.25, 8], "texture": "#0"}, + "south": {"uv": [8.75, 6.5, 9, 8], "texture": "#0"}, + "west": {"uv": [8.5, 6.5, 8.75, 8], "texture": "#0"}, + "up": {"uv": [8.5, 6.5, 8.25, 6], "texture": "#0"}, + "down": {"uv": [8.75, 6, 8.5, 6.5], "texture": "#0"} + } + }, + { + "name": "tubeConnector6", + "from": [6.5, 6.5, 6], + "to": [9.5, 7.5, 7], + "faces": { + "north": {"uv": [7.25, 5.5, 8, 6], "texture": "#0"}, + "east": {"uv": [7, 5.5, 7.25, 6], "texture": "#0"}, + "south": {"uv": [8.25, 5.5, 9, 6], "texture": "#0"}, + "west": {"uv": [8, 5.5, 8.25, 6], "texture": "#0"}, + "up": {"uv": [8, 5.5, 7.25, 5], "texture": "#0"}, + "down": {"uv": [8.75, 5, 8, 5.5], "texture": "#0"} + } + }, + { + "name": "frame1", + "from": [6, 6, 6.25], + "to": [10, 7, 10.25], + "faces": { + "north": {"uv": [9, 2, 10, 2.5], "texture": "#0"}, + "east": {"uv": [8, 2, 9, 2.5], "texture": "#0"}, + "south": {"uv": [11, 2, 12, 2.5], "texture": "#0"}, + "west": {"uv": [10, 2, 11, 2.5], "texture": "#0"}, + "up": {"uv": [10, 2, 9, 0], "texture": "#0"}, + "down": {"uv": [11, 0, 10, 2], "texture": "#0"} + } + }, + { + "name": "frame2", + "from": [6, 1, 6.25], + "to": [10, 2, 10.25], + "faces": { + "north": {"uv": [9, 4.5, 10, 5], "texture": "#0"}, + "east": {"uv": [8, 4.5, 9, 5], "texture": "#0"}, + "south": {"uv": [11, 4.5, 12, 5], "texture": "#0"}, + "west": {"uv": [10, 4.5, 11, 5], "texture": "#0"}, + "up": {"uv": [10, 4.5, 9, 2.5], "texture": "#0"}, + "down": {"uv": [11, 2.5, 10, 4.5], "texture": "#0"} + } + }, + { + "name": "frame3", + "from": [5, 1, 6.25], + "to": [6, 7, 10.25], + "faces": { + "north": {"uv": [1, 5, 1.25, 8], "texture": "#0"}, + "east": {"uv": [0, 5, 1, 8], "texture": "#0"}, + "south": {"uv": [2.25, 5, 2.5, 8], "texture": "#0"}, + "west": {"uv": [1.25, 5, 2.25, 8], "texture": "#0"}, + "up": {"uv": [1.25, 5, 1, 3], "texture": "#0"}, + "down": {"uv": [1.5, 3, 1.25, 5], "texture": "#0"} + } + }, + { + "name": "frame4", + "from": [10, 1, 6.25], + "to": [11, 7, 10.25], + "faces": { + "north": {"uv": [1, 10, 1.25, 13], "texture": "#0"}, + "east": {"uv": [0, 10, 1, 13], "texture": "#0"}, + "south": {"uv": [2.25, 10, 2.5, 13], "texture": "#0"}, + "west": {"uv": [1.25, 10, 2.25, 13], "texture": "#0"}, + "up": {"uv": [1.25, 10, 1, 8], "texture": "#0"}, + "down": {"uv": [1.5, 8, 1.25, 10], "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [75, -135, 0], + "translation": [-1.25, 1.25, 1.25], + "scale": [0.5, 0.5, 0.5] + }, + "thirdperson_lefthand": { + "rotation": [75, -135, 0], + "translation": [-1.25, 1.25, 1.25], + "scale": [0.5, 0.5, 0.48] + }, + "firstperson_righthand": { + "rotation": [0, -45, 0], + "translation": [0, 3.5, 0.5], + "scale": [0.6, 0.6, 0.6] + }, + "firstperson_lefthand": { + "rotation": [0, -45, 0], + "translation": [0, 3.5, 0.5], + "scale": [0.6, 0.6, 0.6] + }, + "ground": { + "translation": [0, 3, 0], + "scale": [0.5, 0.5, 0.5] + }, + "gui": { + "rotation": [30, 45, 0], + "translation": [0, 4.75, 0], + "scale": [1.25, 1.25, 1.25] + }, + "fixed": { + "translation": [0, 5.25, -2.5] + } + }, + "groups": [ + { + "name": "faceplate", + "origin": [4, 12, 5], + "children": [1] + }, + { + "name": "tubeConnector1", + "origin": [1.5, 9.5, 2], + "children": [2] + }, + { + "name": "tubeConnector2", + "origin": [1.5, 9.5, 2], + "children": [3] + }, + { + "name": "tubeConnector3", + "origin": [1.5, 9.5, 2], + "children": [4] + }, + { + "name": "tubeConnector4", + "origin": [1.5, 9.5, 2], + "children": [5] + }, + { + "name": "tubeConnector5", + "origin": [1.5, 9.5, 2], + "children": [6] + }, + { + "name": "tubeConnector6", + "origin": [1.5, 9.5, 2], + "children": [7] + }, + { + "name": "frame1", + "origin": [4, 12.5, 6], + "children": [8] + }, + { + "name": "frame2", + "origin": [4, 4.5, 6], + "children": [9] + }, + { + "name": "frame3", + "origin": [-3.5, 11.5, 6], + "children": [10, 11] + }, + { + "name": "frame4", + "origin": [4.5, 11.5, 6], + "children": [] + } + ] +} diff --git a/src/main/resources/assets/pneumaticcraft/textures/pnc_model/modules/thermostat_module.png b/src/main/resources/assets/pneumaticcraft/textures/pnc_model/modules/thermostat_module.png new file mode 100644 index 0000000000000000000000000000000000000000..4c174444b02354e57b44e758775ab03a60c06db4 GIT binary patch literal 5533 zcmeHL3se->8J=Z{JX8`9~f zxC=)bI038kp2d{XW(&!)9Gu0muuLMC$RG$uag0Fa1g?TH1rdu9a?mN>5bWXod{>Z% zH({69(}n@B7cGM^oRBF20aRMK0l<#TmY2#U2x zNF!^YC8ZXdzy!sW5};|Jc@i$Qn5}lAG(OrPL4dZkT2fLXDUnH7u271p)oLkQQ3-Ep0yXT0qpk-JE!i55U1nf zx;u=>VT?3Ia$1rnXV9D-cwB?UNqZOahC%?wnH8ri~gsS4;;o(Jj*} z*>runM#v=Ib>+b$=<`=%WT|2c2qDDAv54L2X^DZcl3ZCJ?E-19nw=BQGLyWCNS8jI{;(-X=0=+UhH76A_W}}9tsaTo87>LtXv{&AABUn<##L%2ZtxUmG z@>B()O-fWD@>mo@5|fmvh)SL!Q{tEcOHK?Jias>Gs+_{Qo*^dL%oYcnhDWSd!X(m8 zr!r<*NX8nzh~_M;ohSL(7S>p74j7uVoO5F4v<<0#_5@FK7spenGYePclaX1~&_apmGG4>D|SZ6YnGA56yCV zmNjd)$p{?(sg5%!luES>lOr;j0Yem+ z+=Lj^m;%8RD#{c~t7w&)a$EVIIL=Par~mIZqPyF?>E@@p4O1&HQ>>Cg6qGy`Aysl2 z0(z8)j8rQrIc>x#wd}v^Hs>?gJrz2Vs^8QZ=XlW~!0uWIDps@BRm-|Eit&{*Nrw*Vp1vOh*Bjd5f#XY2qibE z4RYFqt7xTrt$fIQ6nVLlSu@Lly^PiX2m9;xi%L&U2JdAiP!wwH*^`ps^ps=;n7#tR zg*P8BjgOp*$LUv}j|Pq;>+A)eBsAf`aQEj8O?c?G#o!BxxFB7ds4rUb{kG%mg@i$0 z9RD4$t}n82LUCHdsn!=8)aQ?1Wy7D4^aJsn2ihbn94CbWzs@Wm~o z>L(wF-oN(>b`Ps8jIWkPWLE7#g8j?R1Jh`DI|%sgRXKHoNJP zna$OwSB4~R%bz~7%{ajlvLMqIGobGNn5*v&TPqf;`nOw;^c@vkTRC=6__pfmFRou7 z-uQ6t;qc4Fx3|ogSr8KS=!Y{ojaLf`j&(#xt%DDB+|lgbA9Agp{(O*ac+B~&*^}G0 zO|vh(S@!l{nvt^&=g#$OK$k!0c=+DL%+>$+^@K0SM8kd8EQUj;UClq)bnW%?9lW^x z$U9d$I|_7%>Mds{?+t2xWVrjN>-RB+#o_BAQ?VM5j_r(2CSsz?(7w7$0 zGqmo4h=|$nS#8(Y^|tq*DX9ZPH|-3*NFMImB<>SdlSnpQthoo>_}7j(wwt1FPF9>5 zu&~Uer`JQ_Uz5ehn5~i1_Pl?3;i}qs8`nVA zPoMQ`R20Pj(AjtMrJ&T-ukf`S$8T0tZ4OtC+shCC16x-1Nz0J*)1Q=>Yrag(+@Xya zGCAyCR&!S;e0v<3{Z+rEHsjrhWb3Gw)(=-?hCCcCjr!HSkcwfJ;BU^1ta*FIfIofQ z`O6t{>B{^*OLF?37#w}Pd{1!w^G9L%FhmNsmAFumE&@{ bCU!yO{mwCU_m*uCJ}suFWNPb@<}Cd;m{A5_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/pneumaticcraft/textures/pnc_model/modules/thermostat_module_upgraded.png b/src/main/resources/assets/pneumaticcraft/textures/pnc_model/modules/thermostat_module_upgraded.png new file mode 100644 index 0000000000000000000000000000000000000000..6e16bdafdc703e0ffaa11f4db057d9a58fda422b GIT binary patch literal 3522 zcma)94OkOL8r~ovA_}6YfLB7SLOt@I010712uLV@g`iLoS&|K`CfRhe2#7zCqgJG6 zrHJ-Xs;OGMss#@@MJ=3KJbx)#J@JtuRIFO$K&w*lwA>`&Cvc?c=GmFq`QG>aX1cIHw`7{5ha&_*(%Ke{jC<4`PG)1C_jfED0wgY5OafK#<76tqu ziU(w8Y(vmeiswi>o#H!$u>lx11WL#a+=`Dd$aV<74%CJ#3fw@+R3~70s8WTHI6+My za4MI@{2oP1*$2Us8lTkO`U1DDbVhUxnQ&xF=+~!5*s6w z;VK3q$1_nzo=Rh2L83e%XsS>Wq2{TSYOOFYm}W!>LEF&Hq*09!a&<5*B{qQ?juR-= zpTT0VXs{!dN)-`ug)mVZIYb9f!L)3W)Cif(+}vD7E|-B5SxmM-AYigMOb&+*5Oi(6 znnd#GYVCZJ$gqwW)yfD=Lt?m^YS2Y8@f zG1&|jQ;n!ltp<^y6UhP4h=y7_6eJ@XF|j8ik(gq1wqsZZi_z&sG&B#hKr>iOG-GT{ zQx=V#sxS$YqcVgLBP6mECA1(`Fk8g54jK)j1;u3qMxw-GjYf&d5W^b4qmcyr(2|e; zr~N@sVss5AL*ZCN#^(D8eqVkF`v;ZdlVCQF!Dd*Di)qXNW>qjkjbtiOIV>e|P)kD` z##j|gmP%m5J2)Cw5^P?xM}{1i<)~0KN!JiKU29rtMkc04h(nN8HbNB*5K%^y~W-?Y?#^6Km5Eib)b1Y6{1ZGt* z4AG*Im=ZOlF__Fo2^Fp-5ptypm**(al{uO$0+FK@9gU$|b(WNk6J!*k%^r!DrI?H& zt%{nKYgn@#8Nq^tlTM<8VT(?Ns9GRcg=n&}uayf6{f;>sLDs!Ud6Bn)1FiMq$L;t33F zM^lCc8Olg8?;DR#9d!c-a9H4CvJK@B)!aOun)3TpbF&%Ma105Jkxdn2AR8Ia7%rII zgoX);DWgPxo;lIXFhmqF4M)A%(Qo>$F!q8E3)m4X#PCN7?07`Awh4kJ{Z}GhEY05Z zpU+}(&*WK~_kGa4*2aJ7{1`N7|2wtCw)FBYY4Y;qFG~{wkQO(aqC3yMY91f{(9Shz z@WVBiZIT_O@1;@SI_QwI$?;P9HKzr>rDdhcti$QEzx(`$fnzeCxR~wx{+dtY8wY{TOFGE;CVj&1Iuaa1={Y)i1d>y?{`VQlG64x)toqC z-x1VP)EW5nF>OG)=*7M&A9n1_YZ8BsyB@9!@^X3B5qjXp7SYa2KF%GdTkq9%1~%mX zOnT^EKH5l0@SSx>G`M3=u4`Rn;tu;{TrX^bz6L2Upvyf z?&_f|+0hL-#oU`*X;0gn(vt3sxtn`a9K3J6(p)cURJHc?4Ky~|%4D+I_v!O4p8H^4 zHT6n+nb*;pXOA;mBA&eLOK%qq)&@VF`{}zYpZ1+Pq8#j>eW7~w(VnAje#gqABOVX} zWozH3)q9=ODCa!4yEA4vdYnCfzOc9OlZI2?;`##iRXGQ$xRy-$n+-Gl_MJ5=(ppeO z=K_cyBrV)l(a;;}7vCdTvPl11#;U9b?uG6Boz2a4AscoT*F4Vu`rFE0+e`4h-ikl( z`loG&cki?7kJr=7^&#%IlfTzj`3U#}3$O27U!UGP_twwHAANQ@>7`SdpT0c$OW6#k z+g{nZQ&OFkt=o9m8@(N_Pw|V4mu~&!g-y+$uE=zX<8G&ywv_Sq(3{^hwbd~)PR2%W z{&5Nq3tq4jrSvO(yBAWki`GhXTVFW1#6k1cyWZzyNOp9~gAz+0MovpWY_ZPe!;9bOWIv^`JwI=_>k=*u@U!o(XR(Y2RKlX6(ycJe| zWu-lHYUNS)CdHGpm)o4zdwu}`CBIPKtNv!mitByh2W|G>-79`cId*2>Pm^8B5z&ne z#gkj9wZXbBmw!9Y;B-9NIM~?~^73C#N-G}*x~%$(%Tk@t=kP19gY%vCw)KC!Jtj0jOU_$V5Ym4)2S9Hnn|3wlJC$0+1DEuFesQtPC literal 0 HcmV?d00001 From 5e49cee4d22c5636ab4c4f83726bd8cf4987d8da Mon Sep 17 00:00:00 2001 From: Johannes Lundberg Date: Fri, 24 Nov 2023 10:39:01 -0700 Subject: [PATCH 2/5] Correct spelling --- .../client/gui/tubemodule/ThermostatModuleScreen.java | 2 +- src/main/resources/assets/pneumaticcraft/lang/en_us.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java b/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java index 5d6d32a27..0505f99b9 100644 --- a/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java +++ b/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java @@ -73,7 +73,7 @@ public void init() { thresholdField.setValue(threshold); x = guiLeft + 10 + thresholdLabel.getWidth() + thresholdField.getWidth() + 10; - addRenderableWidget(new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.celcius"))); + addRenderableWidget(new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.celsius"))); } @Override diff --git a/src/main/resources/assets/pneumaticcraft/lang/en_us.json b/src/main/resources/assets/pneumaticcraft/lang/en_us.json index 2052f7645..530fd38b5 100644 --- a/src/main/resources/assets/pneumaticcraft/lang/en_us.json +++ b/src/main/resources/assets/pneumaticcraft/lang/en_us.json @@ -1814,7 +1814,7 @@ "pneumaticcraft.gui.tubeModule.simpleConfig.higherThan" : "Higher than", "pneumaticcraft.gui.tubeModule.simpleConfig.lowerThan" : "Lower than", "pneumaticcraft.gui.tubeModule.simpleConfig.threshold" : "Threshold:", - "pneumaticcraft.gui.tubeModule.celcius" : "°C", + "pneumaticcraft.gui.tubeModule.celsius" : "°C", "pneumaticcraft.gui.tubeModule.simpleConfig.turn" : "Emit when", "pneumaticcraft.gui.universalSensor.desc.block_comparator" : "This sensor setting simulates a Redstone Comparator at the position(s) marked by the GPS (Area) Tool, so the output redstone signal is proportional to the contents of inventories at those positions. If the comparator output would be side dependant, the highest signal will be emitted.\nIn the case of multiple positions, the highest comparator value from any position will be emitted.", "pneumaticcraft.gui.universalSensor.desc.block_heat" : "The block position(s) marked by the GPS (Area) Tool are monitored for heat. When the temperature of the monitored block is higher than the temperature in the text box (in °C) the sensor will emit a redstone level of 15, and 0 if not.\nIf the textfield is empty, the output level is proportional to the temperature, scaling from 0°C (redstone=0) through 400°C (redstone=15).\nIn the case of multiple positions, the position with the highest temperature is used.", From 32de05e28e8376e0d4f766b8e3ec5eee8f3cbc3b Mon Sep 17 00:00:00 2001 From: Johannes Lundberg Date: Sat, 25 Nov 2023 16:11:19 -0700 Subject: [PATCH 3/5] Add upgraded version and advanced config --- .../pneumaticcraft/client/ClientSetup.java | 2 +- .../SimpleThermostatModuleScreen.java | 116 +++++++ .../tubemodule/ThermostatModuleScreen.java | 285 ++++++++++++++++-- .../gui/widget/WidgetColorSelector.java | 4 + .../PacketSyncThermostatModuleToClient.java | 6 +- .../tubemodules/AbstractTubeModule.java | 4 + .../tubemodules/ModuleNetworkManager.java | 2 +- .../common/tubemodules/ThermostatModule.java | 50 ++- .../assets/pneumaticcraft/lang/en_us.json | 3 + 9 files changed, 426 insertions(+), 46 deletions(-) create mode 100644 src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/SimpleThermostatModuleScreen.java diff --git a/src/main/java/me/desht/pneumaticcraft/client/ClientSetup.java b/src/main/java/me/desht/pneumaticcraft/client/ClientSetup.java index a70daaef8..6f4faee1c 100644 --- a/src/main/java/me/desht/pneumaticcraft/client/ClientSetup.java +++ b/src/main/java/me/desht/pneumaticcraft/client/ClientSetup.java @@ -418,7 +418,7 @@ private static void registerTubeModuleFactories() { TubeModuleClientRegistry.registerTubeModuleGUI(Names.MODULE_SAFETY_VALVE, PressureGaugeModuleScreen::createGUI); TubeModuleClientRegistry.registerTubeModuleGUI(Names.MODULE_REDSTONE, RedstoneModuleScreen::new); TubeModuleClientRegistry.registerTubeModuleGUI(Names.MODULE_LOGISTICS, LogisticsModuleScreen::new); - TubeModuleClientRegistry.registerTubeModuleGUI(Names.MODULE_THERMOSTAT, ThermostatModuleScreen::new); + TubeModuleClientRegistry.registerTubeModuleGUI(Names.MODULE_THERMOSTAT, ThermostatModuleScreen::createGUI); TubeModuleClientRegistry.registerTubeModuleRenderer(Names.MODULE_AIR_GRATE, AirGrateRenderer::new); TubeModuleClientRegistry.registerTubeModuleRenderer(Names.MODULE_REDSTONE, RedstoneRenderer::new); diff --git a/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/SimpleThermostatModuleScreen.java b/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/SimpleThermostatModuleScreen.java new file mode 100644 index 000000000..99269d960 --- /dev/null +++ b/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/SimpleThermostatModuleScreen.java @@ -0,0 +1,116 @@ +/* + * This file is part of pnc-repressurized. + * + * pnc-repressurized is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pnc-repressurized is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pnc-repressurized. If not, see . + */ + +package me.desht.pneumaticcraft.client.gui.tubemodule; + +import me.desht.pneumaticcraft.client.gui.widget.WidgetCheckBox; +import me.desht.pneumaticcraft.client.gui.widget.WidgetColorSelector; +import me.desht.pneumaticcraft.client.gui.widget.WidgetLabel; +import me.desht.pneumaticcraft.client.gui.widget.WidgetTextField; +import me.desht.pneumaticcraft.client.gui.widget.WidgetTextFieldNumber; +import me.desht.pneumaticcraft.common.network.NetworkHandler; +import me.desht.pneumaticcraft.common.network.PacketSyncThermostatModuleToServer; +import me.desht.pneumaticcraft.common.network.PacketUpdatePressureModule; +import me.desht.pneumaticcraft.common.network.PacketTubeModuleColor; +import me.desht.pneumaticcraft.common.tubemodules.AbstractTubeModule; +import me.desht.pneumaticcraft.common.tubemodules.ThermostatModule; +import me.desht.pneumaticcraft.lib.Textures; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.DyeColor; + +import static me.desht.pneumaticcraft.common.util.PneumaticCraftUtils.xlate; + +public class SimpleThermostatModuleScreen extends AbstractTubeModuleScreen { + private int color; + private int threshold; + private WidgetTextFieldNumber thresholdField; + + public SimpleThermostatModuleScreen(ThermostatModule module) { + super(module); + + ySize = 57; + } + + @Override + public void init() { + super.init(); + + color = module.getColorChannel(); + threshold = module.getThreshold(); + + addLabel(getTitle(), guiLeft + xSize / 2, guiTop + 5, WidgetLabel.Alignment.CENTRE); + + int x = guiLeft + 10; + int y = guiTop + 24; + WidgetLabel colorLabel; + addRenderableWidget(colorLabel = new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.channel"))); + + x = guiLeft + 10 + colorLabel.getWidth() + 10; + WidgetColorSelector colorSelector = new WidgetColorSelector(x, y-4, w -> color = w.getColor().getId()) + .withInitialColor(DyeColor.byId(color)); + addRenderableWidget(colorSelector); + + if (module.isUpgraded()) { + x = guiLeft + 10 + colorLabel.getWidth() + 10 + colorSelector.getWidth() + 10; + WidgetCheckBox advancedMode = new WidgetCheckBox(x, y, 0xFF404040, Component.literal("Advanced"), b -> { + module.advancedConfig = b.checked; + NetworkHandler.sendToServer(new PacketUpdatePressureModule(module)); + }).setChecked(false); + advancedMode.setTooltip(Tooltip.create(xlate("pneumaticcraft.gui.tubeModule.advancedConfig.tooltip"))); + addRenderableWidget(advancedMode); + } + + x = guiLeft + 10; + y = guiTop + 22 + colorLabel.getHeight() + 10; + WidgetLabel thresholdLabel; + addRenderableWidget(thresholdLabel = new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.simpleConfig.threshold"))); + + x = guiLeft + 10 + thresholdLabel.getWidth() + 5; + thresholdField = new WidgetTextFieldNumber(font, x, y-1, 30, font.lineHeight + 2).setDecimals(0); + addRenderableWidget(thresholdField); + thresholdField.setWidth(40); + setInitialFocus(thresholdField); + thresholdField.setValue(threshold); + + x = guiLeft + 10 + thresholdLabel.getWidth() + thresholdField.getWidth() + 10; + addRenderableWidget(new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.celsius"))); + } + + @Override + public void tick() { + super.tick(); + if (module.advancedConfig) { + minecraft.setScreen(new ThermostatModuleScreen(module)); + } + } + + @Override + protected ResourceLocation getTexture() { + return Textures.GUI_MODULE_SIMPLE; + } + + @Override + public void removed() { + super.removed(); + + module.setColorChannel(color); + module.setThreshold(thresholdField.getIntValue()); + NetworkHandler.sendToServer(new PacketSyncThermostatModuleToServer(module)); + } +} diff --git a/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java b/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java index 0505f99b9..e38c4a86a 100644 --- a/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java +++ b/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java @@ -17,29 +17,59 @@ package me.desht.pneumaticcraft.client.gui.tubemodule; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat; +import me.desht.pneumaticcraft.client.gui.widget.WidgetAnimatedStat; +import me.desht.pneumaticcraft.client.gui.widget.WidgetCheckBox; import me.desht.pneumaticcraft.client.gui.widget.WidgetColorSelector; import me.desht.pneumaticcraft.client.gui.widget.WidgetLabel; -import me.desht.pneumaticcraft.client.gui.widget.WidgetTextField; -import me.desht.pneumaticcraft.client.gui.widget.WidgetTextFieldNumber; +import me.desht.pneumaticcraft.client.gui.widget.WidgetTooltipArea; import me.desht.pneumaticcraft.common.network.NetworkHandler; import me.desht.pneumaticcraft.common.network.PacketSyncThermostatModuleToServer; -import me.desht.pneumaticcraft.common.network.PacketTubeModuleColor; +import me.desht.pneumaticcraft.common.network.PacketUpdatePressureModule; +import me.desht.pneumaticcraft.common.tubemodules.AbstractTubeModule; import me.desht.pneumaticcraft.common.tubemodules.ThermostatModule; +import me.desht.pneumaticcraft.common.util.PneumaticCraftUtils; import me.desht.pneumaticcraft.lib.Textures; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; import net.minecraft.world.item.DyeColor; +import org.joml.Matrix4f; + import static me.desht.pneumaticcraft.common.util.PneumaticCraftUtils.xlate; public class ThermostatModuleScreen extends AbstractTubeModuleScreen { private int color; - private int threshold; - private WidgetTextFieldNumber thresholdField; + WidgetColorSelector colorSelector; + private EditBox lowerBoundField; + private EditBox higherBoundField; + private int graphLowY; + private int graphHighY; + private int graphLeft; + private int graphRight; + private Rect2i lowerBoundArea, higherBoundArea; + private boolean grabLower, grabHigher; + + public static AbstractTubeModuleScreen createGUI(AbstractTubeModule module) { + return module.isUpgraded() ? new ThermostatModuleScreen((ThermostatModule)module) + : new SimpleThermostatModuleScreen((ThermostatModule)module); + } public ThermostatModuleScreen(ThermostatModule module) { super(module); - - ySize = 57; + ySize = 191; } @Override @@ -47,47 +77,242 @@ public void init() { super.init(); color = module.getColorChannel(); - threshold = module.getThreshold(); addLabel(getTitle(), guiLeft + xSize / 2, guiTop + 5, WidgetLabel.Alignment.CENTRE); int x = guiLeft + 10; - int y = guiTop + 24; + int y = guiTop + 22; + WidgetLabel colorLabel; addRenderableWidget(colorLabel = new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.channel"))); - x = guiLeft + 10 + colorLabel.getWidth() + 10; - addRenderableWidget(new WidgetColorSelector(x, y-4, w -> color = w.getColor().getId()) - .withInitialColor(DyeColor.byId(color))); + x = guiLeft + 10 + colorLabel.getWidth() + 7; + colorSelector = new WidgetColorSelector(x, y-2, w -> color = w.getColor().getId()) + .withInitialColor(DyeColor.byId(color)); + addRenderableWidget(colorSelector); + + x = guiLeft + 10 + colorLabel.getWidth() + 7 + colorSelector.getWidth() + 10; + WidgetCheckBox advancedMode = new WidgetCheckBox(x, y, 0xFF404040, Component.literal("Advanced"), b -> { + module.advancedConfig = b.checked; + NetworkHandler.sendToServer(new PacketUpdatePressureModule(module)); + }).setChecked(true); + advancedMode.setTooltip(Tooltip.create(xlate("pneumaticcraft.gui.tubeModule.advancedConfig.tooltip"))); + addRenderableWidget(advancedMode); + + int xStart = (width - xSize) / 2; + int yStart = (height - ySize) / 2; + + addLabel(Component.literal("lower"), guiLeft + 15, guiTop + 33); + addLabel(Component.literal("°C"), guiLeft + 60, guiTop + 44); + addLabel(Component.literal("higher"), guiLeft + 140, guiTop + 33); + + addLabel(title, width / 2 - font.width(title) / 2, guiTop + 5); + + lowerBoundField = new EditBox(font, xStart + 15, yStart + 43, 40, 10, + Component.literal(PneumaticCraftUtils.roundNumberTo(module.lowerBound, 0))); + lowerBoundField.setResponder(s -> updateBoundFromTextfield(0)); + addRenderableWidget(lowerBoundField); + + higherBoundField = new EditBox(font, xStart + 130, yStart + 43, 40, 10, + Component.literal(PneumaticCraftUtils.roundNumberTo(module.higherBound, 0))); + higherBoundField.setResponder(s -> updateBoundFromTextfield(1)); + addRenderableWidget(higherBoundField); - x = guiLeft + 10; - y = guiTop + 22 + colorLabel.getHeight() + 10; - WidgetLabel thresholdLabel; - addRenderableWidget(thresholdLabel = new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.simpleConfig.threshold"))); + graphLowY = guiTop + 158; + graphHighY = guiTop + 98; + graphLeft = guiLeft + 22; + graphRight = guiLeft + 172; - x = guiLeft + 10 + thresholdLabel.getWidth() + 5; - thresholdField = new WidgetTextFieldNumber(font, x, y-1, 30, font.lineHeight + 2).setDecimals(0); - addRenderableWidget(thresholdField); - thresholdField.setWidth(40); - setInitialFocus(thresholdField); - thresholdField.setValue(threshold); + addRenderableWidget(new WidgetTooltipArea(graphLeft - 20, graphHighY, 25, graphLowY - graphHighY, xlate("pneumaticcraft.gui.redstone"))); + addRenderableWidget(new WidgetTooltipArea(graphLeft, graphLowY - 5, graphRight - graphLeft, 25, xlate("pneumaticcraft.gui.temperature"))); - x = guiLeft + 10 + thresholdLabel.getWidth() + thresholdField.getWidth() + 10; - addRenderableWidget(new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.celsius"))); + WidgetAnimatedStat stat = new WidgetAnimatedStat(this, xlate("pneumaticcraft.gui.tab.info"), + WidgetAnimatedStat.StatIcon.of(Textures.GUI_INFO_LOCATION), xStart, yStart + 5, 0xFF8888FF, null, true); + stat.setText(xlate("pneumaticcraft.gui.tab.info.tubeModule")); + stat.setBeveled(true); + addRenderableWidget(stat); + + higherBoundArea = new Rect2i(guiLeft + 11, guiTop + 59, 158, 15); + lowerBoundArea = new Rect2i(guiLeft + 11, guiTop + 73, 158, 15); } @Override protected ResourceLocation getTexture() { - return Textures.GUI_MODULE_SIMPLE; + return Textures.GUI_TUBE_MODULE; } @Override - public void removed() { - super.removed(); + public void drawForeground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + int scrollbarLowerBoundX = temperatureToX((int)module.lowerBound); + int scrollbarHigherBoundX = temperatureToX((int)module.higherBound); + + graphics.blit(getTexture(), scrollbarLowerBoundX, guiTop + 73, 183, 0, 15, 12); + graphics.blit(getTexture(), scrollbarHigherBoundX, guiTop + 59, 183, 0, 15, 12); + + renderGraph(graphics); - module.setColorChannel(color); - module.setThreshold(thresholdField.getIntValue()); - // NetworkHandler.sendToServer(new PacketTubeModuleColor(module)); + // Update bounds and advanced state + NetworkHandler.sendToServer(new PacketUpdatePressureModule(module)); + // Update channel NetworkHandler.sendToServer(new PacketSyncThermostatModuleToServer(module)); + + graphics.hLine(graphLeft + 4, graphRight, graphHighY + (graphLowY - graphHighY) * (15 - module.getLevel()) / 15, 0xFFFF0000); + String status = I18n.get("pneumaticcraft.gui.tubeModule.simpleConfig.temperature") + + " " + PneumaticCraftUtils.roundNumberTo(module.getTemperature(), 0) + " °C"; + graphics.drawString(font, status, guiLeft + xSize / 2f - font.width(status) / 2f, guiTop + 175, 0xFF404040, false); + + // the actual graph data + RenderSystem.setShader(GameRenderer::getPositionColorShader); + BufferBuilder bufferBuilder = Tesselator.getInstance().getBuilder(); + bufferBuilder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); + RenderSystem.enableBlend(); + RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + Matrix4f posMat = graphics.pose().last().pose(); + float temperatureRange = ThermostatModule.MAX_VALUE - ThermostatModule.MIN_VALUE; + for (int i = 0; i < 16; i++) { + float y = graphHighY + (graphLowY - graphHighY) * (15 - i) / 15f; + float x = graphLeft + (graphRight - graphLeft) * (module.getTemperatureForLevel(i) - ThermostatModule.MIN_VALUE) / temperatureRange; + bufferBuilder.vertex(posMat, x, y, 90f).color(0.25f + i * 0.05f, 0f, 0f, 1.0f).endVertex(); + } + Tesselator.getInstance().end(); + RenderSystem.disableBlend(); + + } + + private void renderGraph(GuiGraphics graphics) { + graphics.vLine(graphLeft, graphHighY, graphLowY, 0xFF303030); + for (int i = 0; i < 16; i++) { + boolean longer = i % 5 == 0; + if (longer) { + String txt = String.valueOf(i); + graphics.drawString(font, txt, graphLeft - 5 - font.width(txt), graphHighY + (graphLowY - graphHighY) * (15 - i) / 15f - 3, 0xFF303030, false); + graphics.hLine(graphLeft + 4, graphRight, graphHighY + (graphLowY - graphHighY) * (15 - i) / 15, i == 0 ? 0xFF303030 : 0x33000000); + + } + graphics.hLine(graphLeft - (longer ? 5 : 3), graphLeft + 3, graphHighY + (graphLowY - graphHighY) * (15 - i) / 15, 0xFF303030); + } + + int offset = 0; // offset = (temp + 273) * (100/2273) + String txt = String.valueOf(-273); + graphics.drawString(font, txt, graphLeft + (graphRight - graphLeft) * offset / 100f - font.width(txt) / 2f - 3, graphLowY + 6, 0xFF303030, false); + graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphHighY, graphLowY - 2, 0x33000000); + graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphLowY - 5, graphLowY + 3, 0xFF303030); + + offset = 12; + txt = String.valueOf(0); + graphics.drawString(font, txt, graphLeft + (graphRight - graphLeft) * offset / 100f - font.width(txt) / 2f + 1, graphLowY + 6, 0xFF303030, false); + graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphHighY, graphLowY - 2, 0x33000000); + graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphLowY - 5, graphLowY + 3, 0xFF303030); + + offset = 56; + txt = String.valueOf(1000); + graphics.drawString(font, txt, graphLeft + (graphRight - graphLeft) * offset / 100f - font.width(txt) / 2f + 1, graphLowY + 6, 0xFF303030, false); + graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphHighY, graphLowY - 2, 0x33000000); + graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphLowY - 5, graphLowY + 3, 0xFF303030); + + offset = 100; + txt = String.valueOf(2000); + graphics.drawString(font, txt, graphLeft + (graphRight - graphLeft) * offset / 100f - font.width(txt) / 2f - 5, graphLowY + 6, 0xFF303030, false); + graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphHighY, graphLowY - 2, 0x33000000); + graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphLowY - 5, graphLowY + 3, 0xFF303030); + } + + private void updateBoundFromTextfield(int fieldId) { + try { + float prev; + switch (fieldId) { + case 0 -> { + prev = module.lowerBound; + module.lowerBound = Mth.clamp(Integer.parseInt(lowerBoundField.getValue()), + ThermostatModule.MIN_VALUE, ThermostatModule.MAX_VALUE); + if (!Mth.equal(module.lowerBound, prev)) { + NetworkHandler.sendToServer(new PacketUpdatePressureModule(module)); + } + } + case 1 -> { + prev = module.higherBound; + module.higherBound = Mth.clamp(Integer.parseInt(higherBoundField.getValue()), + ThermostatModule.MIN_VALUE, ThermostatModule.MAX_VALUE); + if (!Mth.equal(module.higherBound, prev)) { + NetworkHandler.sendToServer(new PacketUpdatePressureModule(module)); + } + } + default -> throw new IllegalArgumentException("unknown field id " + fieldId); + } + } catch (NumberFormatException ignored) { + } + } + + private int xToTemperature(double mouseX) { + float sliderWidth = 158 - 12; + int sliderLeft = guiLeft + 11; + float temperatureRange = ThermostatModule.MAX_VALUE - ThermostatModule.MIN_VALUE; + float xNormalized = Math.max(0f, Math.min(1f, ((float)mouseX - sliderLeft) / sliderWidth)); + int temperature = (int)(xNormalized * temperatureRange) + ThermostatModule.MIN_VALUE; + return temperature; + } + + private int temperatureToX(int temperature) { + float sliderWidth = 158 - 12; + int sliderLeft = guiLeft + 11; + float temperatureRange = ThermostatModule.MAX_VALUE - ThermostatModule.MIN_VALUE; + float tempNormalized = Math.max(ThermostatModule.MIN_VALUE, + Math.min(ThermostatModule.MAX_VALUE, ((float)temperature - ThermostatModule.MIN_VALUE) / temperatureRange)); + int x = (int)(tempNormalized * sliderWidth) + sliderLeft; + return x; + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { + if (!colorSelector.isExpanded() && lowerBoundArea.contains((int)mouseX, (int)mouseY)) { + module.lowerBound = xToTemperature(mouseX); + grabLower = true; + return true; + } else if (!colorSelector.isExpanded() && higherBoundArea.contains((int)mouseX, (int)mouseY)) { + module.higherBound = xToTemperature(mouseX); + grabHigher = true; + return true; + } + return super.mouseClicked(mouseX, mouseY, mouseButton); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int clickedMouseButton, double dx, double dy) { + if (grabLower) { + module.lowerBound = xToTemperature(mouseX); + return true; + } else if (grabHigher) { + module.higherBound = xToTemperature(mouseX); + return true; + } else { + return super.mouseDragged(mouseX, mouseY, clickedMouseButton, dx, dy); + } + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int state) { + if (grabLower) { + NetworkHandler.sendToServer(new PacketUpdatePressureModule(module)); + grabLower = false; + return true; + } else if (grabHigher) { + NetworkHandler.sendToServer(new PacketUpdatePressureModule(module)); + grabHigher = false; + return true; + } else { + return super.mouseReleased(mouseX, mouseY, state); + } + } + + @Override + public void tick() { + super.tick(); + + if (!module.advancedConfig) minecraft.setScreen(new SimpleThermostatModuleScreen(module)); + + if (!lowerBoundField.isFocused()) + lowerBoundField.setValue(PneumaticCraftUtils.roundNumberTo(module.lowerBound, 0)); + if (!higherBoundField.isFocused()) + higherBoundField.setValue(PneumaticCraftUtils.roundNumberTo(module.higherBound, 0)); } } diff --git a/src/main/java/me/desht/pneumaticcraft/client/gui/widget/WidgetColorSelector.java b/src/main/java/me/desht/pneumaticcraft/client/gui/widget/WidgetColorSelector.java index 21709a61d..a0f6d8e76 100644 --- a/src/main/java/me/desht/pneumaticcraft/client/gui/widget/WidgetColorSelector.java +++ b/src/main/java/me/desht/pneumaticcraft/client/gui/widget/WidgetColorSelector.java @@ -50,6 +50,10 @@ public WidgetColorSelector withInitialColor(DyeColor color) { return this; } + public boolean isExpanded() { + return expanded; + } + public DyeColor getColor() { return color; } diff --git a/src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToClient.java b/src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToClient.java index b8b94cda3..cb6af0994 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToClient.java +++ b/src/main/java/me/desht/pneumaticcraft/common/network/PacketSyncThermostatModuleToClient.java @@ -35,7 +35,7 @@ public class PacketSyncThermostatModuleToClient extends LocationIntPacket { private final Direction side; private final int channel; private final int level; - private final double temperature; + private final int temperature; public PacketSyncThermostatModuleToClient(ThermostatModule module) { super(module.getTube().getBlockPos()); @@ -51,7 +51,7 @@ public PacketSyncThermostatModuleToClient(ThermostatModule module) { channel = buffer.readByte(); side = buffer.readEnum(Direction.class); level = buffer.readInt(); - temperature = buffer.readDouble(); + temperature = buffer.readInt(); } @Override @@ -60,7 +60,7 @@ public void toBytes(FriendlyByteBuf buf) { buf.writeByte(channel); buf.writeEnum(side); buf.writeInt(level); - buf.writeDouble(temperature); + buf.writeInt(temperature); } public void handle(Supplier ctx) { diff --git a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/AbstractTubeModule.java b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/AbstractTubeModule.java index 8881a14e8..dc6cfe25c 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/AbstractTubeModule.java +++ b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/AbstractTubeModule.java @@ -288,4 +288,8 @@ public void onRemoved() { public boolean isInlineAndFocused(PressureTubeBlock.TubeHitInfo hitInfo) { return false; } + + public boolean canConnectTo(AbstractTubeModule other) { + return this.getClass() == other.getClass(); + } } diff --git a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ModuleNetworkManager.java b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ModuleNetworkManager.java index dbfeab0f6..d297bdb92 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ModuleNetworkManager.java +++ b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ModuleNetworkManager.java @@ -60,7 +60,7 @@ private Set computeConnections(AbstractTubeModule module) { while (!pendingPositions.isEmpty()) { BlockPos pos = pendingPositions.pop(); PneumaticCraftUtils.getTileEntityAt(level, pos, PressureTubeBlockEntity.class).ifPresent(tube -> tube.tubeModules() - .filter(tm -> tm instanceof INetworkedModule) + .filter(tm -> tm instanceof INetworkedModule && tm.canConnectTo(module)) .forEach(modules::add)); for (Direction dir : DirectionUtil.VALUES) { BlockPos pos1 = pos.relative(dir); diff --git a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java index 546d1eecb..469bf6e42 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java +++ b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java @@ -53,21 +53,33 @@ public class ThermostatModule extends AbstractTubeModule implements INetworkedModule { + public static final int MIN_VALUE = -273; + public static final int MAX_VALUE = 2000; + private int colorChannel; - private double temperature = 0.0; + private int temperature = 0; private int level; private int threshold; private boolean update = true; public ThermostatModule(Direction dir, PressureTubeBlockEntity pressureTube) { super(dir, pressureTube); + lowerBound = ThermostatModule.MIN_VALUE; + higherBound = ThermostatModule.MAX_VALUE; } - public double getTemperature() { + public int getTemperature() { return this.temperature; } - public void setTemperature(double temperature) { + public int getTemperatureForLevel(int level) { + float temperatureRange = higherBound - lowerBound; + float levelNormalized = (float)level / 15f; + float temperature = levelNormalized * temperatureRange + lowerBound; + return (int)temperature; + } + + public void setTemperature(int temperature) { this.temperature = temperature; } @@ -125,7 +137,12 @@ protected double getHeight() { @Override public void addInfo(List curInfo) { super.addInfo(curInfo); - curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.tubeModule.threshold_temp", PneumaticCraftUtils.roundNumberTo(getThreshold(), 1))); + if (advancedConfig) { + curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.tubeModule.threshold_temp_bounds", + PneumaticCraftUtils.roundNumberTo(lowerBound, 0), PneumaticCraftUtils.roundNumberTo(higherBound, 0))); + } else { + curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.tubeModule.threshold_temp", PneumaticCraftUtils.roundNumberTo(getThreshold(), 1))); + } curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.thermostatModule.temperature", temperature)); curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.thermostatModule.level", level)); } @@ -156,6 +173,11 @@ public void onNeighborTileUpdate() { updateInputLevel(); } + @Override + public boolean canConnectTo(AbstractTubeModule other) { + return true; + } + @Override public void tickServer() { super.tickServer(); @@ -167,17 +189,23 @@ public void tickServer() { } } - private void updateInputLevel() { + public void updateInputLevel() { Level world = Objects.requireNonNull(pressureTube.getLevel()); - BlockPos pos = pressureTube.getBlockPos().relative(getDirection()); HeatExchangerManager.getInstance().getLogic(world, pos, null) - .ifPresent(logic -> setTemperature(logic.getTemperature() - 273)); + .ifPresent(logic -> setTemperature((int)logic.getTemperature() - 273)); int level = 0; - if (temperature >= threshold) { - level = 15; + if (advancedConfig) { + float temperatureRange = higherBound - lowerBound; + float temperatureNormalized = (temperature - lowerBound) / temperatureRange; + level = (int)(15f * temperatureNormalized); + level = Math.max(0, Math.min(15, level)); + } else { + if (temperature >= threshold) { + level = 15; + } } if (this.level != level) { @@ -192,7 +220,7 @@ public CompoundTag writeToNBT(CompoundTag tag) { tag.putByte("channel", (byte) colorChannel); tag.putByte("level", (byte) level); - tag.putDouble("temperature", temperature); + tag.putInt("temperature", temperature); tag.putInt("threshold", threshold); return tag; @@ -204,7 +232,7 @@ public void readFromNBT(CompoundTag tag) { colorChannel = tag.getByte("channel"); level = tag.getByte("level"); - temperature = tag.getDouble("temperature"); + temperature = tag.getInt("temperature"); threshold = tag.getInt("threshold"); } diff --git a/src/main/resources/assets/pneumaticcraft/lang/en_us.json b/src/main/resources/assets/pneumaticcraft/lang/en_us.json index 530fd38b5..72ec5ca98 100644 --- a/src/main/resources/assets/pneumaticcraft/lang/en_us.json +++ b/src/main/resources/assets/pneumaticcraft/lang/en_us.json @@ -1713,6 +1713,7 @@ "pneumaticcraft.gui.thermopneumatic.dumpInput" : "Dump Input Tank\n§7Void any unwanted / excess fluids from the input tank", "pneumaticcraft.gui.thermopneumatic.moveInput" : "Move Fluid\n§7Move any fluid from the input tank to the output tank, if possible\n§oHold Shift to dump fluid", "pneumaticcraft.gui.threshold" : "Threshold(bar)", + "pneumaticcraft.gui.temperature" : "Temperature (°C)", "pneumaticcraft.gui.tooltip.aerial_interface.xpDisabled" : "XP handling disabled", "pneumaticcraft.gui.tooltip.air" : "Air: %s mL", "pneumaticcraft.gui.tooltip.airUsage" : "Using: %s mL/t", @@ -1814,6 +1815,7 @@ "pneumaticcraft.gui.tubeModule.simpleConfig.higherThan" : "Higher than", "pneumaticcraft.gui.tubeModule.simpleConfig.lowerThan" : "Lower than", "pneumaticcraft.gui.tubeModule.simpleConfig.threshold" : "Threshold:", + "pneumaticcraft.gui.tubeModule.simpleConfig.temperature" : "Temperature:", "pneumaticcraft.gui.tubeModule.celsius" : "°C", "pneumaticcraft.gui.tubeModule.simpleConfig.turn" : "Emit when", "pneumaticcraft.gui.universalSensor.desc.block_comparator" : "This sensor setting simulates a Redstone Comparator at the position(s) marked by the GPS (Area) Tool, so the output redstone signal is proportional to the contents of inventories at those positions. If the comparator output would be side dependant, the highest signal will be emitted.\nIn the case of multiple positions, the highest comparator value from any position will be emitted.", @@ -1957,6 +1959,7 @@ "pneumaticcraft.waila.temperatureLoss" : "§7Heat Extraction: §f%d%%", "pneumaticcraft.waila.tubeModule.threshold" : "Threshold: §e%d bar", "pneumaticcraft.waila.tubeModule.threshold_temp" : "Threshold: §e%d °C", + "pneumaticcraft.waila.tubeModule.threshold_temp_bounds" : "Threshold bounds: §e%d - §e%d °C", "programmingPuzzle.pneumaticcraft.area.name" : "Area", "programmingPuzzle.pneumaticcraft.block_right_click.name" : "Right Click", "programmingPuzzle.pneumaticcraft.comment.name" : "Comment", From dc2a4aa5592ed45640627eaf1aa621042ed39b00 Mon Sep 17 00:00:00 2001 From: Johannes Lundberg Date: Sat, 25 Nov 2023 20:09:53 -0700 Subject: [PATCH 4/5] Add book entry and minor tweaks --- .../tubemodule/ThermostatModuleScreen.java | 54 +++++++----------- .../common/tubemodules/ThermostatModule.java | 3 +- .../assets/pneumaticcraft/lang/en_us.json | 4 +- .../entries/tubes/thermostat_module.json | 30 ++++++++++ .../en_us/entries/tubes/tube_modules.json | 1 + .../textures/patchouli/thermostat_gui.png | Bin 0 -> 7518 bytes 6 files changed, 57 insertions(+), 35 deletions(-) create mode 100644 src/main/resources/assets/pneumaticcraft/patchouli_books/book/en_us/entries/tubes/thermostat_module.json create mode 100644 src/main/resources/assets/pneumaticcraft/textures/patchouli/thermostat_gui.png diff --git a/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java b/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java index e38c4a86a..a85d1621d 100644 --- a/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java +++ b/src/main/java/me/desht/pneumaticcraft/client/gui/tubemodule/ThermostatModuleScreen.java @@ -80,6 +80,8 @@ public void init() { addLabel(getTitle(), guiLeft + xSize / 2, guiTop + 5, WidgetLabel.Alignment.CENTRE); + int xStart = (width - xSize) / 2; + int yStart = (height - ySize) / 2; int x = guiLeft + 10; int y = guiTop + 22; @@ -87,7 +89,11 @@ public void init() { addRenderableWidget(colorLabel = new WidgetLabel(x, y, xlate("pneumaticcraft.gui.tubeModule.channel"))); x = guiLeft + 10 + colorLabel.getWidth() + 7; - colorSelector = new WidgetColorSelector(x, y-2, w -> color = w.getColor().getId()) + colorSelector = new WidgetColorSelector(x, y-2, w -> { + color = w.getColor().getId(); + module.setColorChannel(color); + NetworkHandler.sendToServer(new PacketSyncThermostatModuleToServer(module)); + }) .withInitialColor(DyeColor.byId(color)); addRenderableWidget(colorSelector); @@ -99,9 +105,6 @@ public void init() { advancedMode.setTooltip(Tooltip.create(xlate("pneumaticcraft.gui.tubeModule.advancedConfig.tooltip"))); addRenderableWidget(advancedMode); - int xStart = (width - xSize) / 2; - int yStart = (height - ySize) / 2; - addLabel(Component.literal("lower"), guiLeft + 15, guiTop + 33); addLabel(Component.literal("°C"), guiLeft + 60, guiTop + 44); addLabel(Component.literal("higher"), guiLeft + 140, guiTop + 33); @@ -151,7 +154,7 @@ public void drawForeground(GuiGraphics graphics, int mouseX, int mouseY, float p renderGraph(graphics); - // Update bounds and advanced state + // Update bounds and advancedConfig state NetworkHandler.sendToServer(new PacketUpdatePressureModule(module)); // Update channel NetworkHandler.sendToServer(new PacketSyncThermostatModuleToServer(module)); @@ -192,29 +195,16 @@ private void renderGraph(GuiGraphics graphics) { graphics.hLine(graphLeft - (longer ? 5 : 3), graphLeft + 3, graphHighY + (graphLowY - graphHighY) * (15 - i) / 15, 0xFF303030); } - int offset = 0; // offset = (temp + 273) * (100/2273) - String txt = String.valueOf(-273); - graphics.drawString(font, txt, graphLeft + (graphRight - graphLeft) * offset / 100f - font.width(txt) / 2f - 3, graphLowY + 6, 0xFF303030, false); - graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphHighY, graphLowY - 2, 0x33000000); - graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphLowY - 5, graphLowY + 3, 0xFF303030); - - offset = 12; - txt = String.valueOf(0); - graphics.drawString(font, txt, graphLeft + (graphRight - graphLeft) * offset / 100f - font.width(txt) / 2f + 1, graphLowY + 6, 0xFF303030, false); - graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphHighY, graphLowY - 2, 0x33000000); - graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphLowY - 5, graphLowY + 3, 0xFF303030); - - offset = 56; - txt = String.valueOf(1000); - graphics.drawString(font, txt, graphLeft + (graphRight - graphLeft) * offset / 100f - font.width(txt) / 2f + 1, graphLowY + 6, 0xFF303030, false); - graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphHighY, graphLowY - 2, 0x33000000); - graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphLowY - 5, graphLowY + 3, 0xFF303030); - - offset = 100; - txt = String.valueOf(2000); - graphics.drawString(font, txt, graphLeft + (graphRight - graphLeft) * offset / 100f - font.width(txt) / 2f - 5, graphLowY + 6, 0xFF303030, false); - graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphHighY, graphLowY - 2, 0x33000000); - graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphLowY - 5, graphLowY + 3, 0xFF303030); + int[] temps = { ThermostatModule.MIN_VALUE, 0, 1000, ThermostatModule.MAX_VALUE }; + int[] adjusts = { -3, 1, 1, -5 }; + for (int i = 0; i < 4; i++) { + int offset = (int)((temps[i] - ThermostatModule.MIN_VALUE) * (100f / (ThermostatModule.MAX_VALUE - ThermostatModule.MIN_VALUE))); + String txt = String.valueOf(temps[i]); + graphics.drawString(font, txt, graphLeft + (graphRight - graphLeft) * offset / 100f - font.width(txt) / 2f + adjusts[i], + graphLowY + 6, 0xFF303030, false); + graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphHighY, graphLowY - 2, 0x33000000); + graphics.vLine(graphLeft + (graphRight - graphLeft) * offset / 100, graphLowY - 5, graphLowY + 3, 0xFF303030); + } } private void updateBoundFromTextfield(int fieldId) { @@ -265,11 +255,11 @@ private int temperatureToX(int temperature) { @Override public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { if (!colorSelector.isExpanded() && lowerBoundArea.contains((int)mouseX, (int)mouseY)) { - module.lowerBound = xToTemperature(mouseX); + module.lowerBound = xToTemperature(mouseX - 7); grabLower = true; return true; } else if (!colorSelector.isExpanded() && higherBoundArea.contains((int)mouseX, (int)mouseY)) { - module.higherBound = xToTemperature(mouseX); + module.higherBound = xToTemperature(mouseX - 7); grabHigher = true; return true; } @@ -279,10 +269,10 @@ public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { @Override public boolean mouseDragged(double mouseX, double mouseY, int clickedMouseButton, double dx, double dy) { if (grabLower) { - module.lowerBound = xToTemperature(mouseX); + module.lowerBound = xToTemperature(mouseX - 7); return true; } else if (grabHigher) { - module.higherBound = xToTemperature(mouseX); + module.higherBound = xToTemperature(mouseX - 7); return true; } else { return super.mouseDragged(mouseX, mouseY, clickedMouseButton, dx, dy); diff --git a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java index 469bf6e42..5fba9ab71 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java +++ b/src/main/java/me/desht/pneumaticcraft/common/tubemodules/ThermostatModule.java @@ -141,7 +141,8 @@ public void addInfo(List curInfo) { curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.tubeModule.threshold_temp_bounds", PneumaticCraftUtils.roundNumberTo(lowerBound, 0), PneumaticCraftUtils.roundNumberTo(higherBound, 0))); } else { - curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.tubeModule.threshold_temp", PneumaticCraftUtils.roundNumberTo(getThreshold(), 1))); + curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.tubeModule.threshold_temp", + PneumaticCraftUtils.roundNumberTo(getThreshold(), 1))); } curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.thermostatModule.temperature", temperature)); curInfo.add(PneumaticCraftUtils.xlate("pneumaticcraft.waila.thermostatModule.level", level)); diff --git a/src/main/resources/assets/pneumaticcraft/lang/en_us.json b/src/main/resources/assets/pneumaticcraft/lang/en_us.json index 72ec5ca98..c2a54c9db 100644 --- a/src/main/resources/assets/pneumaticcraft/lang/en_us.json +++ b/src/main/resources/assets/pneumaticcraft/lang/en_us.json @@ -355,7 +355,7 @@ "gui.tooltip.item.pneumaticcraft.programming_puzzle" : "Used by a Programmer when writing programs to a Drone or Network API. Either keep these pieces in your inventory or put them in an inventory adjacent to the Programmer.", "gui.tooltip.item.pneumaticcraft.raw_salmon_tempura" : "Needs some deep frying!", "gui.tooltip.item.pneumaticcraft.redstone_module" : "§bThis module transmits redstone signals to other Redstone Modules on connected tubes. Right-click with any dye to set the channel; right-click with a wrench to toggle between input and output.\n\nUpgrade with a Module Expansion Card for extra signal processing operations.", - "gui.tooltip.item.pneumaticcraft.thermostat_module" : "§bThis module transmits redstone signals on selected channel when temperature of facing block is above threshold.", + "gui.tooltip.item.pneumaticcraft.thermostat_module" : "§bThis module transmits redstone signals to Redstone Modules on connected tubes based on temperature of facing block. Right-click with any dye to set the channel.\n\nUpgrade with a Module Expansion Card for extra signal processing operations.", "gui.tooltip.item.pneumaticcraft.regulator_tube_module" : "§bThis module limits the pressure allowed on its low side based on the redstone signal it receives. No signal = 4.9 bar, a full signal = 0 bar (no air allowed through), and other signal levels are interpolated. Air is always allowed to travel \"backwards\" through the Regulator, making it usable as a one-way valve.\nWhen upgraded with a Module Expansion Card, the threshold can be configured precisely via GUI.", "gui.tooltip.item.pneumaticcraft.reinforced_chest_kit" : "Sneak+Right-click on any wooden chest to upgrade it to a Reinforced Chest, keeping the contents intact.\nThe old chest will be returned to you as an item drop.", "gui.tooltip.item.pneumaticcraft.reinforced_air_canister" : "A stronger version of the basic Air Canister. In conjunction with a couple of Aerial Interfaces, Charging Modules and an Ender Chest, this could have some wireless pressure transfer possibilities...", @@ -1480,7 +1480,7 @@ "pneumaticcraft.gui.tab.info.smart_chest.push_pull.title" : "Push/Pull Modes", "pneumaticcraft.gui.tab.info.smart_chest.slots" : "§eAlt + Left-Click\n§f• Empty slot: mark slot (and all following slots) closed\n• Empty closed or filtered slot: remove filter\n• Item in slot or on cursor: filter on that item\n• Also hold Shift to set item limit to max\n\n§eAlt + Mouse Wheel\n§f• Filtered slot: adjust item limit\n• Also hold Shift for fast adjust\n\n§eAlt + Cursor Up/Down\n§f• Adjust item limit, like Alt + Mouse Wheel", "pneumaticcraft.gui.tab.info.smart_chest.slots.title" : "Slot Interaction", - "pneumaticcraft.gui.tab.info.tubeModule" : "§0In this interface you can define exactly how a module should behave, dependent on the redstone signal. The signal will be proportional to the pressure interpolated between the lower and higher bounds.", + "pneumaticcraft.gui.tab.info.tubeModule" : "§0In this interface you can define exactly how a module should behave, dependent on the redstone signal. The signal will be proportional to the pressure or temperature interpolated between the lower and higher bounds.", "pneumaticcraft.gui.tab.liquidCompressor.fuel" : "Available Fuels", "pneumaticcraft.gui.tab.liquidHopper.mode.empty" : "Empty out tank.", "pneumaticcraft.gui.tab.liquidHopper.mode.leaveLiquid" : "Leave 1000mB in tank, to filter.", diff --git a/src/main/resources/assets/pneumaticcraft/patchouli_books/book/en_us/entries/tubes/thermostat_module.json b/src/main/resources/assets/pneumaticcraft/patchouli_books/book/en_us/entries/tubes/thermostat_module.json new file mode 100644 index 000000000..53763d344 --- /dev/null +++ b/src/main/resources/assets/pneumaticcraft/patchouli_books/book/en_us/entries/tubes/thermostat_module.json @@ -0,0 +1,30 @@ +{ + "name": "Thermostat Module", + "icon": "pneumaticcraft:thermostat_module", + "category": "pneumaticcraft:tubes", + "advancement": "pneumaticcraft:pressure_tube", + "pages": [ + { + "type": "text", + "text": "This tube module measures the temperature of the block it's facing and emits a redstone signal on configured channel if the temperature is higher than the set threshold." + }, + { + "type": "spotlight", + "item": "pneumaticcraft:module_expansion_card", + "text": "Applying a $(l:tubes/module_expansion_card)Module Expansion Card/$ to the Thermostat Module unlocks the advanced GUI to provide much more control over $(#f00)redstone signal/$ emission. By default, you can provide a threshold level: the signal will be off below that level and fully on above it (or vice versa). If you select the $(bold)Advanced Config/$ toggle in the GUI, you gain even more control (see over)." + }, + { + "type": "image", + "images": [ + "pneumaticcraft:textures/patchouli/thermostat_gui.png" + ], + "text": "$(italic)<0°C = 0 redstone, >1000°C = 15 redstone, 0-1000°C = interpolate (e.g. 200°C = 3 redstone)/$", + "anchor": "img" + }, + { + "type": "crafting", + "text": "Crafting a Thermostat Module", + "recipe": "pneumaticcraft:thermostat_module" + } + ] +} diff --git a/src/main/resources/assets/pneumaticcraft/patchouli_books/book/en_us/entries/tubes/tube_modules.json b/src/main/resources/assets/pneumaticcraft/patchouli_books/book/en_us/entries/tubes/tube_modules.json index a49c4d969..4e151b57a 100644 --- a/src/main/resources/assets/pneumaticcraft/patchouli_books/book/en_us/entries/tubes/tube_modules.json +++ b/src/main/resources/assets/pneumaticcraft/patchouli_books/book/en_us/entries/tubes/tube_modules.json @@ -26,6 +26,7 @@ "pneumaticcraft:tubes/charging_module", "pneumaticcraft:tubes/logistics_module", "pneumaticcraft:tubes/redstone_module", + "pneumaticcraft:tubes/thermostat_module", "pneumaticcraft:tubes/vacuum_module" ] } diff --git a/src/main/resources/assets/pneumaticcraft/textures/patchouli/thermostat_gui.png b/src/main/resources/assets/pneumaticcraft/textures/patchouli/thermostat_gui.png new file mode 100644 index 0000000000000000000000000000000000000000..ef33a42581f9db1fce3c659951540a446826f7b7 GIT binary patch literal 7518 zcmcIo2|Sc*+ka+^Jt1u>nPdr#*=#cyOLhj?g)+=wY8K6mHJqV3c~eQ2PFd0^RD`2a zsBk)E&63KNIF%xjSA=ZeGq%*5)BF3r-}n4}&ph{Y-`D?tUH5g}_jO;-{L9Y9OiW~x z2mk~_=1miimQb$kqD@OZ6QDqvIgLrlK~|mn*jc~HUM}- zHZQgJLv}34KtUNa0R95&z?%iZ%(d5o?U-X!0JeZl1)sdj9K3n@=bm=d5DJY>;xJio zI~Eg;RZ~~P0ssbu!QfG7JPHR#q44TxygCX1_)f!?cpqgz7kME-2H)2OlKiX&Z1zIKbSE4FIB2yc+_XPu&Q*#GLBr%5f!H<9(QPH4>TWO;HP> z2k@8x-4Hz3q*FK~cnF=wVB$*}=nPnLxf(cOBsf1L zS`CF{kmwY40Lh2)BRWuMiG#sjaMB!_G>`rfh(q=LI@@nhypcJjKY~$0s4KvDBP+r{ z6N$usHj++9{zxI4V-f_qaUm?<7#gxLJ+@rz;O(S=3jP*{cm z0W_))iMNsnU)KY;16R`VpRoT@ldS^*t*(YvThaP?W>Du@m>t z_Abc&l-bGAg23DSUtPfgcg?a_H8RsDkPb#25x`<1*z>_r^QJOLtk9KA;F11Rvk8Ob zO{0(rj;uh+N<@n?KP8)Yr5%mL@ny2;1Ukvb)?p>m?___0CzhQlwBlR5t5j>H}V9Es3CWQc&0ayeYjlgI)Vo$x zk$B#TLkr}kX(tAiLjX75kGj7{*|MnMR+!K3VBVdBEbseX-tDUzf))k^UPv_WcLBP5 z_V{NczCk*+HumyIk#&eaEab1EBLVWGMd!E9w+oWMt zI!Hcq6^0LQUsJ&JIB(cO@AoiWB(J8WQNNACeDAlxncKib;tztUJ0E3mvHO8%GtGG6 z)Lxh)`M;jyiZox1UQlK6zjfohie>Qsp#DEvzYM;NdZ`4(?_$!JEHL*_2v}X@kGdC7 z^AT9~?J*ai`CjnLh9CllWAQ7AAd)MW5C{OPpIaCkI)~Q3f&aJ^ZC3Fhhy(e_OPE-ZnzIVfQ{y;sosP^+%2xt=BlM_%P4TRqhD46mqpY z7A~ZyrFi_L{lT`vf{l}At410WH&rY^)KE zB~>BLaq)%v z$G+PaPU$GS@I47Jgqw|=U@dPGnaR!>lc4Gcy=Q7P2=h`3&8D_ zAAfaWNT}|WGd)?{W`vSk`cy8XEi3FdP*Ay{Y`mt3eAej#*{%IkF6H;mtp`e=fiZ#> zBihp1C1dikmHKCIZSnL{JS&N`iX_mbt9#Bx=3FJ1oEOasJQ^e_2l*|?*#Z7rbn|DO z*R{6pHl1eA$eqL8Rb50wc_2Zqg8u28t{Jhj>6zJcwJgu-TFKb>&Af;lTNlT6SWJ+* z=kMm}dTTA<)jdjQQ${_hfmKrSR839I%PqB915*jMgm|U&5F?NJzwYA8R3??in5xV} z_D9{56u9Jq(wBYKwOSEz#Nya5r%tqbdP&R3B+2Lmxkfx92S#d)26{Fl_NIUCAX?nD zwtuXmWayM#2s>TW^gF!v)83ArlpuyXD!cq{Toa>8vwL5n%G zs$=H1o`V;!HRFGn!rPkE;`XUj796k%;H&@pkiGcBl-fT5YLT(LLdOJilaSW3YQ}vv7po)f#NP?SBSri+)oe!E-XGjQ zvSG?TXh46`P-CNTOpS(2-3gdFJ4oPkaM-mhbckX~KRtA$x5+ZOp=f6VRm#iT`_G#Pgx1FN#XWM@)XE)*?Ob6!auEn4Lf(D{r2p*U~dT#2pitRl7A{=c)y< zR(;N)zN?DgeqHFr5RS7s7-X+X3!+F>HWphSFUf?9?7t^>^POxLaW`4%ogT0 zxph_)tvY-IR(@w-(98YT!#GG3Hy+?F-AV6Zx{*_Na>9V4C*$Ig8-y zp*hf-d(sT+{@?_RTmOFaH;AsNFd(!sjoS-<$<9pRL zKhBz0Qp#x~kdW@DR~=X%+HYm$G~ql1>YP;|C*tBZY^_|K5t_NC{9){do>vcJ^WH<( zdY5cI{rVS8-d#%ocy9s)puU}g<$YR>GS0&A z(5pwSxCW(7;6JLS;0W)2>jdp)XlLx*djbYBWk|me6N2SBLbb!kQCcJb@zzNe;D#-C z+4pTXaoG9u=g$-u7b6-HUgh%*oppjX@|Oxh#BU}!NtLhdb#QP( zN=nD@CYk7G6UXg`U7}@I_t*f`sI<>}3X$*`j~46lpnZ;(rY3KgF#Rn#;g$sIM5ABvTg@z4q?F+4kE*Z%KwjW$9orNMDbB7gy2;g(Nv!%0e?O!i%5Fq z`)q!NHoxr}bjWuaX`(S!UuNG8fSgP}_gd--COTWJmx@pfS^(`%8Xecx<;BJoT~AS}Gee zo@PHx2S=6D0FJ|vhR2U@F>K18Ra>;_>m#k!)pfe8dkYJX!9ikka-|B0Z0L-$@`R05 z+|e|xzYwL~6z{gIpr|1bJ@;p(v+ReTc-f7YhWp;wT0)~zuRbX&Yo(+ypi{4Q z5Aikj)1c$U_QQJ7vgXgKCxChtg-W4FxWl_gkW^>OQ&Lj~YH8=z3@F8!j-|oJqh8?S z0UH&Ce2H=HEij8_XJ>28f_dgZ?Wf=C)AdRx#-DKy>)+pM^eAjc-mrAkEBZ`dA2mAy zz*<&YXHYy+Z}IKH1JF~tQ$IwuMpSn&Xq#phs`YD4XNCt zdY?|D^l*TF2t~V}&-}oona3#P&Y+dQ>hlM?doNJtdazZ4UKr!-$IFUc}!mla1m;Rt0GU+j0) zm=5Y-b=~>mNuRh!I2b8yH|B9W{`e~R{{4-+J2@83BOUbGh}Z9fZ}p6QdE_QlezTBX z`)U8=K6%RoCCQQ+x&u40#lp^H#bK% zKI`fi?N>BtuOYfmWVO7ShJ?lmTx4|T2^`MpdY0VPFXcxBJU8#`pEfyiH>#iE`)nJ% ztnbyw(US>L26BD(rknah58e6{X}duyBtA!xKDaLb^%zE?s?H4xgquK7K5&V-;(D&Y zcCHtB@p0^S(&PGiO}hlzbY$7{l7}tCsYCQyVl86WZ9FGQ7~bCYezjVcLW|kRiy~cm zanXgNUHBFlSVO1Go}o0o4hbC|&Fxtm@yl>2F~4J{ma;8yo^U{=A-0>D?VJwz?XpbL zD>Fo=Bw|LJj?1bn8S76@${utZt=f}5$k8i)q1zKbegGDBo1+4WX_c+E*5RaI%Dt-R zaU`ebE$(E4L%Op*$L!r2gZ5MVMS#wJO`W@g<{vEE!g}lNj;nROEp1wzW(g*j*4#Av zv62t0;Z#Cp3M};8`}p;=ELHguV?Pz7y;gKtTJ%NICJp~3v!|wg3E_y6$26_^sgV+`r; Date: Mon, 27 Nov 2023 07:36:03 -0700 Subject: [PATCH 5/5] Change thermostat recipe --- .../pneumaticcraft/recipes/thermostat_module.json | 12 ++++++++---- .../pneumaticcraft/datagen/ModRecipeProvider.java | 7 ++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/generated/resources/data/pneumaticcraft/recipes/thermostat_module.json b/src/generated/resources/data/pneumaticcraft/recipes/thermostat_module.json index 8e916b3b5..68ec5623f 100644 --- a/src/generated/resources/data/pneumaticcraft/recipes/thermostat_module.json +++ b/src/generated/resources/data/pneumaticcraft/recipes/thermostat_module.json @@ -3,17 +3,21 @@ "category": "misc", "key": { "D": { - "item": "minecraft:comparator" - }, - "R": { "tag": "forge:dusts/redstone" }, + "H": { + "item": "pneumaticcraft:heat_pipe" + }, + "M": { + "item": "pneumaticcraft:manometer" + }, "T": { "item": "pneumaticcraft:pressure_tube" } }, "pattern": [ - " R ", + " M ", + " H ", "TDT" ], "result": { diff --git a/src/main/java/me/desht/pneumaticcraft/datagen/ModRecipeProvider.java b/src/main/java/me/desht/pneumaticcraft/datagen/ModRecipeProvider.java index b9ed36532..80ce65c8d 100644 --- a/src/main/java/me/desht/pneumaticcraft/datagen/ModRecipeProvider.java +++ b/src/main/java/me/desht/pneumaticcraft/datagen/ModRecipeProvider.java @@ -653,10 +653,11 @@ protected void buildRecipes(Consumer consumer) { ).save(consumer); shaped(ModItems.THERMOSTAT_MODULE.get(), ModItems.COMPRESSED_IRON_INGOT.get(), - " R /TDT", - 'R', Tags.Items.DUSTS_REDSTONE, + " M / H /TDT", + 'M', ModItems.MANOMETER.get(), + 'H', ModBlocks.HEAT_PIPE.get(), 'T', ModBlocks.PRESSURE_TUBE.get(), - 'D', Blocks.COMPARATOR + 'D', Tags.Items.DUSTS_REDSTONE ).save(consumer); shaped(ModBlocks.PRESSURE_TUBE.get(), 8, ModItems.COMPRESSED_IRON_INGOT.get(),