diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index 67ddba4f02e..42901c8f610 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -1942,6 +1942,7 @@ "config.jade.plugin_gtceu.energy_converter_provider": "[GTCEu] Energy Converter Mode", "config.jade.plugin_gtceu.exhaust_vent_info": "[GTCEu] Exhaust Vent Info", "config.jade.plugin_gtceu.hazard_cleaner_provider": "[GTCEu] Hazard Cleaner", + "config.jade.plugin_gtceu.fluid_pipe_info": "[GTCEu] Fluid Pipe Info", "config.jade.plugin_gtceu.ldp_endpoint": "[GTCEu] Long Distance Pipeline Endpoint Info", "config.jade.plugin_gtceu.machine_mode": "[GTCEu] Machine Mode", "config.jade.plugin_gtceu.maintenance_info": "[GTCEu] Maintenance Info", @@ -2354,6 +2355,8 @@ "gtceu.fluid_pipe.channels": "§eChannels: §f%d", "gtceu.fluid_pipe.cryo_proof": "§6Can handle Cryogenics", "gtceu.fluid_pipe.gas_proof": "§6Can handle Gases", + "gtceu.fluid_pipe.insulated": "§bInsulated", + "gtceu.fluid_pipe.insulated_by_default": "§6Pre-Insulated", "gtceu.fluid_pipe.max_temperature": "§cTemperature Limit: §f%s", "gtceu.fluid_pipe.not_gas_proof": "§4Gases may leak!", "gtceu.fluid_pipe.plasma_proof": "§6Can handle all Plasmas", @@ -4315,6 +4318,13 @@ "item.gtceu.ilc_chip.tooltip": "§7Integrated Logic Circuit", "item.gtceu.ilc_wafer": "ILC Wafer", "item.gtceu.ilc_wafer.tooltip": "§7Raw Integrated Circuit", + "item.gtceu.insulation_wrapper": "Insulation Wrapper", + "item.gtceu.insulation_wrapper.desc": "§bNullify damage from thermogenics/cryogenics", + "item.gtceu.insulation_wrapper.message.already_insulated": "§eAll pipes in this network are already insulated", + "item.gtceu.insulation_wrapper.message.invalid_pipe": "§eNot a fluid pipe", + "item.gtceu.insulation_wrapper.message.removed": "§cRemoved Insulation", + "item.gtceu.insulation_wrapper.message.success": "§aInsulated §f%s pipe(s)", + "item.gtceu.insulation_wrapper.usage": "Shift-Right-Click on fluid pipe network", "item.gtceu.image_module": "Image Module", "item.gtceu.impure_bentonite_dust": "Impure Pile of Bentonite", "item.gtceu.impure_cassiterite_sand_dust": "Impure Pile of Cassiterite Sand", diff --git a/src/generated/resources/assets/gtceu/models/item/insulation_wrapper.json b/src/generated/resources/assets/gtceu/models/item/insulation_wrapper.json new file mode 100644 index 00000000000..95f64924a6a --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/insulation_wrapper.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "gtceu:item/insulation_wrapper" + } +} \ No newline at end of file diff --git a/src/main/java/com/gregtechceu/gtceu/api/blockentity/PipeBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/api/blockentity/PipeBlockEntity.java index 5742b0bee21..97a84fb6ed9 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/blockentity/PipeBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/api/blockentity/PipeBlockEntity.java @@ -14,6 +14,8 @@ import com.gregtechceu.gtceu.api.sync_system.annotations.RerenderOnChanged; import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; +import com.gregtechceu.gtceu.common.blockentity.FluidPipeBlockEntity; +import com.gregtechceu.gtceu.common.data.GTItems; import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; import com.gregtechceu.gtceu.common.data.GTMaterials; import com.gregtechceu.gtceu.utils.ExtendedUseOnContext; @@ -26,6 +28,7 @@ import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionResult; @@ -374,6 +377,15 @@ public ResourceTexture getPipeTexture(boolean isBlock) { } return Pair.of(getPipeTuneTool(), InteractionResult.sidedSuccess(isRemote())); } else if (toolType.contains(GTToolType.CROWBAR)) { + if (this instanceof FluidPipeBlockEntity pipe && pipe.isInsulated() && !pipe.getNodeData().isInsulatedByDefault()) { + if (!isRemote()) { + pipe.setInsulated(false); + player.displayClientMessage(Component.translatable("item.gtceu.insulation_wrapper.message.removed"), true); + Block.popResource(context.getLevel(), this.getBlockPos(), + new ItemStack(GTItems.INSULATION_WRAPPER.get())); + } + return Pair.of(GTToolType.CROWBAR, InteractionResult.sidedSuccess(isRemote())); + } if (!frameMaterial.isNull()) { Block.popResource(context.getLevel(), this.getBlockPos(), GTMaterialBlocks.MATERIAL_BLOCKS.get(TagPrefix.frameGt, frameMaterial).asStack()); diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/Material.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/Material.java index 063d6addcb3..704fa4091f5 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/Material.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/Material.java @@ -1808,6 +1808,27 @@ public Builder fluidPipeProperties(int maxTemp, int throughput, boolean gasProof return this; } + /** + * Add Fluid Pipes to this Material. + * + * @param maxTemp The maximum temperature of Fluid that this Pipe can handle before causing damage to the + * Pipe. + * @param throughput The rate at which Fluid can flow through this Pipe. + * @param gasProof Whether this Pipe can hold Gases. If not, some Gas will be lost as it travels through the + * Pipe. + * @param acidProof Whether this Pipe can hold Acids. If not, the Pipe may lose fluid or cause damage. + * @param cryoProof Whether this Pipe can hold Cryogenic Fluids (below 120K). If not, the Pipe may lose fluid + * or cause damage. + * @param plasmaProof Whether this Pipe can hold Plasmas. If not, the Pipe may lose fluid or cause damage. + * @param insulatedByDefault Whether this Pipe is insulated by default. If not, the Pipe may cause damage when storing thermogenics/cryogenics. + */ + public Builder fluidPipeProperties(int maxTemp, int throughput, boolean gasProof, boolean acidProof, + boolean cryoProof, boolean plasmaProof, boolean insulatedByDefault) { + properties.setProperty(PropertyKey.FLUID_PIPE, + new FluidPipeProperties(maxTemp, throughput, gasProof, acidProof, cryoProof, plasmaProof, insulatedByDefault, 1)); + return this; + } + /** * Add Item Pipes to this Material. * diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/FluidPipeProperties.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/FluidPipeProperties.java index 5f0f3979a75..1b346bb3aa1 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/FluidPipeProperties.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/FluidPipeProperties.java @@ -40,17 +40,21 @@ public class FluidPipeProperties implements IMaterialProperty, IPropertyFluidFil @Getter @Setter private boolean plasmaProof; + @Getter + @Setter + private boolean insulatedByDefault; private final Object2BooleanMap containmentPredicate = new Object2BooleanOpenHashMap<>(); public FluidPipeProperties(int maxFluidTemperature, int throughput, boolean gasProof, boolean acidProof, - boolean cryoProof, boolean plasmaProof, int channels) { + boolean cryoProof, boolean plasmaProof, boolean insulatedByDefault, int channels) { this.maxFluidTemperature = maxFluidTemperature; this.throughput = throughput; this.gasProof = gasProof; if (acidProof) setCanContain(FluidAttributes.ACID, true); this.cryoProof = cryoProof; this.plasmaProof = plasmaProof; + this.insulatedByDefault = insulatedByDefault; this.channels = channels; } @@ -59,7 +63,7 @@ public FluidPipeProperties(int maxFluidTemperature, int throughput, boolean gasP */ public FluidPipeProperties(int maxFluidTemperature, int throughput, boolean gasProof, boolean acidProof, boolean cryoProof, boolean plasmaProof) { - this(maxFluidTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof, 1); + this(maxFluidTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof, false, 1); } @Override @@ -98,6 +102,7 @@ public String toString() { ", cryoProof=" + cryoProof + ", plasmaProof=" + plasmaProof + ", channels=" + channels + + ", insulatedByDefault=" + insulatedByDefault + '}'; } diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/GTModelProperties.java b/src/main/java/com/gregtechceu/gtceu/client/model/GTModelProperties.java index 24f641a3328..d5208bb5eee 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/GTModelProperties.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/GTModelProperties.java @@ -20,4 +20,6 @@ public class GTModelProperties { public static final ModelProperty PIPE_BLOCKED_MASK = new ModelProperty<>(); public static final ModelProperty CHILD_MODEL_DATA = new ModelProperty<>(Objects::nonNull); + + public static final ModelProperty PIPE_INSULATED = new ModelProperty<>(); } diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/BakedPipeModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/BakedPipeModel.java index d529223d327..cf6439f93ac 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/BakedPipeModel.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/BakedPipeModel.java @@ -10,6 +10,7 @@ import com.gregtechceu.gtceu.client.model.IBlockEntityRendererBakedModel; import com.gregtechceu.gtceu.client.renderer.cover.ICoverableRenderer; import com.gregtechceu.gtceu.client.util.GTQuadTransformers; +import com.gregtechceu.gtceu.common.blockentity.FluidPipeBlockEntity; import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; import com.gregtechceu.gtceu.utils.GTUtil; @@ -41,10 +42,13 @@ public class BakedPipeModel extends BaseBakedModel implements ICoverableRenderer private final Map parts; private final Map restrictors; + private final Map insulation; - public BakedPipeModel(Map parts, Map restrictors) { + public BakedPipeModel(Map parts, Map restrictors, + Map insulation) { this.parts = parts; this.restrictors = restrictors; + this.insulation = insulation; } @Override @@ -94,6 +98,12 @@ public List getQuads(@Nullable BlockState state, @Nullable Direction ICoverableRenderer.super.renderCovers(quads, pipeNode.getCoverContainer(), pos, level, side, rand, modelData, renderType); + // render insulation overlay if the pipe is insulated and insulation map is not empty + Boolean insulated = modelData.get(GTModelProperties.PIPE_INSULATED); + if (insulated != null && insulated && !insulation.isEmpty()) { + renderInsulationOverlay(quads, connectionMask, state, side, rand, modelData, renderType); + } + if (pipeNode.getFrameMaterial().isNull()) { return quads; } @@ -143,6 +153,10 @@ public ModelData getModelData(BlockAndTintGetter level, BlockPos pos, BlockState var builder = modelData.derive(); + if (level.getBlockEntity(pos) instanceof FluidPipeBlockEntity pipe) { + builder.with(GTModelProperties.PIPE_INSULATED, pipe.isInsulated()); + } + if (level.getBlockEntity(pos) instanceof IPipeNode pipeNode) { Map coverModelData = new EnumMap<>(Direction.class); for (Direction side : GTUtil.DIRECTIONS) { @@ -178,6 +192,25 @@ public ChunkRenderTypeSet getRenderTypes(BlockState state, RandomSource rand, Mo return ChunkRenderTypeSet.union(renderTypes, coverRenderTypes); } + private void renderInsulationOverlay(List quads, @Nullable Integer connectionMask, @Nullable BlockState state, + @Nullable Direction side, RandomSource rand, ModelData modelData, @Nullable RenderType renderType) { + BakedModel overlayCenter = insulation.get(null); + if (overlayCenter != null && (renderType == null || + (state != null && overlayCenter.getRenderTypes(state, rand, modelData).contains(renderType)))) { + quads.addAll(overlayCenter.getQuads(state, side, rand, modelData, renderType)); + } + if (connectionMask == null) return; + for (Direction dir : GTUtil.DIRECTIONS) { + if (PipeBlockEntity.isConnected(connectionMask, dir)) { + BakedModel overlayArm = insulation.get(dir); + if (overlayArm != null && (renderType == null || + (state != null && overlayArm.getRenderTypes(state, rand, modelData).contains(renderType)))) { + quads.addAll(overlayArm.getQuads(state, side, rand, modelData, renderType)); + } + } + } + } + @SuppressWarnings("deprecation") @Override public TextureAtlasSprite getParticleIcon() { @@ -192,4 +225,4 @@ public TextureAtlasSprite getParticleIcon() { @Override public void render(PipeBlockEntity blockEntity, float partialTick, PoseStack poseStack, MultiBufferSource buffer, int packedLight, int packedOverlay) {} -} +} \ No newline at end of file diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModel.java index 5f440b0214f..7c37d49923b 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModel.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModel.java @@ -123,6 +123,8 @@ public static void initDynamicModels() { public @Nullable ResourceLocation sideSecondary, endSecondary; @Setter public @Nullable ResourceLocation sideOverlay, endOverlay; + @Setter + public @Nullable ResourceLocation sideInsulation; /// Use {@link #getOrCreateBlockModel()} instead of referencing this field directly. private BlockModelBuilder blockModel; @@ -184,13 +186,16 @@ protected BlockModelBuilder getOrCreateBlockModel() { return this.blockModel; } // spotless:off - return this.blockModel = this.provider.models().getBuilder(this.blockId.toString()) - // make the "default" model be based on the center part's model + var loader = this.provider.models().getBuilder(this.blockId.toString()) .parent(this.getOrCreateCenterElement()) .customLoader(PipeModelBuilder.begin(this.thickness, this.provider)) .centerModels(this.getOrCreateCenterElement().getLocation()) - .connectionModels(this.getOrCreateConnectionElement().getLocation()) - .end(); + .connectionModels(this.getOrCreateConnectionElement().getLocation()); + if (this.sideInsulation != null) { + loader.insulationTextures(this.sideInsulation); + } + return this.blockModel = loader.end(); + // make the "default" model be based on the center part's model // spotless:on } @@ -408,12 +413,13 @@ public boolean equals(Object o) { Objects.equals(sideSecondary, pipeModel.sideSecondary) && Objects.equals(endSecondary, pipeModel.endSecondary) && Objects.equals(sideOverlay, pipeModel.sideOverlay) && - Objects.equals(endOverlay, pipeModel.endOverlay); + Objects.equals(endOverlay, pipeModel.endOverlay) && + Objects.equals(sideInsulation, pipeModel.sideInsulation); } @Override public int hashCode() { - return Objects.hash(block, side, end, sideSecondary, endSecondary, sideOverlay, endOverlay); + return Objects.hash(block, side, end, sideSecondary, endSecondary, sideOverlay, endOverlay, sideInsulation); } @FunctionalInterface diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModelLoader.java b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModelLoader.java index 9465b8f8471..66ab4bb0059 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModelLoader.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/PipeModelLoader.java @@ -56,7 +56,19 @@ public class PipeModelLoader implements IGeometryLoader { restrictors.put(direction, MachineModelLoader.GSON.fromJson(entry.getValue(), MultiVariantModel.class)); } } + // and the insulation + final Map insulation = new HashMap<>(); + if (json.has("insulation")) { + JsonObject variantsJson = GsonHelper.getAsJsonObject(json, "insulation"); + for (Map.Entry entry : variantsJson.entrySet()) { + Direction direction = Direction.byName(entry.getKey()); + if (direction == null && !CENTER_KEYS.contains(entry.getKey().toLowerCase(Locale.ROOT))) { + throw new JsonParseException("Invalid pipe model insulation specifier " + entry.getKey()); + } + insulation.put(direction, MachineModelLoader.GSON.fromJson(entry.getValue(), MultiVariantModel.class)); + } + } - return new UnbakedPipeModel(parts, restrictors); + return new UnbakedPipeModel(parts, restrictors, insulation); } } diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/UnbakedPipeModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/UnbakedPipeModel.java index 5ea5e68ac76..139c30681f2 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/pipe/UnbakedPipeModel.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/pipe/UnbakedPipeModel.java @@ -21,11 +21,14 @@ public class UnbakedPipeModel implements IUnbakedGeometry { private final Map<@Nullable Direction, UnbakedModel> parts; private final Map<@NotNull Direction, UnbakedModel> restrictors; + private final Map<@Nullable Direction, UnbakedModel> insulation; public UnbakedPipeModel(Map<@Nullable Direction, UnbakedModel> parts, - Map<@NotNull Direction, UnbakedModel> restrictors) { + Map<@NotNull Direction, UnbakedModel> restrictors, + Map<@Nullable Direction, UnbakedModel> insulation) { this.parts = parts; this.restrictors = restrictors; + this.insulation = insulation; } @Override @@ -40,7 +43,11 @@ public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, this.restrictors.forEach((direction, unbaked) -> { bakedRestrictors.put(direction, unbaked.bake(baker, spriteGetter, modelState, modelLocation)); }); - return new BakedPipeModel(bakedParts, bakedRestrictors); + Map bakedInsulation = new IdentityHashMap<>(); + this.insulation.forEach((direction, unbaked) -> { + bakedInsulation.put(direction, unbaked.bake(baker, spriteGetter, modelState, modelLocation)); + }); + return new BakedPipeModel(bakedParts, bakedRestrictors, bakedInsulation); } @Override @@ -67,5 +74,15 @@ public void resolveParents(Function resolver, IG this.restrictors.put(side, variant); } }); + copy = new IdentityHashMap<>(this.insulation); + copy.forEach((side, variant) -> { + if (variant == null || variant == MISSING_MARKER) { + // replace null & markers with the actual missing model + this.insulation.put(side, missingModel); + } else { + variant.resolveParents(resolver); + this.insulation.put(side, variant); + } + }); } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/block/FluidPipeBlock.java b/src/main/java/com/gregtechceu/gtceu/common/block/FluidPipeBlock.java index 1af49f770c2..58e769fe6ca 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/block/FluidPipeBlock.java +++ b/src/main/java/com/gregtechceu/gtceu/common/block/FluidPipeBlock.java @@ -114,6 +114,7 @@ public void appendHoverText(ItemStack stack, @Nullable BlockGetter level, List - implements IDataInfoProvider { + implements IDataInfoProvider { public static final int FREQUENCY = 5; @@ -71,6 +74,11 @@ public class FluidPipeBlockEntity extends PipeBlockEntity tankLists = new EnumMap<>(Direction.class); @SaveField(nbtKey = "Fluids") private CustomFluidTank[] fluidTanks; + @Getter + @SyncToClient + @RerenderOnChanged + @SaveField(nbtKey = "Insulated") + private boolean insulated = false; private long timer = 0L; private final int offset = GTValues.RNG.nextInt(20); @@ -90,6 +98,10 @@ public long getOffsetTimer() { @Override public void onLoad() { super.onLoad(); + if (!insulated && getNodeData().isInsulatedByDefault()) { + this.insulated = true; + setChanged(); + } if (updateSubs == null) { updateSubs = this.subscribeServerTick(this::update); } @@ -495,12 +507,20 @@ public static void setNeighboursToFire(Level world, BlockPos selfPos) { } } + public void setInsulated(boolean insulated) { + this.insulated = insulated; + syncDataHolder.markClientSyncFieldDirty("insulated"); + } + @Override public @NotNull List getDataInfo(PortableScannerBehavior.DisplayMode mode) { List list = new ArrayList<>(); if (mode == PortableScannerBehavior.DisplayMode.SHOW_ALL || mode == PortableScannerBehavior.DisplayMode.SHOW_MACHINE_INFO) { + if (insulated) { + list.add(Component.translatable("gtceu.fluid_pipe.insulated")); + } FluidStack[] fluids = getContainedFluids(); if (fluids != null) { boolean allTanksEmpty = true; diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java index 7cef69333c5..80d167c3144 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java @@ -2554,6 +2554,15 @@ public static ItemEntry createFluidCell(Material mat, int capacit .onRegister(attach(new ImageModuleBehaviour())) .register(); + public static ItemEntry INSULATION_WRAPPER = REGISTRATE.item("insulation_wrapper", ComponentItem::create) + .lang("Insulation Wrapper") + .onRegister(attach(new TooltipBehavior(lines -> { + lines.add(Component.translatable("item.gtceu.insulation_wrapper.desc")); + lines.add(Component.translatable("item.gtceu.insulation_wrapper.usage")); + }))) + .onRegister(attach(new InsulationWrapperBehaviour())) + .register(); + public static void init() { GTMaterialItems.generateMaterialItems(); GTMaterialItems.generateTools(); diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java index 432009190f2..8be11c12c10 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java @@ -958,7 +958,7 @@ public static void register() { .element(GTElements.Nq) .rotorStats(160, 105, 4.0f, 1280) .cableProperties(V[ZPM], 2, 2) - .fluidPipeProperties(3776, 200, true, false, true, true) + .fluidPipeProperties(3776, 200, true, false, true, true, true) .blast(b -> b.temp(5000, GasTier.HIGH) .blastStats(VA[IV], 600) .vacuumStats(VA[EV], 150)) @@ -996,7 +996,7 @@ public static void register() { .toolStats(ToolProperty.Builder.of(180.0F, 100.0F, 65535, 6) .attackSpeed(0.5F).enchantability(33).magnetic().unbreakable().build()) .rotorStats(400, 250, 12.0f, 655360) - .fluidPipeProperties(100_000, 5000, true, true, true, true) + .fluidPipeProperties(100_000, 5000, true, true, true, true, true) .radioactiveHazard(10) .buildAndRegister(); @@ -1019,7 +1019,7 @@ public static void register() { .element(GTElements.Dr) .toolStats(ToolProperty.Builder.of(14.0F, 12.0F, 8192, 5) .attackSpeed(0.3F).enchantability(33).magnetic().build()) - .fluidPipeProperties(9625, 500, true, true, true, true) + .fluidPipeProperties(9625, 500, true, true, true, true, true) .buildAndRegister(); Trinium = new Material.Builder(GTCEu.id("trinium")) diff --git a/src/main/java/com/gregtechceu/gtceu/common/item/behavior/InsulationWrapperBehaviour.java b/src/main/java/com/gregtechceu/gtceu/common/item/behavior/InsulationWrapperBehaviour.java new file mode 100644 index 00000000000..b6b7294fa81 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/item/behavior/InsulationWrapperBehaviour.java @@ -0,0 +1,84 @@ +package com.gregtechceu.gtceu.common.item.behavior; + +import com.gregtechceu.gtceu.api.item.component.IInteractionItem; +import com.gregtechceu.gtceu.api.pipenet.IPipeNode; +import com.gregtechceu.gtceu.utils.BreadthFirstBlockSearch; +import com.gregtechceu.gtceu.common.block.FluidPipeBlock; +import com.gregtechceu.gtceu.common.blockentity.FluidPipeBlockEntity; +import com.gregtechceu.gtceu.common.data.GTItems; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.context.UseOnContext; + +import java.util.ArrayList; +import java.util.List; + +public class InsulationWrapperBehaviour implements IInteractionItem { + + @Override + public InteractionResult useOn(UseOnContext context) { + var player = context.getPlayer(); + var level = context.getLevel(); + var pos = context.getClickedPos(); + + if (player == null || level.isClientSide || !player.isCrouching()) { + return InteractionResult.PASS; + } + + if (!(level.getBlockState(pos).getBlock() instanceof FluidPipeBlock)) { + player.displayClientMessage(Component.translatable("item.gtceu.insulation_wrapper.message.invalid_pipe"), true); + return InteractionResult.FAIL; + } + + if (!(level.getBlockEntity(pos) instanceof FluidPipeBlockEntity first)) return InteractionResult.FAIL; + + // count available wrappers in inventory + int available = player.isCreative() ? Integer.MAX_VALUE : player.getInventory().clearOrCountMatchingItems( + itemStack -> itemStack.getItem() == GTItems.INSULATION_WRAPPER.get(), + 0, player.inventoryMenu.getCraftSlots()); + + if (!player.isCreative() && available == 0) { + return InteractionResult.FAIL; + } + + // get all pipes in the network with amount of available wrappers as the limit, should function similar to spray cans + var collected = BreadthFirstBlockSearch.conditionalSearch(IPipeNode.class, first, level, IPipeNode::getBlockPos, + (parent, child, dir) -> parent == null || (parent.isConnected(dir) && child.isConnected(dir.getOpposite())), + available, Integer.MAX_VALUE); + + List toInsulate = new ArrayList<>(); + for (var node : collected) { + if (node instanceof FluidPipeBlockEntity pipe && !pipe.isInsulated()) { + toInsulate.add(pipe.getBlockPos()); + } + } + + if (toInsulate.isEmpty()) { + player.displayClientMessage(Component.translatable("item.gtceu.insulation_wrapper.message.already_insulated"), true); + return InteractionResult.FAIL; + } + + int needed = toInsulate.size(); + + // insulate all pipes + for (BlockPos blockPos : toInsulate) { + if (level.getBlockEntity(blockPos) instanceof FluidPipeBlockEntity pipe) { + pipe.setInsulated(true); + } + } + + // clear needed amount from inventory + if (!player.isCreative()){ + player.getInventory().clearOrCountMatchingItems( + itemStack -> itemStack.getItem() == GTItems.INSULATION_WRAPPER.get(), + needed, player.inventoryMenu.getCraftSlots()); + } + + // it always insulates pipes matching amount of available wrappers so partial insulation message is no longer possible + player.displayClientMessage(Component.translatable( + "item.gtceu.insulation_wrapper.message.success", needed), true); + return InteractionResult.SUCCESS; + } + +} \ No newline at end of file diff --git a/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeNet.java b/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeNet.java index 1bb6ddef095..614f24bd59c 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeNet.java +++ b/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeNet.java @@ -24,6 +24,7 @@ protected void writeNodeData(FluidPipeProperties nodeData, CompoundTag tagCompou tagCompound.putBoolean("acid_proof", nodeData.isAcidProof()); tagCompound.putBoolean("cryo_proof", nodeData.isCryoProof()); tagCompound.putBoolean("plasma_proof", nodeData.isPlasmaProof()); + tagCompound.putBoolean("insulated_by_default", nodeData.isInsulatedByDefault()); tagCompound.putInt("channels", nodeData.getChannels()); } @@ -35,8 +36,9 @@ protected FluidPipeProperties readNodeData(CompoundTag tagCompound) { boolean acidProof = tagCompound.getBoolean("acid_proof"); boolean cryoProof = tagCompound.getBoolean("cryo_proof"); boolean plasmaProof = tagCompound.getBoolean("plasma_proof"); + boolean insulatedByDefault = tagCompound.getBoolean("insulated_by_default"); int channels = tagCompound.getInt("channels"); - return new FluidPipeProperties(maxTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof, + return new FluidPipeProperties(maxTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof, insulatedByDefault, channels); } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeType.java b/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeType.java index f068dd69236..c8ba7f3116e 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeType.java +++ b/src/main/java/com/gregtechceu/gtceu/common/pipelike/fluidpipe/FluidPipeType.java @@ -61,6 +61,7 @@ public FluidPipeProperties modifyProperties(FluidPipeProperties fluidPipeData) { fluidPipeData.isAcidProof(), fluidPipeData.isCryoProof(), fluidPipeData.isPlasmaProof(), + fluidPipeData.isInsulatedByDefault(), channels); } @@ -88,6 +89,19 @@ public PipeModel createPipeModel(PipeBlock block, Material material, GT } else { side = side.formatted(""); } - return new PipeModel(block, provider, thickness, GTCEu.id(side), GTCEu.id(end)); + + // insulation overlays + String insulationSide; + if (channels == 9) { + insulationSide = "block/pipe/insulation/pipe_insulation_nonuple_side"; + } else if (channels == 4) { + insulationSide = "block/pipe/insulation/pipe_insulation_quadruple_side"; + } else { + insulationSide = "block/pipe/insulation/pipe_insulation_side"; + } + + PipeModel model = new PipeModel(block, provider, thickness, GTCEu.id(side), GTCEu.id(end)); + model.setSideInsulation(GTCEu.id(insulationSide)); + return model; } -} +} \ No newline at end of file diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/ItemLang.java b/src/main/java/com/gregtechceu/gtceu/data/lang/ItemLang.java index 9b47bcbb63f..f6c65d5aae6 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/lang/ItemLang.java +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/ItemLang.java @@ -236,6 +236,12 @@ private static void initItemTooltips(RegistrateLangProvider provider) { provider.add("item.gtceu.ram_chip.tooltip", "§7Random Access Memory"); provider.add("item.gtceu.soc.tooltip", "§7System on Chip"); provider.add("item.gtceu.simple_soc.tooltip", "§7Simple System on Chip"); + provider.add("item.gtceu.insulation_wrapper.message.already_insulated", "§eAll pipes in this network are already insulated"); + provider.add("item.gtceu.insulation_wrapper.message.invalid_pipe", "§eNot a fluid pipe"); + provider.add("item.gtceu.insulation_wrapper.message.success", "§aInsulated §f%s pipe(s)"); + provider.add("item.gtceu.insulation_wrapper.message.removed", "§cRemoved Insulation"); + provider.add("item.gtceu.insulation_wrapper.desc", "§bNullify damage from thermogenics/cryogenics"); + provider.add("item.gtceu.insulation_wrapper.usage", "Shift-Right-Click on fluid pipe network"); multilineLang(provider, "item.gtceu.basic_electronic_circuit.tooltip", "§7Your First Circuit\n§cLV-Tier Circuit"); multilineLang(provider, "item.gtceu.good_electronic_circuit.tooltip", diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java index 091a1564988..d894d29f076 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java @@ -1146,6 +1146,8 @@ public static void init(RegistrateLangProvider provider) { provider.add("gtceu.fluid_pipe.cryo_proof", "§6Can handle Cryogenics"); provider.add("gtceu.fluid_pipe.plasma_proof", "§6Can handle all Plasmas"); provider.add("gtceu.fluid_pipe.not_gas_proof", "§4Gases may leak!"); + provider.add("gtceu.fluid_pipe.insulated", "§bInsulated"); + provider.add("gtceu.fluid_pipe.insulated_by_default", "§6Pre-Insulated"); provider.add("gtceu.item_pipe.priority", "§9Priority: §f%d"); provider.add("gtceu.duct_pipe.transfer_rate", "§bAir transfer rate: %s"); provider.add("gtceu.multiblock.work_paused", "Work Paused."); @@ -1300,6 +1302,7 @@ public static void init(RegistrateLangProvider provider) { provider.add("config.jade.plugin_gtceu.me_pattern_buffer_proxy", "[GTCEu] Pattern Buffer Proxy Info"); provider.add("config.jade.plugin_gtceu.energy_converter_provider", "[GTCEu] Energy Converter Mode"); provider.add("config.jade.plugin_gtceu.ldp_endpoint", "[GTCEu] Long Distance Pipeline Endpoint Info"); + provider.add("config.jade.plugin_gtceu.fluid_pipe_info", "[GTCEu] Fluid Pipe Info"); // gui provider.add("gtceu.button.ore_veins", "Show GT Ore Veins"); diff --git a/src/main/java/com/gregtechceu/gtceu/data/model/builder/PipeModelBuilder.java b/src/main/java/com/gregtechceu/gtceu/data/model/builder/PipeModelBuilder.java index e9a72cf2c3a..9ed31c8c480 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/model/builder/PipeModelBuilder.java +++ b/src/main/java/com/gregtechceu/gtceu/data/model/builder/PipeModelBuilder.java @@ -51,6 +51,8 @@ public static > BiFunction> modelsForDirection(@Nullable ImmutableList.of()); } + public PipeModelBuilder insulationTextures(ResourceLocation side) { + this.insulationSideTexture = side; + return this; + } + @Override public T end() { this.restrictors = getOrCreateRestrictorModels(this.provider.models(), this.thickness); + if (this.insulationSideTexture != null) { + this.insulation = makeInsulationModels(this.provider.models(), this.thickness, this.insulationSideTexture); + } return super.end(); } @@ -319,6 +329,21 @@ public JsonObject toJson(JsonObject json) { json.add("restrictors", restrictors); } + // build json for insulation + if (this.insulation != null) { + final JsonObject insulation = new JsonObject(); + for (int i = 0; i < GTUtil.DIRECTIONS.length; i++) { + Direction dir = GTUtil.DIRECTIONS[i]; + insulation.add(dir.getName(), configuredModelToJSON(ConfiguredModel.builder() + .modelFile(new ModelFile.UncheckedModelFile(this.insulation[i].getLocation())) + .buildLast(), false)); + } + insulation.add(PipeModelLoader.PRIMARY_CENTER_KEY, configuredModelToJSON(ConfiguredModel.builder() + .modelFile(new ModelFile.UncheckedModelFile(this.insulation[GTUtil.DIRECTIONS.length].getLocation())) + .buildLast(), false)); + json.add("insulation", insulation); + } + return json; } @@ -331,6 +356,66 @@ private static BlockModelBuilder[] getOrCreateRestrictorModels(BlockModelProvide private static final MemoizedBiFunction RESTRICTOR_MODEL_CACHE = GTMemoizer .memoizeFunctionWeakIdent(PipeModelBuilder::makeRestrictorModels); + private static BlockModelBuilder[] makeInsulationModels(BlockModelProvider provider, float thickness, ResourceLocation sideTexture) { + BlockModelBuilder[] models = new BlockModelBuilder[GTUtil.DIRECTIONS.length + 1]; + + float min = (16.0f - thickness) / 2.0f - 0.003f; + float max = min + thickness + 0.006f; // offset by 0.003 * 2 + + String suffix = sideTexture.getPath().substring(sideTexture.getPath().lastIndexOf('/') + 1); + + for (Direction dir : GTUtil.DIRECTIONS) { + String modelPath = "block/pipe/insulation/" + suffix + "/" + dir.getName() + "/thickness_" + thickness; + ResourceLocation modelName = GTCEu.id(modelPath); + if (provider.generatedModels.containsKey(modelName)) { + models[dir.ordinal()] = provider.generatedModels.get(modelName); + continue; + } + + var coords = GTMath.getCoordinates(dir, min, max); + Vector3f minPos = coords.getLeft(); + Vector3f maxPos = coords.getRight(); + + BlockModelBuilder model = provider.getBuilder(modelPath); + model.texture("insulation_side", sideTexture) + .renderType(new ResourceLocation("translucent")) + .element() + .from(minPos.x, minPos.y, minPos.z) + .to(maxPos.x, maxPos.y, maxPos.z) + .face(getSideAtBorder(dir, Border.BOTTOM)).end() + .face(getSideAtBorder(dir, Border.TOP)).end() + .face(getSideAtBorder(dir, Border.LEFT)).end() + .face(getSideAtBorder(dir, Border.RIGHT)).end() + .faces((face, builder) -> builder.texture("#insulation_side")) + .end(); + models[dir.ordinal()] = model; + } + + // center overlay + String centerPath = "block/pipe/insulation/" + suffix + "/center/thickness_" + thickness; + ResourceLocation centerName = GTCEu.id(centerPath); + if (provider.generatedModels.containsKey(centerName)) { + models[GTUtil.DIRECTIONS.length] = provider.generatedModels.get(centerName); + } else { + BlockModelBuilder center = provider.getBuilder(centerPath); + center.texture("insulation_side", sideTexture) + .renderType(new ResourceLocation("translucent")) + .element() + .from(min, min, min) + .to(max, max, max) + .face(Direction.DOWN).end() + .face(Direction.UP).end() + .face(Direction.NORTH).end() + .face(Direction.SOUTH).end() + .face(Direction.WEST).end() + .face(Direction.EAST).end() + .faces((face, builder) -> builder.texture("#insulation_side")) + .end(); + models[GTUtil.DIRECTIONS.length] = center; + } + return models; + } + private static BlockModelBuilder[] makeRestrictorModels(BlockModelProvider provider, float thickness) { BlockModelBuilder[] models = new BlockModelBuilder[GTUtil.DIRECTIONS.length]; @@ -434,4 +519,4 @@ private enum Border { mask = 1 << this.ordinal(); } } -} +} \ No newline at end of file diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/AssemblerRecipeLoader.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/AssemblerRecipeLoader.java index 7c19fc75c65..5c736dd73fc 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/AssemblerRecipeLoader.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/AssemblerRecipeLoader.java @@ -271,5 +271,13 @@ public static void init(Consumer provider) { .inputItems(ring, PolyvinylChloride, 1) .outputItems(HAZMAT_HELMET) .save(provider); + + // insulation wrapper + ASSEMBLER_RECIPES.recipeBuilder("insulation_wrapper") + .inputItems(dust, Asbestos, 6) + .inputItems(Items.WHITE_WOOL, 2) + .inputItems(foil, Steel, 1) + .outputItems(INSULATION_WRAPPER) + .duration(80).EUt(VA[LV]).save(provider); } } diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java index 1d2936362ba..2d0b2a722b2 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java +++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java @@ -56,6 +56,10 @@ public static void init(Consumer provider) { VanillaRecipeHelper.addShapelessRecipe(provider, "programmed_circuit", PROGRAMMED_CIRCUIT.asStack(), CustomTags.LV_CIRCUITS); + // insulation wrapper + VanillaRecipeHelper.addShapedRecipe(provider, true, "insulation_wrapper", INSULATION_WRAPPER.asStack(), "DDD", "WFW", "DDD", + 'D', new MaterialEntry(dust, Asbestos), 'W', new ItemStack(Items.WHITE_WOOL), 'F', new MaterialEntry(foil, Steel)); + VanillaRecipeHelper.addShapedRecipe(provider, "item_filter", ITEM_FILTER.asStack(), "XXX", "XYX", "XXX", 'X', new MaterialEntry(foil, Zinc), 'Y', new MaterialEntry(plate, Steel)); VanillaRecipeHelper.addShapedRecipe(provider, "fluid_filter_lapis", FLUID_FILTER.asStack(), "XXX", "XYX", "XXX", diff --git a/src/main/java/com/gregtechceu/gtceu/integration/jade/GTJadePlugin.java b/src/main/java/com/gregtechceu/gtceu/integration/jade/GTJadePlugin.java index 425f02b6dbf..7a83bdd9016 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/jade/GTJadePlugin.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/jade/GTJadePlugin.java @@ -46,6 +46,7 @@ public void register(IWailaCommonRegistration registration) { registration.registerBlockDataProvider(new EnergyConverterModeProvider(), BlockEntity.class); registration.registerBlockDataProvider(new BatteryStorageInfoProvider(), BlockEntity.class); registration.registerBlockDataProvider(new LDPEndpointProvider(), BlockEntity.class); + registration.registerBlockDataProvider(new FluidPipeInfoProvider(), BlockEntity.class); if (GTCEu.Mods.isAE2Loaded()) { registration.registerBlockDataProvider(new MEPatternBufferProvider(), BlockEntity.class); registration.registerBlockDataProvider(new MEPatternBufferProxyProvider(), BlockEntity.class); @@ -79,6 +80,7 @@ public void registerClient(IWailaClientRegistration registration) { registration.registerBlockComponent(new LDPEndpointProvider(), Block.class); registration.registerBlockComponent(new EnergyConverterModeProvider(), Block.class); registration.registerBlockComponent(new BatteryStorageInfoProvider(), Block.class); + registration.registerBlockComponent(new FluidPipeInfoProvider(), Block.class); if (GTCEu.Mods.isAE2Loaded()) { registration.registerBlockComponent(new MEPatternBufferProvider(), Block.class); registration.registerBlockComponent(new MEPatternBufferProxyProvider(), Block.class); diff --git a/src/main/java/com/gregtechceu/gtceu/integration/jade/provider/FluidPipeInfoProvider.java b/src/main/java/com/gregtechceu/gtceu/integration/jade/provider/FluidPipeInfoProvider.java new file mode 100644 index 00000000000..3651fffdb73 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/jade/provider/FluidPipeInfoProvider.java @@ -0,0 +1,44 @@ +package com.gregtechceu.gtceu.integration.jade.provider; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.common.block.FluidPipeBlock; +import com.gregtechceu.gtceu.common.blockentity.FluidPipeBlockEntity; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.entity.BlockEntity; +import snownee.jade.api.BlockAccessor; +import snownee.jade.api.IBlockComponentProvider; +import snownee.jade.api.IServerDataProvider; +import snownee.jade.api.ITooltip; +import snownee.jade.api.config.IPluginConfig; + +public class FluidPipeInfoProvider implements IBlockComponentProvider, IServerDataProvider { + + @Override + public void appendTooltip(ITooltip tooltip, BlockAccessor blockAccessor, IPluginConfig config) { + BlockEntity be = blockAccessor.getBlockEntity(); + if (be != null) { + CompoundTag data = blockAccessor.getServerData().getCompound(getUid().toString()); + if (data.contains("insulated") && data.getBoolean("insulated")) { + tooltip.add(Component.translatable("gtceu.fluid_pipe.insulated")); + } + } + } + + @Override + public void appendServerData(CompoundTag compoundTag, BlockAccessor blockAccessor) { + CompoundTag data = compoundTag.getCompound(getUid().toString()); + if (blockAccessor.getBlock() instanceof FluidPipeBlock fluidPipeBlock) { + FluidPipeBlockEntity pipe = (FluidPipeBlockEntity) fluidPipeBlock.getPipeTile( + blockAccessor.getLevel(), blockAccessor.getPosition()); + if (pipe != null) { + data.putBoolean("insulated", pipe.isInsulated()); + } + } + compoundTag.put(getUid().toString(), data); + } + + @Override + public ResourceLocation getUid() {return GTCEu.id("fluid_pipe_info");} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/pipe/insulation/pipe_insulation_nonuple_side.png b/src/main/resources/assets/gtceu/textures/block/pipe/insulation/pipe_insulation_nonuple_side.png new file mode 100644 index 00000000000..f15aa2d5f72 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/pipe/insulation/pipe_insulation_nonuple_side.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/pipe/insulation/pipe_insulation_quadruple_side.png b/src/main/resources/assets/gtceu/textures/block/pipe/insulation/pipe_insulation_quadruple_side.png new file mode 100644 index 00000000000..0e8e35951b9 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/pipe/insulation/pipe_insulation_quadruple_side.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/pipe/insulation/pipe_insulation_side.png b/src/main/resources/assets/gtceu/textures/block/pipe/insulation/pipe_insulation_side.png new file mode 100644 index 00000000000..3056fa219c3 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/pipe/insulation/pipe_insulation_side.png differ diff --git a/src/main/resources/assets/gtceu/textures/item/insulation_wrapper.png b/src/main/resources/assets/gtceu/textures/item/insulation_wrapper.png new file mode 100644 index 00000000000..c9fc099e778 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/item/insulation_wrapper.png differ