diff --git a/docs/content/Modpacks/Changes/v8.0.0.md b/docs/content/Modpacks/Changes/v8.0.0.md index d9de4b0a49c..de588da8c65 100644 --- a/docs/content/Modpacks/Changes/v8.0.0.md +++ b/docs/content/Modpacks/Changes/v8.0.0.md @@ -125,6 +125,19 @@ A large number of machine feature interfaces have been removed, and have had the - `IFluidRendererMulti` - Use `MultiblockFluidRendererTrait` +## Connected texture reimplementation +The mod's connected texture logic has been reimplemented in GTM proper. +Texture packs, addons, and modpacks will have to change their texture metadata files for connected texures slightly. +A few regexes for fixing all the MCMeta files is follows, run them in order: + +1. Match: `"ldlib":([\s\{]*)"connection"(:\s".*?")(?:,\s.*)?` + Replace with: `"gtceu":$1"connection_texture"$2` +2. Match: `\s*\},\s*"shimmer":\s*\{(\s*"bloom":.*)` + Replace with: `,$1` +3. Match: `(\{\s*)"shimmer":(\s*\{\s*"bloom":.*)` + Replace with: `$1"gtceu":$2` + + ## Other Changes - `BlastingRecipeBuilder`, `CampfireRecipeBuilder`, `SmeltingRecipeBuilder` and `SmokingRecipeBuilder` have been merged into `SimpleCookingRecipeBuilder` diff --git a/docs/content/Modpacks/Other-Topics/Connected-Textures.md b/docs/content/Modpacks/Other-Topics/Connected-Textures.md new file mode 100644 index 00000000000..1b929e6aefe --- /dev/null +++ b/docs/content/Modpacks/Other-Topics/Connected-Textures.md @@ -0,0 +1,63 @@ +--- +title: Creating Connected Textures +--- + +**Connected textures** are, as the name would imply, textures that connect with neighboring blocks. + +The CTM renderer will draw the block faces by assembling 4 quadrants from the 5 available block textures. +The normal `texture.png` is the block's "unconnected" texture, and is used when CTM is disabled or the block +has nothing to connect to. +`texture.png` has the outside corner quadrants and `texture_ctm.png` contains the connections. +``` +┌─────────────────┐ ┌────────────────────────────────┐ +│ texture.png │ │ texture_ctm.png │ +│ ╔══════╤══════╗ │ │ ──────┼────── ║ ─────┼───── ║ │ +│ ║ │ ║ │ │ │ │ │║ │ ║ │ +│ ║ 4/4 │ 4/5 ║ │ │ │ 0/0 │ 0/1 │║ 0/2 │ 0/3 ║ │ +│ ╟──────┼──────╢ │ │ ┼──────┼──────┼╟──────┼──────╢ │ +│ ║ │ ║ │ │ │ │ │║ │ ║ │ +│ ║ 5/4 │ 5/5 ║ │ │ │ 1/0 │ 1/1 │║ 1/2 │ 1/3 ║ │ +│ ╚══════╧══════╝ │ │ ──────┼────── ║ ─────┼───── ║ │ +└─────────────────┘ │ ═══════╤═══════╝ ─────┼───── ╚ │ + │ │ │ ││ │ │ │ + │ │ 2/0 │ 2/1 ││ 2/2 │ 2/3 │ │ + │ ┼──────┼──────┼┼──────┼──────┼ │ + │ │ │ ││ │ │ │ + │ │ 3/0 │ 3/1 ││ 3/2 │ 3/3 │ │ + │ ═══════╧═══════╗ ─────┼───── ╔ │ + └────────────────────────────────┘ +``` + +For example, combining sections 4/4, 2/1, 5/4, and 3/1, we can generate a texture connected to the right! +``` +╔══════╤═══════ +║ │ │ +║ 4/4 │ 2/1 │ +╟──────┼──────┼ +║ │ │ +║ 5/4 │ 3/1 │ +╚══════╧═══════ +``` +Combining sections 0/2, 2/3, 5/4, and 3/1, we can generate a texture in the shape of an L (connected to the right and up): +``` +║ ─────┼───── ╚ +║ │ │ +║ 0/2 │ 2/3 │ +╟──────┼──────┼ +║ │ │ +║ 5/4 │ 3/1 │ +╚══════╧═══════ +``` + + +??? example "Example MCMeta file" + (For a texture `mypack/assets/textures/blocks/texture.png` with a ctm texture `mypack/assets/textures/blocks/texture_ctm.png`) + ```json title="mypack:blocks/texture.png.mcmeta" + { + "gtceu": { + "connection_texture": "mypack:blocks/texture_ctm" + } + } + ``` + The CTM texture layout is [here](https://github.com/GregTechCEu/GregTech-Modern/blob/1.20.1/src/main/resources/assets/gtceu/textures/block/ctm_test.png) for the unconnected texture and [here](https://github.com/GregTechCEu/GregTech-Modern/blob/1.20.1/src/main/resources/assets/gtceu/textures/block/ctm_test_ctm.png) for its connections. + Its MCMeta metadata file is [this one](https://github.com/GregTechCEu/GregTech-Modern/blob/1.20.1/src/main/resources/assets/gtceu/textures/block/ctm_test.png.mcmeta). diff --git a/src/generated/resources/assets/gtceu/blockstates/ctm_test.json b/src/generated/resources/assets/gtceu/blockstates/ctm_test.json new file mode 100644 index 00000000000..9332a79dea2 --- /dev/null +++ b/src/generated/resources/assets/gtceu/blockstates/ctm_test.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "gtceu:block/ctm_test" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/lang/en_ud.json b/src/generated/resources/assets/gtceu/lang/en_ud.json index 0d9e0086a6a..7ec43a2631d 100644 --- a/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -187,6 +187,7 @@ "block.gtceu.creative_tank": "ʞuɐ⟘ ǝʌıʇɐǝɹƆ", "block.gtceu.creosote": "ǝʇosoǝɹƆ", "block.gtceu.crushing_wheels": "sןǝǝɥM buıɥsnɹƆ", + "block.gtceu.ctm_test": "ʞɔoןᗺ ʇsǝ⟘ ǝɹnʇxǝ⟘ pǝʇɔǝuuoƆ", "block.gtceu.cupronickel_coil_block": "ʞɔoןᗺ ןıoƆ ןǝʞɔıuoɹdnƆ", "block.gtceu.cyan_borderless_lamp": "dɯɐꞀ ssǝןɹǝpɹoᗺ uɐʎƆ", "block.gtceu.cyan_lamp": "dɯɐꞀ uɐʎƆ", diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index 67ddba4f02e..3152522f4dd 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -187,6 +187,7 @@ "block.gtceu.creative_tank": "Creative Tank", "block.gtceu.creosote": "Creosote", "block.gtceu.crushing_wheels": "Crushing Wheels", + "block.gtceu.ctm_test": "Connected Texture Test Block", "block.gtceu.cupronickel_coil_block": "Cupronickel Coil Block", "block.gtceu.cyan_borderless_lamp": "Cyan Borderless Lamp", "block.gtceu.cyan_lamp": "Cyan Lamp", diff --git a/src/generated/resources/assets/gtceu/models/block/ctm_test.json b/src/generated/resources/assets/gtceu/models/block/ctm_test.json new file mode 100644 index 00000000000..47bfa0945dd --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/block/ctm_test.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "gtceu:block/ctm_test" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/ctm_test.json b/src/generated/resources/assets/gtceu/models/item/ctm_test.json new file mode 100644 index 00000000000..1dec31234c8 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/ctm_test.json @@ -0,0 +1,3 @@ +{ + "parent": "gtceu:block/ctm_test" +} \ No newline at end of file diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java index 7a011bb3c71..d809950b750 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java +++ b/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java @@ -38,7 +38,7 @@ import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable; import com.gregtechceu.gtceu.client.model.IBlockEntityRendererBakedModel; import com.gregtechceu.gtceu.client.model.machine.MachineRenderState; -import com.gregtechceu.gtceu.client.util.ModelUtils; +import com.gregtechceu.gtceu.client.util.RenderUtil; import com.gregtechceu.gtceu.common.cover.FluidFilterCover; import com.gregtechceu.gtceu.common.cover.ItemFilterCover; import com.gregtechceu.gtceu.common.cover.data.ManualIOMode; @@ -46,6 +46,7 @@ import com.gregtechceu.gtceu.common.machine.owner.PlayerOwner; import com.gregtechceu.gtceu.common.machine.trait.AutoOutputTrait; import com.gregtechceu.gtceu.utils.ExtendedUseOnContext; +import com.gregtechceu.gtceu.utils.GTStringUtils; import com.gregtechceu.gtceu.utils.data.TagCompatibilityFixer; import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; @@ -53,8 +54,6 @@ import com.lowdragmc.lowdraglib.utils.DummyWorld; import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.block.BlockRenderDispatcher; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -661,7 +660,7 @@ public void addDebugOverlayText(Consumer lines) { // add render state info MachineRenderState renderState = this.getRenderState(); for (var property : renderState.getValues().entrySet()) { - lines.accept(ModelUtils.getPropertyValueString(property)); + lines.accept(GTStringUtils.getPropertyValueString(property)); } } @@ -1011,8 +1010,7 @@ public int getDefaultPaintingColor() { @OnlyIn(Dist.CLIENT) @Override public AABB getRenderBoundingBox() { - BlockRenderDispatcher blockRenderDispatcher = Minecraft.getInstance().getBlockRenderer(); - BakedModel model = blockRenderDispatcher.getBlockModel(this.getBlockState()); + BakedModel model = RenderUtil.getModelForState(this.getBlockState()); if (model instanceof IBlockEntityRendererBakedModel modelWithBER) { if (modelWithBER.getBlockEntityType() == this.getType()) { diff --git a/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java b/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java index 668e0c8388f..59778491561 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java +++ b/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java @@ -30,6 +30,7 @@ import com.gregtechceu.gtceu.client.renderer.machine.DynamicRenderManager; import com.gregtechceu.gtceu.client.renderer.machine.impl.*; import com.gregtechceu.gtceu.client.renderer.machine.impl.BoilerMultiPartRender; +import com.gregtechceu.gtceu.client.util.ModelEventHelper; import com.gregtechceu.gtceu.common.CommonEventListener; import com.gregtechceu.gtceu.common.CommonProxy; import com.gregtechceu.gtceu.common.data.GTBlockEntities; @@ -72,6 +73,8 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; +import java.util.*; + public class ClientProxy extends CommonProxy { public static final BiMap CLIENT_ORE_VEINS = HashBiMap.create(); @@ -91,6 +94,7 @@ public static void init() { CommonEventListener.registerCapes(new RegisterGTCapesEvent()); } initializeDynamicRenders(); + ModelEventHelper.initInternalAssetReloadListeners(); } @SubscribeEvent @@ -158,7 +162,7 @@ public void onClientSetup(FMLClientSetupEvent event) { } } - public static void initializeDynamicRenders() { + private static void initializeDynamicRenders() { DynamicRenderManager.register(GTCEu.id("quantum_tank_fluid"), QuantumTankFluidRender.TYPE); DynamicRenderManager.register(GTCEu.id("quantum_chest_item"), QuantumChestItemRender.TYPE); 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..c33392c683c 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/GTModelProperties.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/GTModelProperties.java @@ -13,6 +13,7 @@ public class GTModelProperties { public static final ModelProperty LEVEL = new ModelProperty<>(); public static final ModelProperty POS = new ModelProperty<>(); + public static final ModelProperty PARENT_MODEL_DATA = new ModelProperty<>(); public static final ModelProperty> COVER_MODEL_DATA = new ModelProperty<>(); diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/TextureOverrideModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/TextureOverrideModel.java index 652d19bbba8..d554b30c13f 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/TextureOverrideModel.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/TextureOverrideModel.java @@ -1,6 +1,6 @@ package com.gregtechceu.gtceu.client.model; -import com.gregtechceu.gtceu.client.util.GTQuadTransformers; +import com.gregtechceu.gtceu.client.util.quad.transformers.GTQuadTransformers; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; @@ -14,7 +14,6 @@ import net.minecraftforge.client.model.data.ModelData; import lombok.Getter; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -23,7 +22,6 @@ public class TextureOverrideModel extends BakedModelWrappe public static final IQuadTransformer OVERLAY_OFFSET = GTQuadTransformers.offset(0.002f); - @NotNull @Getter protected final Map textureOverrides; @@ -37,10 +35,9 @@ public BakedModel getChild() { } @Override - public @NotNull List getQuads(@Nullable BlockState state, @Nullable Direction side, - @NotNull RandomSource rand, @NotNull ModelData extraData, - @Nullable RenderType renderType) { - return retextureQuads(super.getQuads(state, side, rand, extraData, renderType), textureOverrides); + public List getQuads(@Nullable BlockState state, @Nullable Direction side, + RandomSource rand, ModelData modelData, @Nullable RenderType renderType) { + return retextureQuads(super.getQuads(state, side, rand, modelData, renderType), textureOverrides); } public static List retextureQuads(List quads, Map overrides) { diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/ctm/CTMBakedModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/CTMBakedModel.java new file mode 100644 index 00000000000..9cf0d70302a --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/CTMBakedModel.java @@ -0,0 +1,59 @@ +package com.gregtechceu.gtceu.client.model.ctm; + +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.BakedModelWrapper; +import net.minecraftforge.client.model.data.ModelData; + +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +import static com.gregtechceu.gtceu.client.model.GTModelProperties.*; + +public class CTMBakedModel extends BakedModelWrapper { + + public CTMBakedModel(T parent) { + super(parent); + } + + public BakedModel getParent() { + return this.originalModel; + } + + @SuppressWarnings("DataFlowIssue") + @Override + public List getQuads(@Nullable BlockState state, @Nullable Direction side, + RandomSource rand, ModelData data, @Nullable RenderType renderType) { + ModelData parentModelData = data.has(PARENT_MODEL_DATA) ? data.get(PARENT_MODEL_DATA) : data; + if (state == null || side == null) { + return super.getQuads(state, side, rand, parentModelData, renderType); + } + BlockAndTintGetter level = data.get(LEVEL); + BlockPos pos = data.get(POS); + if (level == null || pos == null) { + return super.getQuads(state, side, rand, parentModelData, renderType); + } + + TextureConnections connections = TextureConnections.getInstance(); + connections.fillSubmapCache(level, pos, state, side); + return CTMMeshBuilder.buildCTMQuads(connections, super.getQuads(state, side, rand, parentModelData, renderType), + side); + } + + @Override + public ModelData getModelData(BlockAndTintGetter level, BlockPos pos, BlockState state, ModelData modelData) { + ModelData parentModelData = super.getModelData(level, pos, state, modelData); + return ModelData.builder() + .with(LEVEL, level) + .with(POS, pos) + .with(PARENT_MODEL_DATA, parentModelData) + .build(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/ctm/CTMMeshBuilder.java b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/CTMMeshBuilder.java new file mode 100644 index 00000000000..cf0f19c3656 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/CTMMeshBuilder.java @@ -0,0 +1,240 @@ +package com.gregtechceu.gtceu.client.model.ctm; + +import com.gregtechceu.gtceu.client.model.quad.MeshBuilder; +import com.gregtechceu.gtceu.client.model.quad.MutableQuadView; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +import org.joml.Vector2f; +import org.joml.Vector3f; + +import java.util.LinkedList; +import java.util.List; + +import static com.gregtechceu.gtceu.client.model.quad.MutableQuadView.*; +import static com.gregtechceu.gtceu.client.util.ModelEventHelper.*; + +public class CTMMeshBuilder { + + public static List buildCTMQuads(BlockAndTintGetter level, BlockPos pos, BlockState state, + List quads, Direction cullFace) { + TextureConnections connections = TextureConnections.getInstance(); + connections.fillSubmapCache(level, pos, state, cullFace); + + return buildCTMQuads(connections, quads, cullFace); + } + + public static List buildCTMQuads(TextureConnections connections, List base, + Direction cullFace) { + List result = new LinkedList<>(); + MeshBuilder meshBuilder = MeshBuilder.getInstance(); + var emitter = meshBuilder.getEmitter(); + + for (BakedQuad originalQuad : base) { + TextureAtlasSprite originalSprite = originalQuad.getSprite(); + + TextureAtlasSprite connectionSprite = CTM_SPRITE_CACHE.get(originalSprite.contents().name()); + if (connectionSprite == null) { + result.add(originalQuad); + continue; + } + + for (int xQuadrant = 0; xQuadrant < 2; xQuadrant++) { + for (int yQuadrant = 0; yQuadrant < 2; yQuadrant++) { + boolean defaultTexture = connections.isDefaultTexture(xQuadrant, yQuadrant); + TextureAtlasSprite ctmSprite = defaultTexture ? originalSprite : connectionSprite; + + emitter.fromVanilla(originalQuad, cullFace); + emitter.spriteUnbake(originalSprite, BAKE_NORMALIZED | BAKE_DEROTATE_UV); + + // slice quad into the current quadrant + subsect(emitter, Submap.X2[xQuadrant][yQuadrant]); + remapUVs(emitter, connections.getSubmapFor(xQuadrant, yQuadrant)); + + emitter.spriteBake(ctmSprite, BAKE_NORMALIZED); + + emitter.computeGeometry(); + emitter.populateMissingNormals(); + + result.add(emitter.toBakedQuad(ctmSprite)); + emitter.emit(); + } + } + } + return result; + } + + // these are only used within the below methods, but are stored here as consts to reduce allocations + // because they can be reused infinitely. DO NOT USE OUTSIDE subsect()/transformUVs()!! + + // filled in first copyUv() calls + private static final ThreadLocal uvs = ThreadLocal.withInitial(() -> new Vector2f[4]); + private static final ThreadLocal uvExtremes = ThreadLocal.withInitial(() -> { + return new Vector2f[] { new Vector2f(), new Vector2f() }; + }); + // set in copyPos() calls + private static final ThreadLocal position = ThreadLocal.withInitial(Vector3f::new); + private static final ThreadLocal xy = ThreadLocal.withInitial(() -> { + return new Vector2f[] { new Vector2f(), new Vector2f(), new Vector2f(), new Vector2f() }; + }); + private static final ThreadLocal newXy = ThreadLocal.withInitial(() -> { + return new Vector2f[] { new Vector2f(), new Vector2f(), new Vector2f(), new Vector2f() }; + }); + + private static void remapUVs(MutableQuadView quad, ISubmap submap) { + submap = submap.unitScale(); + + Vector2f maxUV = CTMMeshBuilder.uvExtremes.get()[0]; + maxUV.set(Float.MIN_VALUE, Float.MIN_VALUE); + + // cache UVs + Vector2f[] uvs = CTMMeshBuilder.uvs.get(); + for (int i = 0; i < 4; i++) { + uvs[i] = quad.copyUv(i, uvs[i]); + maxUV.max(uvs[i]); + } + // scale the quadrants' UVs to the quadrant's area + scaleUVCoordinatesToQuadrant(uvs, maxUV); + + // recompute min & max UVs + Vector2f[] uvExtremes = getUVExtremes(uvs); + Vector2f minUV = uvExtremes[0]; + maxUV = uvExtremes[1]; + + float width = maxUV.x - minUV.x; + float height = maxUV.y - minUV.y; + + float minU = submap.getXOffset(); + float minV = submap.getYOffset(); + minU += minUV.x * submap.getWidth(); + minV += minUV.y * submap.getHeight(); + + float maxU = minU + (width * submap.getWidth()); + float maxV = minV + (height * submap.getHeight()); + + quad.uv(0, uvs[0].x <= minUV.x ? minU : maxU, uvs[0].y <= minUV.y ? minV : maxV); + quad.uv(1, uvs[1].x <= minUV.x ? minU : maxU, uvs[1].y <= minUV.y ? minV : maxV); + quad.uv(2, uvs[2].x <= minUV.x ? minU : maxU, uvs[2].y <= minUV.y ? minV : maxV); + quad.uv(3, uvs[3].x <= minUV.x ? minU : maxU, uvs[3].y <= minUV.y ? minV : maxV); + } + + // TODO simplify, this is quite long + public static MutableQuadView subsect(final MutableQuadView quad, ISubmap submap) { + Direction normal = quad.nominalFace(); + // nominalFace should never be null here; MutableQuadView.fromVanilla updates it + assert normal != null; + + Vector2f[] xy = CTMMeshBuilder.xy.get(); + Vector2f[] newXy = CTMMeshBuilder.newXy.get(); + Vector3f position = CTMMeshBuilder.position.get(); + for (int i = 0; i < 4; i++) { + // updates position + quad.copyPos(i, position); + + switch (normal.getAxis()) { + case X -> xy[i].set(position.z, position.y); + case Y -> xy[i].set(position.x, position.z); + case Z -> xy[i].set(position.x, position.y); + } + } + + if (normal != Direction.UP) { + submap = submap.flipY(); + } + if (normal == Direction.EAST || normal == Direction.NORTH) { + submap = submap.flipX(); + } + + submap = submap.unitScale(); + + if (normal.getAxis() == Direction.Axis.Y || normal == Direction.SOUTH || normal == Direction.WEST) { + // Relative X is the same sign for DOWN, UP, SOUTH, and WEST + newXy[0].x = Math.max(xy[0].x, submap.getXOffset()); // DUSW + newXy[1].x = Math.max(xy[1].x, submap.getXOffset()); // DUSW + newXy[2].x = Math.min(xy[2].x, submap.getXOffset() + submap.getWidth()); // DUSW + newXy[3].x = Math.min(xy[3].x, submap.getXOffset() + submap.getWidth()); // DUSW + } else { + // Flip relative X for NORTH and EAST + newXy[0].x = Math.min(xy[0].x, submap.getXOffset() + submap.getWidth()); // NE + newXy[1].x = Math.min(xy[1].x, submap.getXOffset() + submap.getWidth()); // NE + newXy[2].x = Math.max(xy[2].x, submap.getXOffset()); // NE + newXy[3].x = Math.max(xy[3].x, submap.getXOffset()); // NE + } + if (normal != Direction.UP) { + // Relative Y is the same sign for all but UP + newXy[0].y = Math.min(xy[0].y, submap.getYOffset() + submap.getHeight()); // DNSWE + newXy[1].y = Math.max(xy[1].y, submap.getYOffset()); // DNSWE + newXy[2].y = Math.max(xy[2].y, submap.getYOffset()); // DNSWE + newXy[3].y = Math.min(xy[3].y, submap.getYOffset() + submap.getHeight()); // DNSWE + } else { + // Flip relative Y for UP + newXy[0].y = Math.max(xy[0].y, submap.getYOffset()); // U + newXy[1].y = Math.min(xy[1].y, submap.getYOffset() + submap.getHeight()); // U + newXy[2].y = Math.min(xy[2].y, submap.getYOffset() + submap.getHeight()); // U + newXy[3].y = Math.max(xy[3].y, submap.getYOffset()); // U + } + + float u0 = normalize(newXy[0].x, xy[0].x, xy[3].x), + v0 = normalize(newXy[0].y, xy[0].y, xy[1].y); + float u1 = normalize(newXy[1].x, xy[1].x, xy[2].x), + v1 = normalize(newXy[1].y, xy[1].y, xy[0].y); + float u2 = normalize(newXy[2].x, xy[2].x, xy[1].x), + v2 = normalize(newXy[2].y, xy[2].y, xy[3].y); + float u3 = normalize(newXy[3].x, xy[3].x, xy[0].x), + v3 = normalize(newXy[3].y, xy[3].y, xy[2].y); + + quad.uv(0, Mth.lerp(u0, quad.u(0), quad.u(3)), Mth.lerp(v0, quad.v(0), quad.v(1))); + quad.uv(1, Mth.lerp(u1, quad.u(1), quad.u(2)), Mth.lerp(v1, quad.v(1), quad.v(0))); + quad.uv(2, Mth.lerp(u2, quad.u(2), quad.u(1)), Mth.lerp(v2, quad.v(2), quad.v(3))); + quad.uv(3, Mth.lerp(u3, quad.u(3), quad.u(0)), Mth.lerp(v3, quad.v(3), quad.v(2))); + + // spotless:off + for (int i = 0; i < 4; i++) { + switch (normal.getAxis()) { + case X -> quad.pos(i, quad.x(i), newXy[i].y, newXy[i].x); + case Y -> quad.pos(i, newXy[i].x, quad.y(i), newXy[i].y); + case Z -> quad.pos(i, newXy[i].x, newXy[i].y, quad.z(i)); + } + } + // spotless:on + + return quad; + } + + public static Vector2f[] getUVExtremes(Vector2f[] uvs) { + Vector2f[] uvExtremes = CTMMeshBuilder.uvExtremes.get(); + uvExtremes[0].set(Float.MAX_VALUE, Float.MAX_VALUE); + uvExtremes[1].set(Float.MIN_VALUE, Float.MIN_VALUE); + + for (int i = 0; i < 4; i++) { + Vector2f vertexUV = uvs[i]; + uvExtremes[0].min(vertexUV); + uvExtremes[1].max(vertexUV); + } + return uvExtremes; + } + + private static void scaleUVCoordinatesToQuadrant(Vector2f[] uvs, Vector2f maxUV) { + float minU = maxUV.x() - 0.5f > Mth.EPSILON ? 0.5f : 0.0f, + minV = maxUV.y() - 0.5f > Mth.EPSILON ? 0.5f : 0.0f; + float maxU = maxUV.x() - 0.5f > Mth.EPSILON ? 1.0f : 0.5f, + maxV = maxUV.y() - 0.5f > Mth.EPSILON ? 1.0f : 0.5f; + + for (int i = 0; i < 4; i++) { + // scale u,v to a 0-1 range + uvs[i].set(normalize(uvs[i].x, minU, maxU), normalize(uvs[i].y, minV, maxV)); + } + } + + /// scale {@code delta} to a 0-1 range based on {@code min} and {@code max} + public static float normalize(float delta, float min, float max) { + if (min == max) return 0.5f; + return Mth.clamp(Mth.inverseLerp(delta, min, max), 0.0f, 1.0f); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/ctm/ConnectionCheck.java b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/ConnectionCheck.java new file mode 100644 index 00000000000..33724843038 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/ConnectionCheck.java @@ -0,0 +1,86 @@ +/* + * This file is part of ConnectedTexturesMod (https://github.com/Chisel-Team/ConnectedTexturesMod). + * Copyright (c) 2023 Chisel Team. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * ConnectedTexturesMod 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 ConnectedTexturesMod; if not, If not, see . + */ +package com.gregtechceu.gtceu.client.model.ctm; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.Nullable; + +/** + * Sourced from ConnectedTexturesMod + * with considerable simplification. + */ +@UtilityClass +public class ConnectionCheck { + + /** + * A simple check for if the given block can connect to the given direction on the given side. + * + * @param level The level the positions are in. + * @param current The position of your block. + * @param currentState The current state of your block. + * @param connection The position of the block to check against. + * @param dir The {@link Direction side} of the block to check for connection status. + * This is not the direction to check in. + * @return True if the given block can connect to the given location on the given side. + */ + public static boolean isConnected(BlockAndTintGetter level, BlockPos current, BlockState currentState, + BlockPos connection, Direction dir) { + BlockState state = getConnectionState(level, current, currentState, + dir, connection, level.getBlockState(connection)); + return isConnected(level, current, currentState, connection, dir, state); + } + + /** + * A simple check for if the given block can connect to the given direction on the given side. + * + * @param level The level the positions are in. + * @param current The position of your block. + * @param connection The position of the block to check against. + * @param dir The {@link Direction side} of the block to check for connection status. + * This is not the direction to check in. + * @param state The state to check against for connection. + * @return True if the given block can connect to the given location on the given side. + */ + public static boolean isConnected(BlockAndTintGetter level, BlockPos current, BlockState currentState, + BlockPos connection, + Direction dir, BlockState state) { + BlockState connectionState = getConnectionState(level, connection, level.getBlockState(connection), dir, + current, currentState); + BlockPos obscuringPos = connection.relative(dir); + BlockState obscuring = getConnectionState(level, obscuringPos, level.getBlockState(obscuringPos), + dir, current, currentState); + + // check that we are connected AND aren't already connected outwards from this side + return state == connectionState && state != obscuring; + } + + public static BlockState getConnectionState(BlockAndTintGetter level, BlockPos pos, BlockState state, + @Nullable Direction side, BlockPos connection, + BlockState connectionState) { + if (side != null) { + return state.getAppearance(level, pos, side, connectionState, connection); + } + return state; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/ctm/GTTextureMetadata.java b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/GTTextureMetadata.java new file mode 100644 index 00000000000..03922701d1c --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/GTTextureMetadata.java @@ -0,0 +1,64 @@ +package com.gregtechceu.gtceu.client.model.ctm; + +import com.gregtechceu.gtceu.GTCEu; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.metadata.MetadataSectionSerializer; +import net.minecraft.server.packs.resources.Resource; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.JsonOps; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import lombok.SneakyThrows; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.util.Optional; +import java.util.function.Function; + +public record GTTextureMetadata(@Nullable ResourceLocation connectionTexture) { + + public static final String SECTION_NAME = GTCEu.MOD_ID; + public static final MetadataSectionSerializer SERIALIZER = new Serializer(); + + /** + * @apiNote This method throws {@link IOException} even though it isn't specified in the method definition. + */ + @SneakyThrows(IOException.class) + public static Optional getForResourceUnsafe(Resource resource) { + return resource.metadata().getSection(SERIALIZER); + } + + public GTTextureMetadata { + // Optional codec fields can't have null as the default value, so we do this instead. + // It's impossible to define an entirely empty ResourceLocation in a resource file, + // as even ":" is converted to "minecraft:". Thus, this should be entirely safe. + if (connectionTexture == Serializer.EMPTY_CONNECTION) connectionTexture = null; + } + + public static class Serializer implements MetadataSectionSerializer { + + protected static final ResourceLocation EMPTY_CONNECTION = new ResourceLocation("", ""); + + // spotless:off + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + ResourceLocation.CODEC.optionalFieldOf("connection_texture", EMPTY_CONNECTION).forGetter(GTTextureMetadata::connectionTexture) + ).apply(instance, GTTextureMetadata::new)); + // spotless:on + + @Override + public GTTextureMetadata fromJson(@Nullable JsonObject json) throws JsonParseException { + return CODEC.parse(JsonOps.INSTANCE, json).get() + .map(Function.identity(), r -> { + throw new JsonParseException(r.message()); + }); + } + + @Override + public String getMetadataSectionName() { + return SECTION_NAME; + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/ctm/ISubmap.java b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/ISubmap.java new file mode 100644 index 00000000000..bfea41eb64a --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/ISubmap.java @@ -0,0 +1,123 @@ +/* + * This file is part of ConnectedTexturesMod (https://github.com/Chisel-Team/ConnectedTexturesMod). + * Copyright (c) 2023 Chisel Team. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * ConnectedTexturesMod 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 ConnectedTexturesMod; if not, If not, see . + */ +package com.gregtechceu.gtceu.client.model.ctm; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; + +import lombok.RequiredArgsConstructor; + +/** + * Sourced from ConnectedTexturesMod. + */ +public interface ISubmap { + + float getYOffset(); + + float getXOffset(); + + float getWidth(); + + float getHeight(); + + default float getInterpolatedU(TextureAtlasSprite sprite, float u) { + return sprite.getU((getXOffset() + u / getWidth()) / 16F); + } + + default float getInterpolatedV(TextureAtlasSprite sprite, float v) { + return sprite.getV((getYOffset() + v / getHeight()) / 16F); + } + + default float[] toArray() { + return new float[] { getXOffset(), getYOffset(), getXOffset() + getWidth(), getYOffset() + getHeight() }; + } + + default ISubmap unitScale() { + return new SubmapRescaled(this, UNITS_PER_PIXEL, false); + } + + default ISubmap pixelScale() { + return this; + } + + float PIXELS_PER_UNIT = 16f; + float UNITS_PER_PIXEL = 1f / PIXELS_PER_UNIT; + + @RequiredArgsConstructor + class SubmapRescaled implements ISubmap { + + private final ISubmap parent; + private final float ratio; + private final boolean isPixelScale; + + @Override + public float getXOffset() { + return parent.getXOffset() * ratio; + } + + @Override + public float getYOffset() { + return parent.getYOffset() * ratio; + } + + @Override + public float getWidth() { + return parent.getWidth() * ratio; + } + + @Override + public float getHeight() { + return parent.getHeight() * ratio; + } + + @Override + public ISubmap pixelScale() { + return isPixelScale ? this : parent; + } + + @Override + public ISubmap unitScale() { + return isPixelScale ? parent : this; + } + + @Override + public float getInterpolatedU(TextureAtlasSprite sprite, float u) { + return parent.getInterpolatedU(sprite, u); + } + + @Override + public float getInterpolatedV(TextureAtlasSprite sprite, float v) { + return parent.getInterpolatedV(sprite, v); + } + + @Override + public float[] toArray() { + return parent.toArray(); + } + } + + default ISubmap flipX() { + return Submap.fromPixelScale(getWidth(), getHeight(), PIXELS_PER_UNIT - getXOffset() - getWidth(), + getYOffset()); + } + + default ISubmap flipY() { + return Submap.fromPixelScale(getWidth(), getHeight(), getXOffset(), + PIXELS_PER_UNIT - getYOffset() - getHeight()); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/ctm/OctagonalOrientation.java b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/OctagonalOrientation.java new file mode 100644 index 00000000000..ca8c0b4d925 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/OctagonalOrientation.java @@ -0,0 +1,171 @@ +/* + * This file is part of ConnectedTexturesMod (https://github.com/Chisel-Team/ConnectedTexturesMod). + * Copyright (c) 2023 Chisel Team. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * ConnectedTexturesMod 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 ConnectedTexturesMod; if not, If not, see . + */ +package com.gregtechceu.gtceu.client.model.ctm; + +import com.gregtechceu.gtceu.utils.GTUtil; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +import java.util.Locale; + +import static net.minecraft.core.Direction.*; + +/** + * Think of this class as an octagonal {@link net.minecraft.core.Direction}. + *

+ * It represents the eight different directions a face of a block can connect with CTM, + * and contains the logic for determining if a block is indeed connected in that direction. + *

+ * Note that, for example, {@link #TOP_RIGHT} does not mean connected to the {@link #TOP} and {@link #RIGHT}, + * but connected in the diagonal direction represented by {@link #TOP_RIGHT}. + * This is used for inner corner rendering. + *

+ * Sourced from ConnectedTexturesMod. + */ +public enum OctagonalOrientation implements StringRepresentable { + + // spotless:off + TOP(UP), + TOP_RIGHT(UP, EAST), + RIGHT(EAST), + BOTTOM_RIGHT(DOWN, EAST), + BOTTOM(DOWN), + BOTTOM_LEFT(DOWN, WEST), + LEFT(WEST), + TOP_LEFT(UP, WEST); + // spotless:on + + public static final OctagonalOrientation[] VALUES = values(); + private static final Direction NORMAL = SOUTH; + + static { + // Run after static init + for (OctagonalOrientation dir : OctagonalOrientation.VALUES) { + dir.buildCaches(); + } + } + + private final Direction[] dirs; + + private final BlockPos[] offsets = new BlockPos[6]; + + OctagonalOrientation(Direction... dirs) { + this.dirs = dirs; + } + + private void buildCaches() { + // Fill normalized dirs + for (Direction normal : GTUtil.DIRECTIONS) { + Direction[] normalized; + if (normal == NORMAL) { + normalized = dirs; + } else if (normal == NORMAL.getOpposite()) { + // If this is the opposite direction of the default normal, we need to mirror the dirs + // A mirror version does not affect y+ and y- so we ignore those + Direction[] ret = new Direction[dirs.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = dirs[i].getStepY() != 0 ? dirs[i] : dirs[i].getOpposite(); + } + normalized = ret; + } else { + Direction axis; + // Next, we need different a different rotation axis depending on if this is up/down or not + if (normal.getAxis() != Axis.Y) { + // If it is not up/down, pick either the left or right-hand rotation + axis = normal == NORMAL.getClockWise() ? UP : DOWN; + } else { + // If it is up/down, pick either the up or down rotation. + axis = normal == UP ? NORMAL.getCounterClockWise() : NORMAL.getClockWise(); + } + Direction[] ret = new Direction[dirs.length]; + // Finally apply all the rotations + for (int i = 0; i < ret.length; i++) { + ret[i] = rotate(dirs[i], axis); + } + normalized = ret; + } + BlockPos ret = BlockPos.ZERO; + for (Direction dir : normalized) { + ret = ret.relative(dir); + } + offsets[normal.ordinal()] = ret; + } + } + + /** + * Finds if this block is connected for the given side in this OctagonalOrientation. + * + * @param level The level the block is in. + * @param pos The position of your block. + * @param state The state of your block. + * @param side The side of the current face. + * @return True if the block is connected in the given OctagonalOrientation, false otherwise. + */ + public boolean isConnected(BlockAndTintGetter level, BlockPos pos, BlockState state, Direction side) { + return ConnectionCheck.isConnected(level, pos, state, applyConnection(pos, side), side); + } + + /** + * Finds if this block is connected for the given side in this OctagonalOrientation. + * + * @param level The level the block is in. + * @param pos The position of your block. + * @param state The state of your block. + * @param side The side of the current face. + * @param connectionState The state to check for connection with. + * @return True if the block is connected in the given OctagonalOrientation, false otherwise. + */ + public boolean isConnected(BlockAndTintGetter level, BlockPos pos, BlockState state, + Direction side, BlockState connectionState) { + return ConnectionCheck.isConnected(level, pos, state, applyConnection(pos, side), side, connectionState); + } + + /** + * Apply this OctagonalOrientation to the given BlockPos for the given normal direction. + * + * @return The offset BlockPos + */ + public BlockPos applyConnection(BlockPos pos, Direction side) { + return pos.offset(getOffset(side)); + } + + public BlockPos getOffset(Direction normal) { + return offsets[normal.ordinal()]; + } + + private Direction rotate(Direction facing, Direction axisFacing) { + Direction.Axis axis = axisFacing.getAxis(); + AxisDirection axisDir = axisFacing.getAxisDirection(); + + if (axisDir == AxisDirection.POSITIVE) { + return facing.getClockWise(axis); + } else { + return facing.getCounterClockWise(axis); + } + } + + @Override + public String getSerializedName() { + return name().toLowerCase(Locale.ROOT); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/ctm/Submap.java b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/Submap.java new file mode 100644 index 00000000000..3fbfba47392 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/Submap.java @@ -0,0 +1,95 @@ +/* + * This file is part of ConnectedTexturesMod (https://github.com/Chisel-Team/ConnectedTexturesMod). + * Copyright (c) 2023 Chisel Team. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * ConnectedTexturesMod 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 ConnectedTexturesMod; if not, If not, see . + */ +package com.gregtechceu.gtceu.client.model.ctm; + +import lombok.Getter; + +/** + * Sourced from ConnectedTexturesMod. + */ +public class Submap implements ISubmap { + + // spotless:off + public static final ISubmap X1 = fromPixelScale(16, 16, 0, 0); + + public static final ISubmap[][] X2 = { + { fromPixelScale(8, 8, 0, 0), fromPixelScale(8, 8, 8, 0) }, + { fromPixelScale(8, 8, 0, 8), fromPixelScale(8, 8, 8, 8) } + }; + + private static final float DIV3 = 16 / 3f; + public static final ISubmap[][] X3 = { + { fromPixelScale(DIV3, DIV3, 0, 0), fromPixelScale(DIV3, DIV3, DIV3, 0), fromPixelScale(DIV3, DIV3, DIV3 * 2, 0) }, + { fromPixelScale(DIV3, DIV3, 0, DIV3), fromPixelScale(DIV3, DIV3, DIV3, DIV3), fromPixelScale(DIV3, DIV3, DIV3 * 2, DIV3) }, + { fromPixelScale(DIV3, DIV3, 0, DIV3 * 2), fromPixelScale(DIV3, DIV3, DIV3, DIV3 * 2), fromPixelScale(DIV3, DIV3, DIV3 * 2, DIV3 * 2) }, + }; + + public static final ISubmap[][] X4 = { + { fromPixelScale(4, 4, 0, 0), fromPixelScale(4, 4, 4, 0), fromPixelScale(4, 4, 8, 0), fromPixelScale(4, 4, 12, 0) }, + { fromPixelScale(4, 4, 0, 4), fromPixelScale(4, 4, 4, 4), fromPixelScale(4, 4, 8, 4), fromPixelScale(4, 4, 12, 4) }, + { fromPixelScale(4, 4, 0, 8), fromPixelScale(4, 4, 4, 8), fromPixelScale(4, 4, 8, 8), fromPixelScale(4, 4, 12, 8) }, + { fromPixelScale(4, 4, 0, 12), fromPixelScale(4, 4, 4, 12), fromPixelScale(4, 4, 8, 12), fromPixelScale(4, 4, 12, 12) }, + }; + // spotless:on + + public static ISubmap[][] grid(int w, int h) { + float xDiv = 16f / w; + float yDiv = 16f / h; + ISubmap[][] ret = new ISubmap[h][w]; + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + ret[y][x] = fromPixelScale(xDiv, yDiv, xDiv * x, yDiv * y); + } + } + return ret; + } + + public static ISubmap raw(float width, float height, float xOffset, float yOffset) { + return new Submap(width, height, xOffset, yOffset, 1); + } + + public static ISubmap fromUnitScale(float width, float height, float xOffset, float yOffset) { + return fromPixelScale(width * PIXELS_PER_UNIT, height * PIXELS_PER_UNIT, xOffset * PIXELS_PER_UNIT, + yOffset * PIXELS_PER_UNIT); + } + + public static ISubmap fromPixelScale(float width, float height, float xOffset, float yOffset) { + return new Submap(width, height, xOffset, yOffset, UNITS_PER_PIXEL); + } + + @Getter + private final float width, height; + @Getter + private final float xOffset, yOffset; + + final SubmapRescaled rescaled; + + private Submap(float width, float height, float xOffset, float yOffset, float rescale) { + this.width = width; + this.height = height; + this.xOffset = xOffset; + this.yOffset = yOffset; + this.rescaled = new SubmapRescaled(this, rescale, false); + } + + @Override + public SubmapRescaled pixelScale() { + return this.rescaled; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/ctm/TextureConnections.java b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/TextureConnections.java new file mode 100644 index 00000000000..1e717a3bb3c --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/TextureConnections.java @@ -0,0 +1,279 @@ +/* + * This file is part of ConnectedTexturesMod (https://github.com/Chisel-Team/ConnectedTexturesMod). + * Copyright (c) 2023 Chisel Team. + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * ConnectedTexturesMod 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 ConnectedTexturesMod; if not, If not, see . + */ +package com.gregtechceu.gtceu.client.model.ctm; + +import com.gregtechceu.gtceu.utils.ArrayHelpers; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +import lombok.experimental.Accessors; +import org.jetbrains.annotations.Nullable; +import org.joml.Vector2i; +import org.joml.Vector2ic; + +import static com.gregtechceu.gtceu.client.model.ctm.OctagonalOrientation.*; + +// spotless:off +/** + * The CTM renderer will draw the block's FACE by assembling 4 quadrants from the 5 available block textures. + * The normal {@code texture.png} is the block's "unconnected" texture, and is used when CTM is disabled or the block + * has nothing to connect to. + * This texture has all the outside corner quadrants, and {@code texture_ctm.png} contains the rest of the quadrants. + *

+ * ┌─────────────────┐ ┌────────────────────────────────┐
+ * │ texture.png     │ │ texture_ctm.png                │
+ * │ ╔══════╤══════╗ │ │  ──────┼────── ║ ─────┼───── ║ │
+ * │ ║      │      ║ │ │ │      │      │║      │      ║ │
+ * │ ║ 4/4  │ 4/5  ║ │ │ │ 0/0  │ 0/1  │║ 0/2  │ 0/3  ║ │
+ * │ ╟──────┼──────╢ │ │ ┼──────┼──────┼╟──────┼──────╢ │
+ * │ ║      │      ║ │ │ │      │      │║      │      ║ │
+ * │ ║ 5/4  │ 5/5  ║ │ │ │ 1/0  │ 1/1  │║ 1/2  │ 1/3  ║ │
+ * │ ╚══════╧══════╝ │ │  ──────┼────── ║ ─────┼───── ║ │
+ * └─────────────────┘ │ ═══════╤═══════╝ ─────┼───── ╚ │
+ *                     │ │      │      ││      │      │ │
+ *                     │ │ 2/0  │ 2/1  ││ 2/2  │ 2/3  │ │
+ *                     │ ┼──────┼──────┼┼──────┼──────┼ │
+ *                     │ │      │      ││      │      │ │
+ *                     │ │ 3/0  │ 3/1  ││ 3/2  │ 3/3  │ │
+ *                     │ ═══════╧═══════╗ ─────┼───── ╔ │
+ *                     └────────────────────────────────┘
+ * 
+ * combining { { 5/4, 3/1 }, { 2/1, 4/4 } }, we can generate a texture connected to the right! + *
+ * ╔══════╤═══════
+ * ║      │      │
+ * ║ 4/4  │ 2/1  │
+ * ╟──────┼──────┼
+ * ║      │      │
+ * ║ 5/4  │ 3/1  │
+ * ╚══════╧═══════
+ * 
+ * + * combining { { 5/4, 3/1 }, { 0/2, 2/3 } }, we can generate a texture in the shape of an L + * (connected to the right and up) + *
+ * ║ ─────┼───── ╚
+ * ║      │      │
+ * ║ 0/2  │ 2/3  │
+ * ╟──────┼──────┼
+ * ║      │      │
+ * ║ 5/4  │ 3/1  │
+ * ╚══════╧═══════
+ * 
+ * + * HAVE FUN! + * -CptRageToaster- + *

+ * Sourced from ConnectedTexturesMod. + */ +// spotless:on +@Accessors(fluent = true, chain = true) +public class TextureConnections { + + /** Hardcoded offset values for the different submap indices */ + // store the full table(s) to reduce non-required allocations + protected static final Vector2ic[][] submapOffsets = { + { new Vector2i(0, 0), new Vector2i(0, 1), new Vector2i(0, 2), new Vector2i(0, 3), }, + { new Vector2i(1, 0), new Vector2i(1, 1), new Vector2i(1, 2), new Vector2i(1, 3), }, + { new Vector2i(2, 0), new Vector2i(2, 1), new Vector2i(2, 2), new Vector2i(2, 3), }, + { new Vector2i(3, 0), new Vector2i(3, 1), new Vector2i(3, 2), new Vector2i(3, 3), }, + }; + protected static final Vector2ic[][] defaultSubmapCache = { + { new Vector2i(4, 4), new Vector2i(4, 5), }, + { new Vector2i(5, 4), new Vector2i(5, 5), }, + }; + + // spotless:off + // Mapping the different corner indices to their respective dirs + protected static final OctagonalOrientation[][][] submapMap = { + { { LEFT, TOP, TOP_LEFT }, { RIGHT, TOP, TOP_RIGHT }, }, + { { LEFT, BOTTOM, BOTTOM_LEFT }, { RIGHT, BOTTOM, BOTTOM_RIGHT }, }, + }; + // spotless:on + + protected byte connectionMap; + protected Vector2ic[][] submapCache = ArrayHelpers.deepCopy(defaultSubmapCache); + + public static TextureConnections getInstance() { + return new TextureConnections(); + } + + /** + * Calculate the indices of the typical 4x4 submap to use for the given face at the given location. + * Indices are in counter-clockwise order starting at bottom left. + * + * @return The indices of the typical 4x4 submap to use for the given face at the given location. + */ + public Vector2ic[][] fillSubmapCache(@Nullable BlockAndTintGetter level, BlockPos pos, + BlockState state, Direction side) { + if (level == null) { + return this.submapCache; + } + + buildConnectionMap(level, pos, state, side); + // Map connections to submap indices + for (int x = 0; x < 2; x++) { + for (int y = 0; y < 2; y++) { + fillSubmaps(x, y); + } + } + + return this.submapCache; + } + + public Vector2ic[][] getCachedSubmapIndices() { + return this.submapCache; + } + + public Vector2ic getSubmapCoordinatesFor(int quadrantX, int quadrantY) { + return this.submapCache[quadrantX][quadrantY]; + } + + public boolean isDefaultTexture(int quadrantX, int quadrantY) { + return isDefaultTexture(getSubmapCoordinatesFor(quadrantX, quadrantY)); + } + + public static boolean isDefaultTexture(Vector2ic id) { + return id.x() >= 4 && id.y() >= 4; + } + + public ISubmap getSubmapFor(int quadrantX, int quadrantY) { + return getSubmapFor(getSubmapCoordinatesFor(quadrantX, quadrantY)); + } + + public static ISubmap getSubmapFor(Vector2ic coordinates) { + if (isDefaultTexture(coordinates)) { + return Submap.X2[coordinates.x() % 4][coordinates.y() % 4]; + } else { + return Submap.X4[coordinates.x()][coordinates.y()]; + } + } + + protected void setConnectedState(OctagonalOrientation dir, boolean connected) { + this.connectionMap = setConnectedState(this.connectionMap, dir, connected); + } + + private static byte setConnectedState(byte map, OctagonalOrientation dir, boolean connected) { + if (connected) { + return (byte) (map | (1 << dir.ordinal())); + } else { + return (byte) (map & ~(1 << dir.ordinal())); + } + } + + /** + * Builds the connection map and stores it in this CTMLogic instance.
+ * The {@link #connected(OctagonalOrientation)}, {@link #connectedAnd(OctagonalOrientation...)}, + * and {@link #connectedOr(OctagonalOrientation...)} methods can be used to access it. + */ + public void buildConnectionMap(BlockAndTintGetter world, BlockPos pos, BlockState state, Direction side) { + // TODO this naive check doesn't work for models that have unculled faces. + // Perhaps a smarter optimization could be done eventually? + for (OctagonalOrientation dir : OctagonalOrientation.VALUES) { + // Note: We can't cache the state that we are checking about connection for as we want to ensure that + // we can take into account the side of the block we want to know the "state" of as if the block is + // a facade of some sort it might return different results based on where it is being queried from + setConnectedState(dir, dir.isConnected(world, pos, state, side)); + } + } + + @SuppressWarnings("null") + protected void fillSubmaps(int x, int y) { + // [0] is horizontal, [1] is vertical, [2] is diagonal + OctagonalOrientation[] dirs = submapMap[x][y]; + if (connectedOr(dirs[0], dirs[1])) { + if (connectedAnd(dirs)) { + // If all dirs are connected, we use the fully connected face, the base offset value. + this.submapCache[x][y] = submapOffsets[x][y]; + } else { + this.submapCache[x][y] = submapOffsets[x + (connected(dirs[0]) ? 2 : 0)][y + + (connected(dirs[1]) ? 2 : 0)]; + } + } + } + + /** + * @param dir The direction to check connection in. + * @return True if the cached connectionMap holds a connection in this {@link OctagonalOrientation direction}. + */ + public boolean connected(OctagonalOrientation dir) { + return ((this.connectionMap >> dir.ordinal()) & 1) == 1; + } + + /** + * @param dirs The directions to check connection in. + * @return True if the cached connectionMap holds a connection in all the given + * {@link OctagonalOrientation directions}. + */ + @SuppressWarnings("null") + public boolean connectedAnd(OctagonalOrientation... dirs) { + for (OctagonalOrientation dir : dirs) { + if (!connected(dir)) { + return false; + } + } + return true; + } + + /** + * @param dirs + * The directions to check connection in. + * @return True if the cached connectionMap holds a connection in one of the given + * {@link OctagonalOrientation directions}. + */ + @SuppressWarnings("null") + public boolean connectedOr(OctagonalOrientation... dirs) { + for (OctagonalOrientation dir : dirs) { + if (connected(dir)) { + return true; + } + } + return false; + } + + public boolean connectedNone(OctagonalOrientation... dirs) { + for (OctagonalOrientation dir : dirs) { + if (connected(dir)) { + return false; + } + } + return true; + } + + public boolean connectedOnly(OctagonalOrientation... dirs) { + byte map = 0; + for (OctagonalOrientation dir : dirs) { + map = setConnectedState(map, dir, true); + } + return map == this.connectionMap; + } + + @Override + public int hashCode() { + return this.connectionMap; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TextureConnections other)) return false; + return this.connectionMap == other.connectionMap; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/ctm/package-info.java b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/package-info.java new file mode 100644 index 00000000000..ca86d8adbbc --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/ctm/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.client.model.ctm; + +import org.jetbrains.annotations.NotNullByDefault; diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModel.java b/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModel.java index ed631e969e4..e580ab23c2d 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModel.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/machine/MachineModel.java @@ -10,16 +10,16 @@ import com.gregtechceu.gtceu.client.model.GTModelProperties; import com.gregtechceu.gtceu.client.model.IBlockEntityRendererBakedModel; import com.gregtechceu.gtceu.client.model.TextureOverrideModel; +import com.gregtechceu.gtceu.client.model.ctm.CTMMeshBuilder; import com.gregtechceu.gtceu.client.model.machine.multipart.MultiPartBakedModel; +import com.gregtechceu.gtceu.client.model.quad.StaticFaceBakery; import com.gregtechceu.gtceu.client.renderer.cover.ICoverableRenderer; import com.gregtechceu.gtceu.client.renderer.machine.DynamicRender; -import com.gregtechceu.gtceu.client.util.StaticFaceBakery; +import com.gregtechceu.gtceu.client.util.RenderUtil; import com.gregtechceu.gtceu.common.data.models.GTModels; import com.gregtechceu.gtceu.common.machine.trait.AutoOutputTrait; import com.gregtechceu.gtceu.utils.GTUtil; -import com.lowdragmc.lowdraglib.client.model.custommodel.CustomBakedModel; - import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MultiBufferSource; @@ -319,8 +319,8 @@ public List renderMachine(@Nullable MetaMachine machine, @Nullable Bl // we have to recalculate CTM ourselves. // this is the slowest part by a long shot because the LDLib quad logic isn't very optimized. - if (level != null && pos != null && blockState != null) { - return CustomBakedModel.reBakeCustomQuads(quads, level, pos, blockState, side, 0.0f); + if (level != null && pos != null && blockState != null && side != null) { + return CTMMeshBuilder.buildCTMQuads(level, pos, blockState, quads, side); } return quads; } @@ -343,7 +343,7 @@ public List replacePartBaseModel(List originalQuads, IMult var controllers = part.getControllers(); for (MultiblockControllerMachine controller : controllers) { var state = controller.getBlockState(); - BakedModel model = Minecraft.getInstance().getBlockRenderer().getBlockModel(state); + BakedModel model = RenderUtil.getModelForState(state); List newQuads = null; // spotless:off diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/package-info.java b/src/main/java/com/gregtechceu/gtceu/client/model/package-info.java index 756fd4d977e..9c694981ff8 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/model/package-info.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/package-info.java @@ -1,7 +1,4 @@ -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault +@NotNullByDefault package com.gregtechceu.gtceu.client.model; -import net.minecraft.MethodsReturnNonnullByDefault; - -import javax.annotation.ParametersAreNonnullByDefault; +import org.jetbrains.annotations.NotNullByDefault; 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..3e04a26c029 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 @@ -9,7 +9,8 @@ import com.gregtechceu.gtceu.client.model.GTModelProperties; 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.client.util.RenderUtil; +import com.gregtechceu.gtceu.client.util.quad.transformers.GTQuadTransformers; import com.gregtechceu.gtceu.common.data.GTMaterialBlocks; import com.gregtechceu.gtceu.utils.GTUtil; @@ -102,7 +103,7 @@ public List getQuads(@Nullable BlockState state, @Nullable Direction return quads; } BlockState frameState = frameBlockEntry.getDefaultState(); - BakedModel frameModel = Minecraft.getInstance().getBlockRenderer().getBlockModel(frameState); + BakedModel frameModel = RenderUtil.getModelForState(frameState); modelData = frameModel.getModelData(level, pos, frameState, modelData); diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/quad/EncodingFormat.java b/src/main/java/com/gregtechceu/gtceu/client/model/quad/EncodingFormat.java new file mode 100644 index 00000000000..85795309e0f --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/quad/EncodingFormat.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gregtechceu.gtceu.client.model.quad; + +import com.gregtechceu.gtceu.client.util.quad.GeometryHelper; + +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraftforge.client.model.IQuadTransformer; + +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +/** + * Holds all the array offsets and bit-wise encoders/decoders for packing/unpacking quad data in an array of integers. + * All of this is implementation-specific - that's why it isn't a "helper" class. + */ +@SuppressWarnings("PointlessArithmeticExpression") +@UtilityClass +public class EncodingFormat { + + static final int VERTEX_X = IQuadTransformer.POSITION + 0; + static final int VERTEX_Y = IQuadTransformer.POSITION + 1; + static final int VERTEX_Z = IQuadTransformer.POSITION + 2; + static final int VERTEX_COLOR = IQuadTransformer.COLOR; + static final int VERTEX_U = IQuadTransformer.UV0 + 0; + static final int VERTEX_V = IQuadTransformer.UV0 + 1; + static final int VERTEX_LIGHTMAP = IQuadTransformer.UV2; + static final int VERTEX_NORMAL = IQuadTransformer.NORMAL; + public static final int VERTEX_STRIDE = IQuadTransformer.STRIDE; + + public static final int QUAD_STRIDE = VERTEX_STRIDE * 4; + + /** used for quick clearing of quad buffers. */ + static final int[] EMPTY = new int[QUAD_STRIDE]; + + private static final int DIRECTION_MASK = Mth.smallestEncompassingPowerOfTwo(GeometryHelper.NULL_FACE_ID) - 1; + private static final int DIRECTION_BIT_COUNT = Integer.bitCount(DIRECTION_MASK); + private static final int CULL_SHIFT = 0; + private static final int CULL_INVERSE_MASK = ~(DIRECTION_MASK << CULL_SHIFT); + private static final int LIGHT_SHIFT = CULL_SHIFT + DIRECTION_BIT_COUNT; + private static final int LIGHT_INVERSE_MASK = ~(DIRECTION_MASK << LIGHT_SHIFT); + private static final int NORMALS_SHIFT = LIGHT_SHIFT + DIRECTION_BIT_COUNT; + private static final int NORMALS_COUNT = 4; + private static final int NORMALS_MASK = (1 << NORMALS_COUNT) - 1; + private static final int NORMALS_INVERSE_MASK = ~(NORMALS_MASK << NORMALS_SHIFT); + + static @Nullable Direction cullFace(long bits) { + return GeometryHelper.faceFromIndex((int) ((bits >> CULL_SHIFT) & DIRECTION_MASK)); + } + + static long cullFace(long bits, @Nullable Direction face) { + return (bits & CULL_INVERSE_MASK) | (GeometryHelper.toFaceIndex(face) << CULL_SHIFT); + } + + static Direction lightFace(long bits) { + return Objects.requireNonNull(GeometryHelper.faceFromIndex((int) ((bits >> LIGHT_SHIFT) & DIRECTION_MASK))); + } + + static long lightFace(long bits, Direction face) { + return (bits & LIGHT_INVERSE_MASK) | ((long) GeometryHelper.toFaceIndex(face) << LIGHT_SHIFT); + } + + /** indicate if vertex normal has been set - bits correspond to vertex ordinals. */ + static int normalFlags(long bits) { + return (int) ((bits >> NORMALS_SHIFT) & NORMALS_MASK); + } + + static long normalFlags(long bits, int normalFlags) { + return (bits & NORMALS_INVERSE_MASK) | ((long) (normalFlags & NORMALS_MASK) << NORMALS_SHIFT); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/quad/Mesh.java b/src/main/java/com/gregtechceu/gtceu/client/model/quad/Mesh.java new file mode 100644 index 00000000000..29403d1af8a --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/quad/Mesh.java @@ -0,0 +1,66 @@ +package com.gregtechceu.gtceu.client.model.quad; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlas; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +/** + * A bundle of one or more {@link QuadView} instances encoded by the renderer. + * + *

+ * Similar in purpose to the {@code List} instances returned by BakedModel, but affords the renderer the + * ability to optimize the format for performance and memory allocation. + * + *

+ * Only the renderer should implement or extend this interface. + * + * @implNote The way we encode meshes makes it very simple. + */ +public class Mesh { + + /** Used to satisfy external calls to {@link #forEach(Consumer)}. */ + private static final ThreadLocal POOL = ThreadLocal.withInitial(QuadView::new); + + final int[] data; + + Mesh(int[] data) { + this.data = data; + } + + public int[] data() { + return data; + } + + public void forEach(Consumer consumer) { + forEach(consumer, POOL.get()); + } + + /** + * The renderer will call this with its own cursor to avoid the performance hit of a thread-local lookup. Also + * means renderer can hold final references to quad buffers. + */ + void forEach(Consumer consumer, QuadView cursor) { + final int limit = data.length; + int index = 0; + + while (index < limit) { + cursor.load(data, index); + consumer.accept(cursor); + index += EncodingFormat.QUAD_STRIDE; + } + } + + @SuppressWarnings("deprecation") + public List toBlockBakedQuads() { + SpriteFinder finder = SpriteFinder.get(Minecraft.getInstance().getModelManager() + .getAtlas(TextureAtlas.LOCATION_BLOCKS)); + + List result = new ArrayList<>(); + forEach(qv -> result.add(qv.toBakedQuad(finder.find(qv)))); + return result; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/quad/MeshBuilder.java b/src/main/java/com/gregtechceu/gtceu/client/model/quad/MeshBuilder.java new file mode 100644 index 00000000000..bfebec00b2b --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/quad/MeshBuilder.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gregtechceu.gtceu.client.model.quad; + +/** + * Similar in purpose to {@link com.mojang.blaze3d.vertex.BufferBuilder} but simpler and not tied to NIO + * or any other specific implementation, plus designed to handle both static and dynamic building. + * + *

+ * Decouples models from the vertex format(s) used by ModelRenderer to allow compatibility across diverse + * implementations. + * + * @implNote Not much to it - mainly it just needs to grow the int[] array as quads are appended and + * maintain/provide a properly-configured {@link MutableQuadView} instance. + * All the encoding and other work is handled in the quad base classes. + * The one interesting bit is in {@link Maker#emit()}. + */ +public class MeshBuilder { + + private int[] data = new int[256]; + private final Maker maker = new Maker(); + private int index = 0; + private int limit = data.length; + + public static MeshBuilder getInstance() { + return new MeshBuilder(); + } + + protected void ensureCapacity() { + if (EncodingFormat.QUAD_STRIDE > limit - index) { + limit *= 2; + final int[] bigger = new int[limit]; + System.arraycopy(data, 0, bigger, 0, index); + data = bigger; + maker.data = bigger; + } + } + + public Mesh build() { + final int[] packed = new int[index]; + System.arraycopy(data, 0, packed, 0, index); + index = 0; + maker.begin(data, index); + return new Mesh(packed); + } + + public MutableQuadView getEmitter() { + ensureCapacity(); + maker.begin(data, index); + return maker; + } + + /** + * Our base classes are used differently so we define final encoding steps in subtypes. This will be a static mesh + * used at render time so we want to capture all geometry now and apply non-location-dependent lighting. + */ + private class Maker extends MutableQuadView { + + @Override + public Maker emit() { + computeGeometry(); + populateMissingNormals(); + index += EncodingFormat.QUAD_STRIDE; + ensureCapacity(); + baseIndex = index; + clear(); + return this; + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/quad/MutableQuadView.java b/src/main/java/com/gregtechceu/gtceu/client/model/quad/MutableQuadView.java new file mode 100644 index 00000000000..828720357f5 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/quad/MutableQuadView.java @@ -0,0 +1,523 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gregtechceu.gtceu.client.model.quad; + +import com.gregtechceu.gtceu.client.util.TextureHelper; +import com.gregtechceu.gtceu.client.util.quad.GeometryHelper; + +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraftforge.client.model.QuadTransformers; + +import org.jetbrains.annotations.Nullable; +import org.joml.Vector2fc; +import org.joml.Vector3f; + +import static com.gregtechceu.gtceu.client.model.quad.EncodingFormat.*; + +/** + * A mutable {@link QuadView} instance. + * + *

+ * Instances of {@link MutableQuadView} will practically always be thread local and/or reused - do not retain + * references. + * + *

+ * Only the renderer should implement or extend this interface. + * + * @implNote Almost-concrete implementation of a mutable quad. + */ +public abstract class MutableQuadView extends QuadView { + + /** + * Causes texture to appear with no rotation. + * Pass in bakeFlags parameter to {@link #spriteBake(TextureAtlasSprite, int)}. + */ + public static final int BAKE_ROTATE_NONE = 0b000000; + + /** + * Causes texture to appear rotated 90 deg. clockwise relative to nominal face. Pass in bakeFlags parameter to + * {@link #spriteBake(TextureAtlasSprite, int)}. + */ + public static final int BAKE_ROTATE_90 = 0b000001; + + /** + * Causes texture to appear rotated 180 deg. relative to nominal face. Pass in bakeFlags parameter to + * {@link #spriteBake(TextureAtlasSprite, int)}. + */ + public static final int BAKE_ROTATE_180 = 0b000010; + + /** + * Causes texture to appear rotated 270 deg. clockwise relative to nominal face. Pass in bakeFlags parameter to + * {@link #spriteBake(TextureAtlasSprite, int)}. + */ + public static final int BAKE_ROTATE_270 = 0b000011; + + /** + * When enabled, texture coordinates are assigned based on vertex position. + * Any existing UV coordinates will be replaced. + * Pass in bakeFlags parameter to {@link #spriteBake(TextureAtlasSprite, int)}. + * + *

+ * UV lock always derives texture coordinates based on nominal face, even when the quad is not co-planar + * with that face. The result is the same as if the quad were projected onto the nominal face, which is usually the + * desired result. + */ + public static final int BAKE_LOCK_UV = 0b000100; + + /** + * When enabled, texture coordinates are cycled so that vertex 0's UVs are the smallest. + * Pass in bakeFlags parameter to {@link TextureHelper#unbakeSprite(MutableQuadView, TextureAtlasSprite, int)}. + */ + public static final int BAKE_DEROTATE_UV = 0b000100; + + /** + * When set, U texture coordinates for the given sprite are flipped as part of baking. Can be useful for some + * randomization and texture mapping scenarios. Results are different from what can be obtained via rotation and + * both can be applied. Pass in bakeFlags parameter to {@link #spriteBake(TextureAtlasSprite, int)}. + */ + public static final int BAKE_FLIP_U = 0b001000; + + /** + * Same as {@link #BAKE_FLIP_U} but for V coordinate. + */ + public static final int BAKE_FLIP_V = 0b010000; + + /** + * UV coordinates by default are assumed to be 0-16 scale for consistency with conventional Minecraft model format. + * This is scaled to 0-1 during baking before interpolation. Model loaders that already have 0-1 coordinates can + * avoid wasteful multiplication/division by passing 0-1 coordinates directly. + * Pass in bakeFlags parameter to {@link #spriteBake(TextureAtlasSprite, int)}. + */ + public static final int BAKE_NORMALIZED = 0b100000; + + public static MutableQuadView getInstance() { + return MutableQuadView.THREAD_LOCAL.get(); + } + + public static final ThreadLocal THREAD_LOCAL = ThreadLocal + .withInitial(() -> new MutableQuadView() { + + { + begin(new int[QUAD_STRIDE], 0); + } + + @Override + public MutableQuadView emit() { + throw new UnsupportedOperationException(); + } + }); + + public final void begin(int[] data, int baseIndex) { + this.data = data; + this.baseIndex = baseIndex; + clear(); + } + + public void clear() { + System.arraycopy(EMPTY, 0, data, baseIndex, QUAD_STRIDE); + isGeometryInvalid = true; + nominalFace = null; + tintIndex(-1); + cullFace(null); + } + + /** + * Sets the geometric vertex position for the given vertex, relative to block origin, (0,0,0). + * Minecraft rendering is designed for models that fit within a single block space and is recommended + * that coordinates remain in the 0-1 range, with multi-block meshes split into multiple per-block models. + */ + public MutableQuadView pos(int vertexIndex, float x, float y, float z) { + final int index = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X; + data[index] = Float.floatToRawIntBits(x); + data[index + 1] = Float.floatToRawIntBits(y); + data[index + 2] = Float.floatToRawIntBits(z); + isGeometryInvalid = true; + return this; + } + + /** + * Same as {@link #pos(int, float, float, float)} but accepts a vector type. + */ + public MutableQuadView pos(int vertexIndex, Vector3f pos) { + return pos(vertexIndex, pos.x(), pos.y(), pos.z()); + } + + /** + * Sets the vertex X position for the given vertex, relative to block origin, (0,0,0). + * Minecraft rendering is designed for models that fit within a single block space and is recommended + * that coordinates remain in the 0-1 range, with multi-block meshes split into multiple per-block models. + */ + public MutableQuadView x(int vertexIndex, float x) { + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X] = Float.floatToRawIntBits(x); + isGeometryInvalid = true; + return this; + } + + /** + * Sets the vertex Y position for the given vertex, relative to block origin, (0,0,0). + * Minecraft rendering is designed for models that fit within a single block space and is recommended + * that coordinates remain in the 0-1 range, with multi-block meshes split into multiple per-block models. + */ + public MutableQuadView y(int vertexIndex, float y) { + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_Y] = Float.floatToRawIntBits(y); + isGeometryInvalid = true; + return this; + } + + /** + * Sets the vertex Z position for the given vertex, relative to block origin, (0,0,0). + * Minecraft rendering is designed for models that fit within a single block space and is recommended + * that coordinates remain in the 0-1 range, with multi-block meshes split into multiple per-block models. + */ + public MutableQuadView z(int vertexIndex, float z) { + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_Z] = Float.floatToRawIntBits(z); + isGeometryInvalid = true; + return this; + } + + /** + * Set vertex color. + */ + public MutableQuadView color(int vertexIndex, int color) { + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_COLOR] = color; + return this; + } + + /** + * Convenience: set vertex color for all vertices at once. + */ + public MutableQuadView color(int c0, int c1, int c2, int c3) { + color(0, c0); + color(1, c1); + color(2, c2); + color(3, c3); + return this; + } + + /** + * Set texture coordinates. + */ + public MutableQuadView uv(int vertexIndex, float u, float v) { + final int i = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_U; + data[i] = Float.floatToRawIntBits(u); + data[i + 1] = Float.floatToRawIntBits(v); + return this; + } + + /** + * Set texture coordinates. + * + *

+ * Only use this function if you already have a {@link Vector2fc}. + * Otherwise, see {@link MutableQuadView#uv(int, float, float)}. + * + * @see MutableQuadView#uv(int, float, float) + */ + public MutableQuadView uv(int vertexIndex, Vector2fc uv) { + return uv(vertexIndex, uv.x(), uv.y()); + } + + /** + * Assigns sprite atlas u,v coordinates to this quad for the given sprite. + * Can handle UV locking, rotation, interpolation, etc. + * Control this behavior by passing additive combinations of the BAKE_ flags defined in this interface. + */ + public MutableQuadView spriteBake(@Nullable TextureAtlasSprite sprite, int bakeFlags) { + TextureHelper.bakeSprite(this, sprite, bakeFlags); + return this; + } + + /** + * Normalizes this quad's u,v coordinates based on the given sprite. + * Can handle UV rotation, interpolation, etc. + * Control this behavior by passing additive combinations of the BAKE_ flags defined in this interface. + */ + public MutableQuadView spriteUnbake(@Nullable TextureAtlasSprite sprite, int bakeFlags) { + TextureHelper.unbakeSprite(this, sprite, bakeFlags); + return this; + } + + /** + * Accept vanilla lightmap values. + * Input values will override lightmap values computed from world state if input values are higher. + */ + public MutableQuadView lightmap(int vertexIndex, int lightmap) { + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_LIGHTMAP] = lightmap; + return this; + } + + /** + * Accept vanilla lightmap values. + * Input values will override lightmap values computed from world state if input values are higher. + */ + public MutableQuadView lightmap(int vertexIndex, int block, int sky) { + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_LIGHTMAP] = LightTexture.pack(block, sky); + return this; + } + + /** + * Convenience: set lightmap for all vertices at once. + * + * @see #lightmap(int, int) + */ + public MutableQuadView lightmap(int b0, int b1, int b2, int b3) { + lightmap(0, b0); + lightmap(1, b1); + lightmap(2, b2); + lightmap(3, b3); + return this; + } + + protected void normalFlags(int flags) { + headerFlags = EncodingFormat.normalFlags(headerFlags, flags); + } + + /** + * Adds a vertex normal. + * Models that have per-vertex normals should include them to get correct lighting when it matters. + * Computed face normal is used when no vertex normal is provided. + */ + public MutableQuadView normal(int vertexIndex, float x, float y, float z) { + normalFlags(normalFlags() | (1 << vertexIndex)); + data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_NORMAL] = GeometryHelper.packNormal(x, y, z, 0); + return this; + } + + /** + * Same as {@link #normal(int, float, float, float)} but accepts a vector type. + */ + public MutableQuadView normal(int vertexIndex, Vector3f normal) { + return normal(vertexIndex, normal.x(), normal.y(), normal.z()); + } + + /** + * Internal helper method. Copies face normals to vertex normals lacking one. + */ + public final void populateMissingNormals() { + final int normalFlags = this.normalFlags(); + if (normalFlags == 0b1111) + return; + + final int packedFaceNormal = GeometryHelper.packNormal(faceNormal(), 0); + + for (int v = 0; v < 4; v++) { + if ((normalFlags & (1 << v)) == 0) { + data[baseIndex + v * VERTEX_STRIDE + VERTEX_NORMAL] = packedFaceNormal; + } + } + + normalFlags(0b1111); + } + + /** + * If non-null, quad is coplanar with a block face which, if known, simplifies or shortcuts geometric analysis + * that might otherwise be needed. Set to null if quad is not coplanar or if this is not known. + * Also controls face culling during block rendering. + * + *

+ * Null by default. + * + *

+ * When called with a non-null value, also sets {@link #nominalFace(Direction)} to the same value. + * + *

+ * This is different from the value reported by {@link BakedQuad#getDirection()}. That value is computed based on + * face geometry and must be non-null in vanilla quads. That computed value is returned by {@link #lightFace()}. + */ + public final MutableQuadView cullFace(@Nullable Direction face) { + headerFlags = EncodingFormat.cullFace(headerFlags, face); + nominalFace(face); + return this; + } + + /** + * Provides a hint to renderer about the facing of this quad. + * Not required, but if provided can shortcut some geometric analysis if the quad is parallel to a block face. + * Should be the expected value of {@link #lightFace()}. + * Value will be confirmed and if invalid the correct light face will be calculated. + * + *

+ * Null by default, and set automatically by {@link #cullFace()}. + * + *

+ * Models may also find this useful as the face for texture UV locking and rotation semantics. + * + *

+ * Note: This value is not persisted independently when the quad is encoded. + * When reading encoded quads, this value will always be the same as {@link #lightFace()}. + */ + public final MutableQuadView nominalFace(@Nullable Direction face) { + this.nominalFace = face; + return this; + } + + /** + * Value functions identically to {@link BakedQuad#getTintIndex()} + * and is used by renderer / model builder in same way.
+ * Default value is -1. + */ + public final MutableQuadView tintIndex(int tintIndex) { + this.tintIndex = tintIndex; + return this; + } + + /** + * Value functions identically to {@link BakedQuad#isShade()} + * and is used by renderer / model builder in the same way.
+ * Default value is true. + */ + public final MutableQuadView shade(boolean shade) { + this.shade = shade; + return this; + } + + /** + * Value functions identically to {@link BakedQuad#hasAmbientOcclusion()} + * and is used by renderer / model builder in the same way.
+ * Default value is true. + */ + public final MutableQuadView ambientOcclusion(boolean ao) { + this.ambientOcclusion = ao; + return this; + } + + /** + * Enables bulk vertex data transfer using the standard Minecraft vertex formats. Only the + * {@link BakedQuad#getVertices() quad vertex data} is copied. This method should be performant whenever caller's + * vertex representation makes it feasible. + * + *

+ * Use {@link #fromVanilla(BakedQuad, Direction) the other overload} which has better encapsulation + * unless you have a specific reason to use this one. + * + *

+ * Calling this method does not emit the quad. + */ + public final MutableQuadView fromVanilla(int[] quadData, int startIndex) { + clear(); + System.arraycopy(quadData, startIndex, this.data, this.baseIndex, QUAD_STRIDE); + this.isGeometryInvalid = true; + + int colorIndex = baseIndex + VERTEX_COLOR; + + for (int i = 0; i < 4; i++) { + this.data[colorIndex] = QuadTransformers.toABGR(this.data[colorIndex]); + colorIndex += VERTEX_STRIDE; + } + + return this; + } + + /** + * Enables bulk vertex data transfer using the standard Minecraft quad format. + * + *

+ * Calling this method does not emit the quad. + */ + public final MutableQuadView fromVanilla(BakedQuad quad, @Nullable Direction cullFace) { + fromVanilla(quad.getVertices(), 0); + headerFlags = EncodingFormat.cullFace(0, cullFace); + + nominalFace(quad.getDirection()); + tintIndex(quad.getTintIndex()); + shade(quad.isShade()); + ambientOcclusion(quad.hasAmbientOcclusion()); + + return this; + } + + /** + * In static mesh building, causes quad to be appended to the mesh being built. In a dynamic render context, create + * a new quad to be output to rendering. In both cases, current instance is reset to default values. + */ + public abstract MutableQuadView emit(); + + /** + * Tolerance for determining if the depth parameter to {@link #square(Direction, float, float, float, float, float)} + * is effectively zero - meaning the face is a cull face. + */ + private static final float CULL_FACE_EPSILON = Mth.EPSILON; + + /** + * Helper method to assign vertex coordinates for a square aligned with the given face. + * Ensures that vertex order is consistent with vanilla convention. + * (Incorrect order can lead to bad AO lighting unless enhanced lighting logic is available/enabled.) + * + *

+ * Square will be parallel to the given face and coplanar with the face (and culled if the face is occluded) + * if the depth parameter is approximately zero. See {@link #CULL_FACE_EPSILON}. + * + *

+ * All coordinates should be normalized (0-1). + */ + public MutableQuadView square(Direction nominalFace, float left, float bottom, float right, float top, + float depth) { + if (Math.abs(depth) < CULL_FACE_EPSILON) { + cullFace(nominalFace); + depth = 0; // avoid any inconsistency for face quads + } else { + cullFace(null); + } + + nominalFace(nominalFace); + switch (nominalFace) { + case UP: + depth = 1 - depth; + top = 1 - top; + bottom = 1 - bottom; + // Fallthrough + + case DOWN: + pos(0, left, depth, top); + pos(1, left, depth, bottom); + pos(2, right, depth, bottom); + pos(3, right, depth, top); + break; + + case EAST: + depth = 1 - depth; + left = 1 - left; + right = 1 - right; + // Fallthrough + + case WEST: + pos(0, depth, top, left); + pos(1, depth, bottom, left); + pos(2, depth, bottom, right); + pos(3, depth, top, right); + break; + + case SOUTH: + depth = 1 - depth; + left = 1 - left; + right = 1 - right; + // Fallthrough + + case NORTH: + pos(0, 1 - left, top, depth); + pos(1, 1 - left, bottom, depth); + pos(2, 1 - right, bottom, depth); + pos(3, 1 - right, top, depth); + break; + } + + return this; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/quad/QuadView.java b/src/main/java/com/gregtechceu/gtceu/client/model/quad/QuadView.java new file mode 100644 index 00000000000..224930a8409 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/quad/QuadView.java @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gregtechceu.gtceu.client.model.quad; + +import com.gregtechceu.gtceu.client.util.quad.GeometryHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.Direction; +import net.minecraftforge.client.model.QuadTransformers; + +import lombok.Getter; +import lombok.experimental.Accessors; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnknownNullability; +import org.joml.Vector2f; +import org.joml.Vector3f; + +import static com.gregtechceu.gtceu.client.model.quad.EncodingFormat.*; + +/** + * Interface for reading quad data encoded by {@link MeshBuilder}. + * Enables models to do analysis, re-texturing or translation + * without knowing the renderer's vertex formats and without retaining redundant information. + * + * @implNote Base class for all quads / quad makers. Handles the ugly bits of maintaining and encoding the quad state. + */ +@Accessors(fluent = true, chain = true) +public class QuadView { + + /** + * See {@link MutableQuadView#nominalFace(Direction)}. + */ + @Getter + protected @Nullable Direction nominalFace; + /** True when geometry flags or light face may not match geometry. */ + protected boolean isGeometryInvalid = true; + protected final Vector3f faceNormal = new Vector3f(); + /** + * Equivalent to {@link BakedQuad#isShade()}. If false, quad should not have shadows cast on it. + * + * @see MutableQuadView#shade(boolean) + */ + @Getter + protected boolean shade = true; + /** + * Equivalent to {@link BakedQuad#hasAmbientOcclusion()}. If false, quad should not have AO. + * + * @see MutableQuadView#ambientOcclusion(boolean) + */ + @Getter + protected boolean ambientOcclusion = true; + /** + * The quad color index serialized with the quad. + */ + @Getter + protected int tintIndex; + + protected long headerFlags = 0; + /** + * Size and where it comes from will vary in subtypes. But in all cases quad is fully encoded to array. + * + * -- GETTER -- + * Reference to underlying array. Use with caution. Meant for fast renderer access + */ + @Getter + protected int @UnknownNullability [] data; + + /** Beginning of the quad. Also the header index. */ + protected int baseIndex = 0; + + /** + * Use when subtype is "attached" to a pre-existing array. Sets data reference and index and decodes state from + * array. + */ + final void load(int[] data, int baseIndex) { + this.data = data; + this.baseIndex = baseIndex; + load(); + } + + /** + * Like {@link #load(int[], int)} but assumes array and index already set. Only does the decoding part. + */ + public final void load() { + isGeometryInvalid = false; + nominalFace = lightFace(); + + // face normal isn't encoded + GeometryHelper.computeFaceNormal(faceNormal, this); + } + + public int normalFlags() { + return EncodingFormat.normalFlags(headerFlags); + } + + /** True if any vertex normal has been set. */ + public boolean hasVertexNormals() { + return normalFlags() != 0; + } + + @ApiStatus.Internal + public void computeGeometry() { + if (isGeometryInvalid) { + isGeometryInvalid = false; + + GeometryHelper.computeFaceNormal(faceNormal, this); + + // depends on face normal + headerFlags = EncodingFormat.lightFace(headerFlags, GeometryHelper.lightFace(this)); + } + } + + /** + * Equivalent to {@link BakedQuad#getDirection()}. This is the face used for vanilla lighting calculations and will + * be the block face to which the quad is most closely aligned. + * Always the same as cull face for quads that are on a block face, but never null. + */ + public final Direction lightFace() { + computeGeometry(); + return EncodingFormat.lightFace(headerFlags); + } + + /** + * If non-null, quad should not be rendered in-world if the opposite face of a neighbor block occludes it. + * + * @see MutableQuadView#cullFace(Direction) + */ + public final @Nullable Direction cullFace() { + computeGeometry(); + return EncodingFormat.cullFace(headerFlags); + } + + /** + * Normal of the quad as implied by geometry. Will be invalid if quad vertices are not co-planar. Typically computed + * lazily on demand and not encoded. + * + *

+ * Not typically needed by models. Exposed to enable standard lighting utility functions for use by renderers. + */ + public final Vector3f faceNormal() { + computeGeometry(); + return faceNormal; + } + + /** + * Extracts all quad properties except material to the given {@link MutableQuadView} instance. Must be used before + * calling {link QuadEmitter#emit()} on the target instance. Meant for re-texturing, analysis and static + * transformation use cases. + */ + @Contract(mutates = "param") + public void copyTo(MutableQuadView quad) { + computeGeometry(); + + // copy everything except the material + System.arraycopy(data, baseIndex, quad.data, quad.baseIndex, QUAD_STRIDE); + quad.faceNormal.set(faceNormal.x(), faceNormal.y(), faceNormal.z()); + quad.nominalFace = this.nominalFace; + quad.isGeometryInvalid = false; + quad.shade(this.shade); + quad.headerFlags = this.headerFlags; + } + + /** + * Returns the specified vertex's geometric position. + * + *

+ * Pass a non-null target to avoid allocation - will be returned with values. Otherwise, returns a new instance. + */ + @Contract(value = "_, !null -> param2; _, null -> new", mutates = "param2") + public Vector3f copyPos(int vertexIndex, @Nullable Vector3f target) { + if (target == null) { + target = new Vector3f(); + } + + final int index = baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X; + target.set(Float.intBitsToFloat(data[index]), Float.intBitsToFloat(data[index + 1]), + Float.intBitsToFloat(data[index + 2])); + return target; + } + + /** + * Returns the specified vertex's geometric position. + */ + @Contract(value = "_ -> new", pure = true) + public Vector3f copyPos(int vertexIndex) { + return copyPos(vertexIndex, null); + } + + /** + * Returns the specified vertex's normal vector. + * + *

+ * Pass a non-null target to avoid allocation - will be returned with values. Otherwise, returns a new instance. + * + *

+ * Returns null if normal not present. + */ + @Contract(value = "_, !null -> param2; _, null -> new", mutates = "param2") + public @Nullable Vector3f copyNormal(int vertexIndex, @Nullable Vector3f target) { + if (hasNormal(vertexIndex)) { + if (target == null) { + target = new Vector3f(); + } + + final int normal = data[normalIndex(vertexIndex)]; + target.set(GeometryHelper.getPackedNormalComponent(normal, 0), + GeometryHelper.getPackedNormalComponent(normal, 1), + GeometryHelper.getPackedNormalComponent(normal, 2)); + return target; + } else { + return null; + } + } + + /** + * Returns the specified vertex's normal vector. + * + *

+ * Returns null if normal not present. + */ + @Contract(value = "_ -> new", pure = true) + public @Nullable Vector3f copyNormal(int vertexIndex) { + return copyNormal(vertexIndex, null); + } + + /** + * Returns the specified vertex's UV coordinates. + * + *

+ * Pass a non-null target to avoid allocation - will be returned with values. Otherwise, returns a new instance. + */ + @Contract(value = "_, !null -> param2; _, null -> new", mutates = "param2") + public Vector2f copyUv(int vertexIndex, @Nullable Vector2f target) { + if (target == null) { + target = new Vector2f(); + } + + target.set(u(vertexIndex), v(vertexIndex)); + return target; + } + + /** + * Returns the specified vertex's UV coordinates. + */ + @Contract(value = "_ -> new", pure = true) + public Vector2f copyUv(int vertexIndex) { + return copyUv(vertexIndex, null); + } + + /** + * Retrieve geometric position, x coordinate. + */ + public float x(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X]); + } + + /** + * Retrieve geometric position, y coordinate. + */ + public float y(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_Y]); + } + + /** + * Retrieve geometric position, z coordinate. + */ + public float z(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_Z]); + } + + /** + * Retrieve vertex color. + */ + public int color(int vertexIndex) { + return data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_COLOR]; + } + + /** + * Convenience: access x, y, z by index 0-2. + */ + public float posByIndex(int vertexIndex, int coordinateIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_X + coordinateIndex]); + } + + /** + * If false, no vertex normal was provided. Lighting should use face normal in that case. + */ + public boolean hasNormal(int vertexIndex) { + return (normalFlags() & (1 << vertexIndex)) != 0; + } + + protected final int normalIndex(int vertexIndex) { + return baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_NORMAL; + } + + /** + * Will return {@link Float#NaN} if normal not present. + */ + public float normalX(int vertexIndex) { + return hasNormal(vertexIndex) ? GeometryHelper.getPackedNormalComponent(data[normalIndex(vertexIndex)], 0) : + Float.NaN; + } + + /** + * Will return {@link Float#NaN} if normal not present. + */ + public float normalY(int vertexIndex) { + return hasNormal(vertexIndex) ? GeometryHelper.getPackedNormalComponent(data[normalIndex(vertexIndex)], 1) : + Float.NaN; + } + + /** + * Will return {@link Float#NaN} if normal not present. + */ + public float normalZ(int vertexIndex) { + return hasNormal(vertexIndex) ? GeometryHelper.getPackedNormalComponent(data[normalIndex(vertexIndex)], 2) : + Float.NaN; + } + + /** + * Minimum block brightness. Zero if not set. + */ + public int lightmap(int vertexIndex) { + return data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_LIGHTMAP]; + } + + /** + * Retrieve horizontal texture coordinates. + */ + public float u(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_U]); + } + + /** + * Retrieve vertical texture coordinates. + */ + public float v(int vertexIndex) { + return Float.intBitsToFloat(data[baseIndex + vertexIndex * VERTEX_STRIDE + VERTEX_V]); + } + + /** + * Reads baked vertex data and outputs standard {@link BakedQuad#getVertices() baked quad vertex data} in the given + * array and location. + * + * @param target Target array for the baked quad data. + * + * @param targetIndex Starting position in target array - array must have at least 28 elements available at this + * index. + */ + public final void toVanilla(int[] target, int targetIndex) { + System.arraycopy(data, baseIndex, target, targetIndex, QUAD_STRIDE); + + int colorIndex = EncodingFormat.VERTEX_COLOR; + for (int i = 0; i < 4; i++) { + target[colorIndex] = QuadTransformers.toABGR(target[colorIndex]); + colorIndex += VERTEX_STRIDE; + } + } + + /** + * Generates a new BakedQuad instance with texture coordinates and colors from the given sprite. + * + * @param sprite {@link MutableQuadView} does not serialize sprites so the sprite must be provided by the caller. + * + * @return A new baked quad instance with the closest-available appearance supported by vanilla features. Will + * retain emissive light maps, for example, but the standard Minecraft renderer will not use them. + */ + public BakedQuad toBakedQuad(TextureAtlasSprite sprite) { + int[] vertexData = new int[QUAD_STRIDE]; + toVanilla(vertexData, 0); + return new BakedQuad(vertexData, tintIndex(), lightFace(), sprite, shade()); + } + + @SuppressWarnings("deprecation") + public BakedQuad toBlockBakedQuad() { + var finder = SpriteFinder.get(Minecraft.getInstance().getModelManager() + .getAtlas(TextureAtlas.LOCATION_BLOCKS)); + return toBakedQuad(finder.find(this)); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/quad/SpriteFinder.java b/src/main/java/com/gregtechceu/gtceu/client/model/quad/SpriteFinder.java new file mode 100644 index 00000000000..b77c1b59d64 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/quad/SpriteFinder.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gregtechceu.gtceu.client.model.quad; + +import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; + +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.Consumer; + +/** + * Indexes a texture atlas to allow fast lookup of Sprites from baked vertex coordinates. + * Main use is for {@link Mesh}-based models to generate vanilla quads on demand + * without tracking and retaining the sprites that were baked into the mesh. + * In other words, this class supplies the sprite parameter for + * {@link QuadView#toBakedQuad(TextureAtlasSprite)}. + * + * @implNote Implementation is a straightforward quad tree. + * Other options that were considered were linear search (slow) and direct indexing of fixed-size cells. + * Direct indexing would be fastest but would be memory-intensive for large atlases + * and unsuitable for any atlas that isn't consistently aligned to a fixed cell size. + */ +public class SpriteFinder { + + /** + * Retrieves or creates the finder for the given atlas. Instances should not be retained as fields or they must be + * refreshed whenever there is a resource reload or other event that causes atlas textures to be re-stitched. + */ + public static SpriteFinder get(TextureAtlas atlas) { + return ((SpriteFinderAccess) atlas).gtceu$spriteFinder(); + } + + private final Node root; + private final TextureAtlas textureAtlas; + + public SpriteFinder(Map sprites, TextureAtlas textureAtlas) { + root = new Node(0.5f, 0.5f, 0.25f); + this.textureAtlas = textureAtlas; + sprites.values().forEach(root::add); + } + + /** + * Finds the atlas sprite containing the vertex centroid of the quad. Vertex centroid is essentially the mean u,v + * coordinate - the intent being to find a point that is unambiguously inside the sprite (vs on an edge.) + * + *

+ * Should be reliable for any convex quad or triangle. May fail for non-convex quads. Note that all the above refers + * to u,v coordinates. Geometric vertex does not matter, except to the extent it was used to determine u,v. + */ + public TextureAtlasSprite find(QuadView quad) { + float u = 0; + float v = 0; + + for (int i = 0; i < 4; i++) { + u += quad.u(i); + v += quad.v(i); + } + + return find(u * 0.25f, v * 0.25f); + } + + /** + * Alternative to {@link #find(QuadView)} when vertex centroid is already known or unsuitable. + * Expects normalized (0-1) coordinates on the atlas texture, which should already be the case for u,v values + * in vanilla baked quads and in {@link QuadView} after calling + * {@link MutableQuadView#spriteBake(TextureAtlasSprite, int)}. + * + *

+ * Coordinates must be in the sprite interior for reliable results. + * Generally it'll be easier to use {@link #find(QuadView)} unless you know + * the vertex centroid will somehow not be in the quad interior. + * This method will be slightly faster if you already have the centroid or another appropriate value. + */ + public TextureAtlasSprite find(float u, float v) { + return root.find(u, v); + } + + private class Node { + + private final float midU; + private final float midV; + private final float cellRadius; + + private @Nullable Object lowLow = null; + private @Nullable Object lowHigh = null; + private @Nullable Object highLow = null; + private @Nullable Object highHigh = null; + + Node(float midU, float midV, float radius) { + this.midU = midU; + this.midV = midV; + cellRadius = radius; + } + + static final float EPS = Mth.EPSILON; + + void add(TextureAtlasSprite sprite) { + final boolean lowU = sprite.getU0() < midU - EPS; + final boolean highU = sprite.getU1() > midU + EPS; + final boolean lowV = sprite.getV0() < midV - EPS; + final boolean highV = sprite.getV1() > midV + EPS; + + if (lowU && lowV) { + addInner(sprite, lowLow, -1, -1, q -> lowLow = q); + } + + if (lowU && highV) { + addInner(sprite, lowHigh, -1, 1, q -> lowHigh = q); + } + + if (highU && lowV) { + addInner(sprite, highLow, 1, -1, q -> highLow = q); + } + + if (highU && highV) { + addInner(sprite, highHigh, 1, 1, q -> highHigh = q); + } + } + + private void addInner(TextureAtlasSprite sprite, @Nullable Object quadrant, int uStep, int vStep, + Consumer setter) { + if (quadrant == null) { + setter.accept(sprite); + } else if (quadrant instanceof Node node) { + node.add(sprite); + } else { + Node n = new Node(midU + cellRadius * uStep, midV + cellRadius * vStep, cellRadius * 0.5f); + + if (quadrant instanceof TextureAtlasSprite quadrantSprite) { + n.add(quadrantSprite); + } + + n.add(sprite); + setter.accept(n); + } + } + + private TextureAtlasSprite find(float u, float v) { + if (u < midU) { + return v < midV ? findInner(lowLow, u, v) : findInner(lowHigh, u, v); + } else { + return v < midV ? findInner(highLow, u, v) : findInner(highHigh, u, v); + } + } + + private TextureAtlasSprite findInner(@Nullable Object quadrant, float u, float v) { + if (quadrant instanceof TextureAtlasSprite sprite) { + return sprite; + } else if (quadrant instanceof Node node) { + return node.find(u, v); + } else { + return textureAtlas.getSprite(MissingTextureAtlasSprite.getLocation()); + } + } + } + + public interface SpriteFinderAccess { + + SpriteFinder gtceu$spriteFinder(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/StaticFaceBakery.java b/src/main/java/com/gregtechceu/gtceu/client/model/quad/StaticFaceBakery.java similarity index 99% rename from src/main/java/com/gregtechceu/gtceu/client/util/StaticFaceBakery.java rename to src/main/java/com/gregtechceu/gtceu/client/model/quad/StaticFaceBakery.java index 7b963ba6b52..43910d2f8c6 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/util/StaticFaceBakery.java +++ b/src/main/java/com/gregtechceu/gtceu/client/model/quad/StaticFaceBakery.java @@ -1,4 +1,4 @@ -package com.gregtechceu.gtceu.client.util; +package com.gregtechceu.gtceu.client.model.quad; import net.minecraft.client.renderer.FaceInfo; import net.minecraft.client.renderer.block.model.*; diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/quad/package-info.java b/src/main/java/com/gregtechceu/gtceu/client/model/quad/package-info.java new file mode 100644 index 00000000000..04eef27d2b2 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/quad/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.client.model.quad; + +import org.jetbrains.annotations.NotNullByDefault; diff --git a/src/main/java/com/gregtechceu/gtceu/client/model/quad/transform/QuadTransform.java b/src/main/java/com/gregtechceu/gtceu/client/model/quad/transform/QuadTransform.java new file mode 100644 index 00000000000..b604160adf5 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/model/quad/transform/QuadTransform.java @@ -0,0 +1,23 @@ +package com.gregtechceu.gtceu.client.model.quad.transform; + +import com.gregtechceu.gtceu.client.model.quad.MutableQuadView; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraftforge.client.model.IQuadTransformer; + +@FunctionalInterface +public interface QuadTransform extends IQuadTransformer { + + /** + * Return false to filter out quads from rendering. When more than one transform is in effect, returning false + * means unapplied transforms will not receive the quad. + */ + boolean transform(MutableQuadView quad); + + @Override + default void processInPlace(BakedQuad quad) { + MutableQuadView quadView = MutableQuadView.getInstance().fromVanilla(quad.getVertices(), 0); + this.transform(quadView); + quadView.toVanilla(quad.getVertices(), 0); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/FacadeCoverRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/FacadeCoverRenderer.java index 2d88b38e102..799fb61a06f 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/FacadeCoverRenderer.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/FacadeCoverRenderer.java @@ -3,9 +3,9 @@ import com.gregtechceu.gtceu.api.cover.CoverBehavior; import com.gregtechceu.gtceu.client.model.BaseBakedModel; import com.gregtechceu.gtceu.client.model.GTModelProperties; -import com.gregtechceu.gtceu.client.util.GTQuadTransformers; -import com.gregtechceu.gtceu.client.util.ModelUtils; -import com.gregtechceu.gtceu.client.util.StaticFaceBakery; +import com.gregtechceu.gtceu.client.model.quad.StaticFaceBakery; +import com.gregtechceu.gtceu.client.util.RenderUtil; +import com.gregtechceu.gtceu.client.util.quad.transformers.GTQuadTransformers; import com.gregtechceu.gtceu.common.cover.FacadeCover; import com.gregtechceu.gtceu.common.item.behavior.FacadeItemBehaviour; import com.gregtechceu.gtceu.utils.GTUtil; @@ -127,7 +127,7 @@ public void renderCover(List quads, @Nullable Direction side, RandomS return; } - BakedModel facadeModel = ModelUtils.getModelForState(facadeState); + BakedModel facadeModel = RenderUtil.getModelForState(facadeState); if (facadeModel.isCustomRenderer()) { return; } @@ -187,7 +187,7 @@ public ModelData getModelData(CoverBehavior coverBehavior, BlockPos pos, BlockAn return ModelData.EMPTY; } - BakedModel facadeModel = ModelUtils.getModelForState(facadeState); + BakedModel facadeModel = RenderUtil.getModelForState(facadeState); return facadeModel.getModelData(level, pos, facadeState, holderModelData); } @@ -202,7 +202,7 @@ public ChunkRenderTypeSet getRenderTypes(CoverBehavior coverBehavior, BlockPos p return ChunkRenderTypeSet.none(); } - BakedModel facadeModel = ModelUtils.getModelForState(facadeState); + BakedModel facadeModel = RenderUtil.getModelForState(facadeState); return facadeModel.getRenderTypes(facadeState, rand, modelData); } @@ -285,7 +285,7 @@ public List getQuads(@Nullable BlockState state, @Nullable Direction if (facadeState.getRenderShape() != RenderShape.MODEL) { return quads; } - BakedModel facadeModel = ModelUtils.getModelForState(facadeState); + BakedModel facadeModel = RenderUtil.getModelForState(facadeState); if (facadeModel.isCustomRenderer()) { return quads; } @@ -340,7 +340,7 @@ public List getQuads(@Nullable BlockState state, @Nullable Direction public ModelData getModelData(BlockAndTintGetter level, BlockPos pos, BlockState state, ModelData modelData) { return super.getModelData(level, pos, state, modelData).derive() .with(GTModelProperties.CHILD_MODEL_DATA, - ModelUtils.getModelForState(facadeState).getModelData(level, pos, state, modelData)) + RenderUtil.getModelForState(facadeState).getModelData(level, pos, state, modelData)) .build(); } @@ -348,7 +348,7 @@ public ModelData getModelData(BlockAndTintGetter level, BlockPos pos, BlockState public List getRenderTypes(ItemStack stack, boolean fabulous) { List renderTypes = new ArrayList<>(); - BakedModel facadeModel = ModelUtils.getModelForState(this.facadeState); + BakedModel facadeModel = RenderUtil.getModelForState(this.facadeState); for (var model : facadeModel.getRenderPasses(stack, fabulous)) { renderTypes.addAll(model.getRenderTypes(this.facadeStack, fabulous)); } diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/ICoverableRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/ICoverableRenderer.java index 489f4e43e0c..2469b6ab994 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/ICoverableRenderer.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/ICoverableRenderer.java @@ -5,8 +5,8 @@ import com.gregtechceu.gtceu.api.cover.CoverBehavior; import com.gregtechceu.gtceu.api.machine.MetaMachine; import com.gregtechceu.gtceu.client.model.GTModelProperties; +import com.gregtechceu.gtceu.client.model.quad.StaticFaceBakery; import com.gregtechceu.gtceu.client.util.RenderUtil; -import com.gregtechceu.gtceu.client.util.StaticFaceBakery; import com.gregtechceu.gtceu.utils.GTUtil; import net.minecraft.client.renderer.MultiBufferSource; diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/IOCoverRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/IOCoverRenderer.java index 28f0c8d5cc9..5c8fd4da25d 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/IOCoverRenderer.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/IOCoverRenderer.java @@ -4,8 +4,8 @@ import com.gregtechceu.gtceu.api.capability.recipe.IO; import com.gregtechceu.gtceu.api.cover.CoverBehavior; import com.gregtechceu.gtceu.api.cover.IIOCover; -import com.gregtechceu.gtceu.client.util.ModelUtils; -import com.gregtechceu.gtceu.client.util.StaticFaceBakery; +import com.gregtechceu.gtceu.client.model.quad.StaticFaceBakery; +import com.gregtechceu.gtceu.client.util.ModelEventHelper; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; @@ -46,7 +46,7 @@ public IOCoverRenderer(@Nullable ResourceLocation overlay, @Nullable ResourceLocation invertedOverlay, @Nullable ResourceLocation emissiveOverlay, @Nullable ResourceLocation invertedEmissiveOverlay) { - ModelUtils.registerAtlasStitchedEventListener(false, InventoryMenu.BLOCK_ATLAS, event -> { + ModelEventHelper.registerAtlasStitchedEventListener(false, InventoryMenu.BLOCK_ATLAS, event -> { var atlas = event.getAtlas(); if (overlay != null) { diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/SimpleCoverRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/SimpleCoverRenderer.java index 472597cafcd..c9acfcd6477 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/SimpleCoverRenderer.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/SimpleCoverRenderer.java @@ -1,8 +1,8 @@ package com.gregtechceu.gtceu.client.renderer.cover; import com.gregtechceu.gtceu.api.cover.CoverBehavior; -import com.gregtechceu.gtceu.client.util.ModelUtils; -import com.gregtechceu.gtceu.client.util.StaticFaceBakery; +import com.gregtechceu.gtceu.client.model.quad.StaticFaceBakery; +import com.gregtechceu.gtceu.client.util.ModelEventHelper; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; @@ -34,7 +34,7 @@ public SimpleCoverRenderer(ResourceLocation texture) { } public SimpleCoverRenderer(ResourceLocation texture, ResourceLocation emissiveTexture) { - ModelUtils.registerAtlasStitchedEventListener(false, InventoryMenu.BLOCK_ATLAS, event -> { + ModelEventHelper.registerAtlasStitchedEventListener(false, InventoryMenu.BLOCK_ATLAS, event -> { var atlas = event.getAtlas(); sprite = atlas.getSprite(texture); diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/machine/impl/BoilerMultiPartRender.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/machine/impl/BoilerMultiPartRender.java index dc4dcd9b5c4..f450e986b41 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/machine/impl/BoilerMultiPartRender.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/machine/impl/BoilerMultiPartRender.java @@ -8,7 +8,7 @@ import com.gregtechceu.gtceu.client.model.machine.IControllerModelRenderer; import com.gregtechceu.gtceu.client.renderer.machine.DynamicRender; import com.gregtechceu.gtceu.client.renderer.machine.DynamicRenderType; -import com.gregtechceu.gtceu.client.util.ModelUtils; +import com.gregtechceu.gtceu.client.util.RenderUtil; import com.gregtechceu.gtceu.common.block.BoilerFireboxType; import com.gregtechceu.gtceu.common.data.GTBlocks; @@ -96,13 +96,13 @@ public void renderPartModel(List quads, MultiblockControllerMachine c Direction frontFacing, @Nullable Direction side, RandomSource rand, @NotNull ModelData modelData, @Nullable RenderType renderType) { if (this.fireboxIdleModel == null) { - this.fireboxIdleModel = ModelUtils.getModelForState(fireboxIdle); + this.fireboxIdleModel = RenderUtil.getModelForState(fireboxIdle); } if (this.fireboxActiveModel == null) { - this.fireboxActiveModel = ModelUtils.getModelForState(fireboxActive); + this.fireboxActiveModel = RenderUtil.getModelForState(fireboxActive); } if (this.casingModel == null) { - this.casingModel = ModelUtils.getModelForState(casing); + this.casingModel = RenderUtil.getModelForState(casing); } BlockPos partPos = part.self().getBlockPos(); diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/AssetEventListener.java b/src/main/java/com/gregtechceu/gtceu/client/util/AssetEventListener.java index eb035bf4ed0..ffdc9caed12 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/util/AssetEventListener.java +++ b/src/main/java/com/gregtechceu/gtceu/client/util/AssetEventListener.java @@ -1,5 +1,9 @@ package com.gregtechceu.gtceu.client.util; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelBakery; +import net.minecraft.client.resources.model.UnbakedModel; +import net.minecraft.resources.ResourceLocation; import net.minecraftforge.client.event.ModelEvent; import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.eventbus.api.Event; @@ -15,6 +19,7 @@ public interface AssetEventListener { return null; } + @FunctionalInterface interface AtlasStitched extends AssetEventListener { @Override @@ -24,15 +29,14 @@ default Class eventClass() { } } - interface ModifyBakingResult extends AssetEventListener { + @FunctionalInterface + interface BakedModelReplacement { - @Override - @Nullable - default Class eventClass() { - return ModelEvent.ModifyBakingResult.class; - } + BakedModel modifyBakedModel(ResourceLocation modelLocation, BakedModel model, + @Nullable UnbakedModel rootModel, ModelBakery modelBakery); } + @FunctionalInterface interface RegisterAdditional extends AssetEventListener { @Override diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/ModelEventHelper.java b/src/main/java/com/gregtechceu/gtceu/client/util/ModelEventHelper.java new file mode 100644 index 00000000000..bb616bf300c --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/util/ModelEventHelper.java @@ -0,0 +1,229 @@ +package com.gregtechceu.gtceu.client.util; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.client.model.ctm.CTMBakedModel; +import com.gregtechceu.gtceu.client.model.machine.MachineModel; +import com.gregtechceu.gtceu.client.renderer.cover.ICoverableRenderer; +import com.gregtechceu.gtceu.core.mixins.ReloadableResourceManagerAccessor; +import com.gregtechceu.gtceu.integration.modernfix.GTModernFixIntegration; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.*; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManagerReloadListener; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.ModelEvent; +import net.minecraftforge.client.event.RegisterClientReloadListenersEvent; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import it.unimi.dsi.fastutil.objects.Object2BooleanMap; +import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.ApiStatus; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +@SuppressWarnings("deprecation") +@UtilityClass +@Mod.EventBusSubscriber(modid = GTCEu.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public class ModelEventHelper { + + @ApiStatus.Internal + public record EventListenerHolder(T listener, boolean removeOnReload) {} + + @ApiStatus.Internal + public static final List> EVENT_LISTENERS = new ArrayList<>(); + @ApiStatus.Internal + public static final Map CTM_SPRITE_CACHE = new ConcurrentHashMap<>(); + + private static final Multimap SCRAPED_TEXTURES = HashMultimap.create(); + private static final Object2BooleanMap WRAPPED_MODELS = new Object2BooleanOpenHashMap<>(); + + @ApiStatus.Internal + public static void markTextureUsedForModel(ResourceLocation modelLocation, Material material) { + SCRAPED_TEXTURES.put(modelLocation, material); + } + + public static void registerAtlasStitchedEventListener(boolean removeOnReload, + AssetEventListener.AtlasStitched listener) { + EVENT_LISTENERS.add(new EventListenerHolder<>(listener, removeOnReload)); + } + + public static void registerAtlasStitchedEventListener(boolean removeOnReload, final ResourceLocation atlasLocation, + final AssetEventListener.AtlasStitched listener) { + registerAtlasStitchedEventListener(removeOnReload, event -> { + if (event.getAtlas().location().equals(atlasLocation)) { + listener.accept(event); + } + }); + } + + public static void registerBakeEventListener(boolean removeOnReload, + AssetEventListener.BakedModelReplacement listener) { + EVENT_LISTENERS.add(new EventListenerHolder<>(listener, removeOnReload)); + } + + public static void registerAddModelsEventListener(boolean removeOnReload, + AssetEventListener.RegisterAdditional listener) { + EVENT_LISTENERS.add(new EventListenerHolder<>(listener, removeOnReload)); + } + + private static final AtomicInteger reloadCounter = new AtomicInteger(0); + + @SubscribeEvent(priority = EventPriority.HIGH) + public static void registerReloadListener(RegisterClientReloadListenersEvent event) { + ((ReloadableResourceManagerAccessor) Minecraft.getInstance().getResourceManager()).getListeners() + .add(0, (ResourceManagerReloadListener) resourceManager -> { + if (reloadCounter.addAndGet(1) > 1) { + EVENT_LISTENERS.removeIf(EventListenerHolder::removeOnReload); + } + + CTM_SPRITE_CACHE.clear(); + WRAPPED_MODELS.clear(); + SCRAPED_TEXTURES.clear(); + TextureMetadataHelper.invalidateCaches(); + }); + } + + @SuppressWarnings("unchecked") + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void onAtlasStitched(TextureStitchEvent.Post event) { + for (var listener : EVENT_LISTENERS) { + if (!(listener.listener instanceof AssetEventListener assetEventListener)) continue; + + Class eventClass = assetEventListener.eventClass(); + if (eventClass != null && eventClass.isInstance(event)) { + ((AssetEventListener) listener.listener).accept(event); + } + } + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void onModifyBakingResult(ModelEvent.ModifyBakingResult event) { + // don't process baked model replacement here if ModernFix is loaded & dynamic resources is enabled + if (GTCEu.Mods.isModernFixLoaded() && GTModernFixIntegration.isDynamicResourcesEnabled()) return; + + for (var entry : event.getModels().entrySet()) { + BakedModel model = entry.getValue(); + + // process all model replacers + for (var listener : EVENT_LISTENERS) { + if (!(listener.listener instanceof AssetEventListener.BakedModelReplacement modelReplacement)) continue; + model = modelReplacement.modifyBakedModel(entry.getKey(), model, + event.getModelBakery().getModel(entry.getKey()), event.getModelBakery()); + } + entry.setValue(model); + } + } + + @SuppressWarnings("unchecked") + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void onRegisterAdditional(ModelEvent.RegisterAdditional event) { + for (var listener : EVENT_LISTENERS) { + if (!(listener.listener instanceof AssetEventListener assetEventListener)) continue; + + Class eventClass = assetEventListener.eventClass(); + if (eventClass != null && eventClass.isInstance(event)) { + ((AssetEventListener) listener.listener).accept(event); + } + } + } + + // INTERNAL ASSET RELOAD LISTENER REGISTRATION + + @ApiStatus.Internal + public static void initInternalAssetReloadListeners() { + registerAtlasStitchedEventListener(false, TextureAtlas.LOCATION_BLOCKS, event -> { + TextureAtlas atlas = event.getAtlas(); + // Cache all textures' CTM metadata + // TODO lazy + for (ResourceLocation location : atlas.getTextureLocations()) { + var sec = TextureMetadataHelper.getMetadataFromRelativeLocation(location); + sec.ifPresent(section -> { + if (section.connectionTexture() != null) { + TextureAtlasSprite ctmSprite = atlas.getSprite(section.connectionTexture()); + CTM_SPRITE_CACHE.put(location, ctmSprite); + } + }); + } + + MachineModel.initSprites(atlas); + ICoverableRenderer.initSprites(atlas); + }); + + // register CTM model wrapper + ModelEventHelper.registerBakeEventListener(false, (rl, baked, rootModel, modelBakery) -> { + if (baked.isCustomRenderer()) { + // Nothing we can add to builtin models + return baked; + } + // do not register automatic CTM for machine models, they handle it themselves + if (baked instanceof MachineModel) { + return baked; + } + + if (!(rl instanceof ModelResourceLocation) || rootModel == null || baked instanceof CTMBakedModel) { + return baked; + } + Deque dependencies = new ArrayDeque<>(); + Set seenModels = new HashSet<>(); + dependencies.push(rl); + seenModels.add(rl); + + boolean shouldWrap = WRAPPED_MODELS.getOrDefault(rl, false); + if (WRAPPED_MODELS.containsKey(rl)) { + // shortcut if the model's already been checked + if (shouldWrap) return new CTMBakedModel<>(baked); + else return baked; + } + // Breadth-first loop through dependencies + // exiting as soon as a CTM texture is found, and skipping duplicates/cycles + PARENT_LOOP: + while (!shouldWrap && !dependencies.isEmpty()) { + ResourceLocation dependencyName = dependencies.pop(); + UnbakedModel unbaked; + try { + unbaked = dependencyName == rl ? rootModel : modelBakery.getModel(dependencyName); + } catch (Exception e) { + continue; + } + try { + // have to copy because the set is updated during this loop + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + Set textures = new HashSet<>(SCRAPED_TEXTURES.get(dependencyName)); + for (Material tex : textures) { + if (TextureMetadataHelper.getMetadata(tex).isPresent()) { + // At least one texture has CTM metadata, so we should wrap this model + shouldWrap = true; + break PARENT_LOOP; + } + } + // shouldWrap is always false here because of the `break` above + for (ResourceLocation newDep : unbaked.getDependencies()) { + if (seenModels.add(newDep)) { + dependencies.push(newDep); + } + } + } catch (Exception e) { + GTCEu.LOGGER.error("Error loading dependency {} for model {}. Skipping...", + dependencyName, rl, e); + } + } + ModelEventHelper.WRAPPED_MODELS.put(rl, shouldWrap); + if (shouldWrap) { + return new CTMBakedModel<>(baked); + } + + return baked; + }); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/ModelUtils.java b/src/main/java/com/gregtechceu/gtceu/client/util/ModelUtils.java deleted file mode 100644 index 8568412da98..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/client/util/ModelUtils.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.gregtechceu.gtceu.client.util; - -import com.gregtechceu.gtceu.GTCEu; -import com.gregtechceu.gtceu.client.model.machine.MachineModel; -import com.gregtechceu.gtceu.client.renderer.cover.ICoverableRenderer; -import com.gregtechceu.gtceu.integration.modernfix.GTModernFixIntegration; - -import com.lowdragmc.lowdraglib.client.model.custommodel.CustomBakedModel; - -import net.minecraft.ChatFormatting; -import net.minecraft.Util; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.texture.TextureAtlas; -import net.minecraft.client.resources.model.*; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.server.packs.resources.ResourceManagerReloadListener; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.Property; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.ModelEvent; -import net.minecraftforge.client.event.RegisterClientReloadListenersEvent; -import net.minecraftforge.client.event.TextureStitchEvent; -import net.minecraftforge.client.model.data.ModelData; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; - -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -@Mod.EventBusSubscriber(modid = GTCEu.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) -public class ModelUtils { - - private ModelUtils() {} - - private static final List EVENT_LISTENERS = new ArrayList<>(); - - public static List getBakedModelQuads(BakedModel model, BlockAndTintGetter level, BlockPos pos, - BlockState state, Direction side, RandomSource rand) { - return model.getQuads(state, side, rand, model.getModelData(level, pos, state, ModelData.EMPTY), null); - } - - public static BakedModel getModelForState(BlockState state) { - return Minecraft.getInstance().getBlockRenderer().getBlockModel(state); - } - - public static String getPropertyValueString(Map.Entry, Comparable> entry) { - Property property = entry.getKey(); - Comparable value = entry.getValue(); - - String valueString = Util.getPropertyName(property, value); - if (Boolean.TRUE.equals(value)) { - valueString = ChatFormatting.GREEN + valueString; - } else if (Boolean.FALSE.equals(value)) { - valueString = ChatFormatting.RED + valueString; - } - - return property.getName() + ": " + valueString; - } - - public static void registerAtlasStitchedEventListener(boolean removeOnReload, - AssetEventListener.AtlasStitched listener) { - EVENT_LISTENERS.add(new EventListenerHolder(listener, removeOnReload)); - } - - public static void registerAtlasStitchedEventListener(boolean removeOnReload, final ResourceLocation atlasLocation, - final AssetEventListener.AtlasStitched listener) { - registerAtlasStitchedEventListener(removeOnReload, event -> { - if (event.getAtlas().location().equals(atlasLocation)) { - listener.accept(event); - } - }); - } - - public static void registerBakeEventListener(boolean removeOnReload, - AssetEventListener.ModifyBakingResult listener) { - EVENT_LISTENERS.add(new EventListenerHolder(listener, removeOnReload)); - } - - public static void registerAddModelsEventListener(boolean removeOnReload, - AssetEventListener.RegisterAdditional listener) { - EVENT_LISTENERS.add(new EventListenerHolder(listener, removeOnReload)); - } - - @SubscribeEvent(priority = EventPriority.HIGH) - public static void registerReloadListener(RegisterClientReloadListenersEvent event) { - event.registerReloadListener(new ResourceManagerReloadListener() { - - @Override - public void onResourceManagerReload(@NotNull ResourceManager resourceManager) { - EVENT_LISTENERS.removeIf(EventListenerHolder::removeOnReload); - } - }); - } - - @SuppressWarnings({ "unchecked", "deprecation" }) - @SubscribeEvent(priority = EventPriority.LOWEST) - public static void onAtlasStitched(TextureStitchEvent.Post event) { - TextureAtlas atlas = event.getAtlas(); - if (atlas.location() == TextureAtlas.LOCATION_BLOCKS) { - MachineModel.initSprites(atlas); - ICoverableRenderer.initSprites(atlas); - } - - for (var listener : EVENT_LISTENERS) { - Class eventClass = listener.listener.eventClass(); - if (eventClass != null && eventClass.isInstance(event)) { - ((AssetEventListener) listener.listener).accept(event); - } - } - } - - @SuppressWarnings("unchecked") - @SubscribeEvent(priority = EventPriority.LOWEST) - public static void onModifyBakingResult(ModelEvent.ModifyBakingResult event) { - for (var listener : EVENT_LISTENERS) { - Class eventClass = listener.listener.eventClass(); - if (eventClass != null && eventClass.isInstance(event)) { - ((AssetEventListener) listener.listener).accept(event); - } - } - - // don't process the CTM model unwrapping here if modernfix dynamic resources is enabled - if (GTCEu.Mods.isModernFixLoaded() && GTModernFixIntegration.isDynamicResourcesEnabled()) return; - - // Unwrap all machine models from LDLib CTM models so we don't need to be as aggressive with mixins - // Also, the caching they have stops our models from updating properly - for (var entry : event.getModels().entrySet()) { - BakedModel model = entry.getValue(); - if (!(model instanceof CustomBakedModel ctmModel)) { - continue; - } - if (ctmModel.getParent() instanceof MachineModel machine) { - entry.setValue(machine); - } - } - } - - @SuppressWarnings("unchecked") - @SubscribeEvent(priority = EventPriority.LOWEST) - public static void onRegisterAdditional(ModelEvent.RegisterAdditional event) { - for (var listener : EVENT_LISTENERS) { - Class eventClass = listener.listener.eventClass(); - if (eventClass != null && eventClass.isInstance(event)) { - ((AssetEventListener) listener.listener).accept(event); - } - } - } - - private record EventListenerHolder(AssetEventListener listener, boolean removeOnReload) {} -} diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/RenderUtil.java b/src/main/java/com/gregtechceu/gtceu/client/util/RenderUtil.java index f1dec39d941..2fe929c0818 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/util/RenderUtil.java +++ b/src/main/java/com/gregtechceu/gtceu/client/util/RenderUtil.java @@ -216,6 +216,10 @@ public static void moveToFace(PoseStack poseStack, float x, float y, float z, Di Math.fma(face.getStepZ(), 0.5f, z)); } + public static BakedModel getModelForState(BlockState state) { + return Minecraft.getInstance().getBlockRenderer().getBlockModel(state); + } + public static void drawBlock(BlockAndTintGetter level, BlockPos pos, BlockState state, MultiBufferSource bufferSource, PoseStack poseStack) { int packedLight = LevelRenderer.getLightColor(level, state, pos); diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/SpriteFunctionWrapper.java b/src/main/java/com/gregtechceu/gtceu/client/util/SpriteFunctionWrapper.java new file mode 100644 index 00000000000..452b46b9540 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/util/SpriteFunctionWrapper.java @@ -0,0 +1,28 @@ +package com.gregtechceu.gtceu.client.util; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.Material; +import net.minecraft.resources.ResourceLocation; + +import java.util.function.Function; + +public class SpriteFunctionWrapper implements Function { + + private final Function internal; + private final ResourceLocation modelLocation; + + public SpriteFunctionWrapper(Function internal, ResourceLocation modelLocation) { + if (internal instanceof SpriteFunctionWrapper wrapper) { + this.internal = wrapper.internal; + } else { + this.internal = internal; + } + this.modelLocation = modelLocation; + } + + @Override + public TextureAtlasSprite apply(Material material) { + ModelEventHelper.markTextureUsedForModel(this.modelLocation, material); + return internal.apply(material); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/TextureHelper.java b/src/main/java/com/gregtechceu/gtceu/client/util/TextureHelper.java new file mode 100644 index 00000000000..facecba1cfb --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/util/TextureHelper.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gregtechceu.gtceu.client.util; + +import com.gregtechceu.gtceu.client.model.quad.MutableQuadView; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.Direction; + +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.Nullable; + +import static com.gregtechceu.gtceu.client.model.quad.MutableQuadView.*; + +/** + * Handles most texture-baking use cases for model loaders and model libraries via + * {@link #bakeSprite(MutableQuadView, TextureAtlasSprite, int)}. + */ +@UtilityClass +public class TextureHelper { + + public static final float NORMALIZER = 1f / 16f; + public static final float DENORMALIZER = 16f; + + private static final int BAKE_ROTATE_ANY = BAKE_ROTATE_270 | BAKE_ROTATE_180 | BAKE_ROTATE_90; + + /** + * Bakes textures in the provided vertex data, handling UV locking, rotation, interpolation, etc. + * Textures must not be already baked. + * + *

+ * If {@code sprite == null}, only the UV modifiers will be applied, + * but they won't be translated to the sprite's atlas coordinates. + * + * @see #unbakeSprite(MutableQuadView, TextureAtlasSprite, int) + * @see MutableQuadView#BAKE_ROTATE_NONE bake flags + */ + public static void bakeSprite(MutableQuadView quad, @Nullable TextureAtlasSprite sprite, int bakeFlags) { + if (quad.nominalFace() != null && (BAKE_LOCK_UV & bakeFlags) != 0) { + // Assigns normalized UV coordinates based on vertex positions + applyModifier(quad, UV_LOCKERS[quad.nominalFace().get3DDataValue()]); + } else if ((BAKE_NORMALIZED & bakeFlags) == 0) { + // flag is NOT set, UVs are assumed to not be normalized yet as is the default. + // normalize through dividing by 16 + + // Scales from 0-16 to 0-1 + applyModifier(quad, (q, i) -> q.uv(i, q.u(i) * NORMALIZER, q.v(i) * NORMALIZER)); + } + + final int rotation = bakeFlags & BAKE_ROTATE_ANY; + + if (rotation != 0) { + // Rotates texture around the center of sprite. + // Assumes normalized coordinates. + applyModifier(quad, ROTATIONS[rotation]); + } + + if ((BAKE_FLIP_U & bakeFlags) != 0) { + // Inverts U coordinates. Assumes normalized (0-1) values. + applyModifier(quad, (q, i) -> q.uv(i, 1 - q.u(i), q.v(i))); + } + + if ((BAKE_FLIP_V & bakeFlags) != 0) { + // Inverts V coordinates. Assumes normalized (0-1) values. + applyModifier(quad, (q, i) -> q.uv(i, q.u(i), 1 - q.v(i))); + } + + if (sprite != null) { + interpolate(quad, sprite); + } + } + + /** + * Faster than sprite method. Sprite computes span and normalizes inputs each call, so we'd have to denormalize + * before we called, only to have the sprite renormalize immediately. + */ + public static void interpolate(MutableQuadView q, TextureAtlasSprite sprite) { + final float uMin = sprite.getU0(); + final float uSpan = sprite.getU1() - uMin; + final float vMin = sprite.getV0(); + final float vSpan = sprite.getV1() - vMin; + + for (int i = 0; i < 4; i++) { + q.uv(i, uMin + q.u(i) * uSpan, vMin + q.v(i) * vSpan); + } + } + + /** + * The reverse operation of {@link #bakeSprite}. Undoes the same operations except UV locking. + * Textures must be already baked. + * + *

+ * Note this the function's order of operations is reversed in relation to {@link #bakeSprite}.
+ * The {@link MutableQuadView#BAKE_NORMALIZED BAKE_NORMALIZED} flag also works inversely + * to the one in {@link #bakeSprite}. + * + *

+ * If {@code sprite == null}, only the UV modifiers will be applied, + * but they won't be translated from the sprite's atlas coordinates to a 0-16 range. + * + * @see #bakeSprite(MutableQuadView, TextureAtlasSprite, int) + * @see MutableQuadView#BAKE_ROTATE_NONE bake flags + */ + public static void unbakeSprite(MutableQuadView quad, @Nullable TextureAtlasSprite sprite, int bakeFlags) { + if (sprite != null) { + deInterpolate(quad, sprite); + } + + if ((BAKE_FLIP_V & bakeFlags) != 0) { + // Inverts V coordinates. Assumes normalized (0-1) values. + applyModifier(quad, (q, i) -> q.uv(i, q.u(i), 1 - q.v(i))); + } + + if ((BAKE_FLIP_U & bakeFlags) != 0) { + // Inverts U coordinates. Assumes normalized (0-1) values. + applyModifier(quad, (q, i) -> q.uv(i, 1 - q.u(i), q.v(i))); + } + + final int rotation = bakeFlags & BAKE_ROTATE_ANY; + + if (rotation != 0) { + // Rotates texture around the center of sprite. + // Assumes normalized coordinates. + applyModifier(quad, ROTATIONS[rotation]); + } + + if ((BAKE_NORMALIZED & bakeFlags) == 0) { + // flag is NOT set, UVs are assumed to be normalized as is the default. + // denormalize through multiplying by 16 + + // Scales from 0-1 to 0-16 + applyModifier(quad, (q, i) -> q.uv(i, q.u(i) * DENORMALIZER, q.v(i) * DENORMALIZER)); + } + if ((BAKE_DEROTATE_UV & bakeFlags) != 0) { + // Cycles texture coordinates so that vertex 0's UVs are the smallest + derotateUV(quad); + } + } + + /** + * Faster than sprite method. Sprite computes span and normalizes inputs each call, so we'd have to denormalize + * before we called, only to have the sprite renormalize immediately. + */ + public static void deInterpolate(MutableQuadView q, TextureAtlasSprite sprite) { + final float uMin = sprite.getU0(); + final float uSpan = sprite.getU1() - uMin; + final float vMin = sprite.getV0(); + final float vSpan = sprite.getV1() - vMin; + + for (int i = 0; i < 4; i++) { + q.uv(i, (q.u(i) - uMin) / uSpan, (q.v(i) - vMin) / vSpan); + } + } + + private static void derotateUV(MutableQuadView quad) { + int minIndex = 0; + float minU = Float.MAX_VALUE, minV = Float.MAX_VALUE; + + for (int i = 0; i < 4; i++) { + if (quad.u(i) <= minU && quad.v(i) <= minV) { + minIndex = i; + minU = quad.u(i); + minV = quad.v(i); + } + } + applyModifier(quad, ROTATIONS[minIndex]); + } + + @FunctionalInterface + public interface VertexModifier { + + void apply(MutableQuadView quad, int vertexIndex); + } + + private static void applyModifier(MutableQuadView quad, VertexModifier modifier) { + for (int i = 0; i < 4; i++) { + modifier.apply(quad, i); + } + } + + private static final VertexModifier[] ROTATIONS = new VertexModifier[] { + (q, i) -> {}, // 0 + (q, i) -> q.uv(i, q.v(i), 1 - q.u(i)), // 90 + (q, i) -> q.uv(i, 1 - q.u(i), 1 - q.v(i)), // 180 + (q, i) -> q.uv(i, 1 - q.v(i), q.u(i)) // 270 + }; + + private static final VertexModifier[] UV_LOCKERS = new VertexModifier[6]; + + static { + UV_LOCKERS[Direction.EAST.get3DDataValue()] = (q, i) -> q.uv(i, 1 - q.z(i), 1 - q.y(i)); + UV_LOCKERS[Direction.WEST.get3DDataValue()] = (q, i) -> q.uv(i, q.z(i), 1 - q.y(i)); + UV_LOCKERS[Direction.NORTH.get3DDataValue()] = (q, i) -> q.uv(i, 1 - q.x(i), 1 - q.y(i)); + UV_LOCKERS[Direction.SOUTH.get3DDataValue()] = (q, i) -> q.uv(i, q.x(i), 1 - q.y(i)); + UV_LOCKERS[Direction.DOWN.get3DDataValue()] = (q, i) -> q.uv(i, q.x(i), 1 - q.z(i)); + UV_LOCKERS[Direction.UP.get3DDataValue()] = (q, i) -> q.uv(i, q.x(i), q.z(i)); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/TextureMetadataHelper.java b/src/main/java/com/gregtechceu/gtceu/client/util/TextureMetadataHelper.java new file mode 100644 index 00000000000..9ed03e35404 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/util/TextureMetadataHelper.java @@ -0,0 +1,67 @@ +package com.gregtechceu.gtceu.client.util; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.client.model.ctm.GTTextureMetadata; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.Material; +import net.minecraft.resources.ResourceLocation; + +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +@UtilityClass +public class TextureMetadataHelper { + + private static final Map metadataCache = new HashMap<>(); + + public static Optional getMetadata(ResourceLocation res) { + // Note, semantically different from computeIfAbsent, as we DO care about keys mapped to null values + if (metadataCache.containsKey(res)) { + return Optional.ofNullable(metadataCache.get(res)); + } + Optional ret; + try { + ret = Minecraft.getInstance().getResourceManager().getResource(res) + .flatMap(GTTextureMetadata::getForResourceUnsafe); + } catch (Exception e) { + // the real exception that's caught should always be an IOException, + // but @SneakyThrows hides that from us so we catch all exceptions instead. + ret = Optional.empty(); + GTCEu.LOGGER.error("Error loading metadata for location {}", res, e); + } + ret.ifPresentOrElse(r -> metadataCache.put(res, r), () -> metadataCache.put(res, null)); + return ret; + } + + public static Optional getMetadata(TextureAtlasSprite sprite) { + return getMetadata(spriteToAbsolute(sprite.contents().name())); + } + + public static Optional getMetadata(Material material) { + return getMetadata(spriteToAbsolute(material.texture())); + } + + public static Optional getMetadataFromRelativeLocation(ResourceLocation relativeLocation) { + return getMetadata(spriteToAbsolute(relativeLocation)); + } + + public static ResourceLocation spriteToAbsolute(ResourceLocation sprite) { + if (!sprite.getPath().startsWith("textures/")) { + sprite = sprite.withPrefix("textures/"); + } + if (!sprite.getPath().endsWith(".png")) { + sprite = sprite.withSuffix(".png"); + } + return sprite; + } + + static void invalidateCaches() { + metadataCache.clear(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/package-info.java b/src/main/java/com/gregtechceu/gtceu/client/util/package-info.java new file mode 100644 index 00000000000..1bc08b04b82 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/util/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.client.util; + +import org.jetbrains.annotations.NotNullByDefault; diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/quad/GeometryHelper.java b/src/main/java/com/gregtechceu/gtceu/client/util/quad/GeometryHelper.java new file mode 100644 index 00000000000..01fc65ccd43 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/util/quad/GeometryHelper.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gregtechceu.gtceu.client.util.quad; + +import com.gregtechceu.gtceu.client.model.quad.QuadView; +import com.gregtechceu.gtceu.utils.GTUtil; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Vec3i; +import net.minecraft.util.Mth; + +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; +import org.joml.Vector3f; + +/** + * Static routines of general utility for renderer implementations. + * Renderers are not required to use these helpers, but they were designed to be usable without the default renderer. + */ +@UtilityClass +public class GeometryHelper { + + /** Result from {@link #toFaceIndex(Direction)} for null values. */ + public static final int NULL_FACE_ID = 6; + + /** + * Convenient way to encode faces that may be null. Null is returned as {@link #NULL_FACE_ID}. + * Use {@link #faceFromIndex(int)} to retrieve encoded face. + */ + public static int toFaceIndex(@Nullable Direction face) { + return face == null ? NULL_FACE_ID : face.get3DDataValue(); + } + + /** + * Use to decode a result from {@link #toFaceIndex(Direction)}. Return value will be null if encoded value was null. + */ + @Contract("null -> null") + public static @Nullable Direction faceFromIndex(int faceIndex) { + return GTUtil.DIRECTIONS_WITH_NULL[faceIndex]; + } + + /** + * Identifies the face to which the quad is most closely aligned. This mimics the value that + * {@link BakedQuad#getDirection()} returns, and is used in the vanilla renderer for all diffuse lighting. + * + *

+ * Derived from the quad face normal and expects convex quads with all points co-planar. + */ + public static Direction lightFace(QuadView quad) { + final Vector3f normal = quad.faceNormal(); + return switch (GeometryHelper.longestAxis(normal)) { + case X -> normal.x() > 0 ? Direction.EAST : Direction.WEST; + case Y -> normal.y() > 0 ? Direction.UP : Direction.DOWN; + case Z -> normal.z() > 0 ? Direction.SOUTH : Direction.NORTH; + }; + } + + /** + * @see #longestAxis(float, float, float) + */ + public static Axis longestAxis(Vector3f vec) { + return longestAxis(vec.x(), vec.y(), vec.z()); + } + + /** + * Identifies the largest (max absolute magnitude) component (X, Y, Z) in the given vector. + */ + public static Axis longestAxis(float normalX, float normalY, float normalZ) { + Axis result = Axis.Y; + float longest = Math.abs(normalY); + float a = Math.abs(normalX); + + if (a > longest) { + result = Axis.X; + longest = a; + } + + return Math.abs(normalZ) > longest ? Axis.Z : result; + } + + /** + * Stores a normal plus an extra value as a quartet of signed bytes. This is the same normal format that vanilla + * item rendering expects. The extra value is for use by shaders. + */ + public static int packNormal(float x, float y, float z, float w) { + x = Mth.clamp(x, -1, 1); + y = Mth.clamp(y, -1, 1); + z = Mth.clamp(z, -1, 1); + w = Mth.clamp(w, -1, 1); + + return ((int) (x * 127) & 255) | (((int) (y * 127) & 255) << 8) | (((int) (z * 127) & 255) << 16) | + (((int) (w * 127) & 255) << 24); + } + + /** + * Version of {@link #packNormal(float, float, float, float)} that accepts a vector type. + */ + public static int packNormal(Vector3f normal, float w) { + return packNormal(normal.x(), normal.y(), normal.z(), w); + } + + /** + * Retrieves values packed by {@link #packNormal(float, float, float, float)}. + * + *

+ * Components are x, y, z, w - zero based. + */ + public static float getPackedNormalComponent(int packedNormal, int component) { + return ((byte) (packedNormal >> (8 * component))) / 127f; + } + + /** + * Computes the face normal of the given quad and saves it in the provided non-null vector. + * If {@link QuadView#nominalFace()} is set will optimize by confirming quad is parallel to that face and, + * if so, use the standard normal for that face direction. + * + *

+ * Will work with triangles also. Assumes counter-clockwise winding order, which is the norm. Expects convex quads + * with all points co-planar. + */ + public static void computeFaceNormal(Vector3f saveTo, QuadView q) { + final Direction nominalFace = q.nominalFace(); + + if (isQuadParallelToFace(nominalFace, q)) { + Vec3i vec = nominalFace.getNormal(); + saveTo.set(vec.getX(), vec.getY(), vec.getZ()); + return; + } + + final float x0 = q.x(0); + final float y0 = q.y(0); + final float z0 = q.z(0); + final float x1 = q.x(1); + final float y1 = q.y(1); + final float z1 = q.z(1); + final float x2 = q.x(2); + final float y2 = q.y(2); + final float z2 = q.z(2); + final float x3 = q.x(3); + final float y3 = q.y(3); + final float z3 = q.z(3); + + final float dx0 = x2 - x0; + final float dy0 = y2 - y0; + final float dz0 = z2 - z0; + final float dx1 = x3 - x1; + final float dy1 = y3 - y1; + final float dz1 = z3 - z1; + + float normX = dy0 * dz1 - dz0 * dy1; + float normY = dz0 * dx1 - dx0 * dz1; + float normZ = dx0 * dy1 - dy0 * dx1; + + float l = (float) Math.sqrt(normX * normX + normY * normY + normZ * normZ); + + if (l != 0) { + normX /= l; + normY /= l; + normZ /= l; + } + + saveTo.set(normX, normY, normZ); + } + + /** + * Returns true if quad is parallel to the given face. Does not validate quad winding order. Expects convex quads + * with all points co-planar. + */ + public static boolean isQuadParallelToFace(@Nullable Direction face, QuadView quad) { + if (face == null) { + return false; + } + + int i = face.getAxis().ordinal(); + final float val = quad.posByIndex(0, i); + return Mth.equal(val, quad.posByIndex(1, i)) && Mth.equal(val, quad.posByIndex(2, i)) && + Mth.equal(val, quad.posByIndex(3, i)); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/GTQuadTransformers.java b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/GTQuadTransformers.java similarity index 78% rename from src/main/java/com/gregtechceu/gtceu/client/util/GTQuadTransformers.java rename to src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/GTQuadTransformers.java index 42e0bb9b62b..de1099e49b5 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/util/GTQuadTransformers.java +++ b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/GTQuadTransformers.java @@ -1,4 +1,4 @@ -package com.gregtechceu.gtceu.client.util; +package com.gregtechceu.gtceu.client.util.quad.transformers; import net.minecraft.client.renderer.FaceInfo; import net.minecraft.client.renderer.block.model.BakedQuad; @@ -9,6 +9,8 @@ import net.minecraftforge.client.model.IQuadTransformer; import net.minecraftforge.client.model.QuadTransformers; +import java.lang.reflect.Array; + public final class GTQuadTransformers { public static IQuadTransformer offset(float by) { @@ -79,9 +81,9 @@ public static BakedQuad setSprite(BakedQuad quad, TextureAtlasSprite sprite) { vertices[offset] = Float.floatToRawIntBits(u); vertices[offset + 1] = Float.floatToRawIntBits(v); } - BakedQuad newQuad = new BakedQuad(vertices, quad.getTintIndex(), quad.getDirection(), - sprite, quad.isShade(), quad.hasAmbientOcclusion()); - return newQuad.gtceu$setTextureKey(quad.gtceu$getTextureKey()); + return new BakedQuad(vertices, quad.getTintIndex(), quad.getDirection(), + sprite, quad.isShade(), quad.hasAmbientOcclusion()) + .gtceu$setTextureKey(quad.gtceu$getTextureKey()); } public static BakedQuad setColor(BakedQuad quad, int argbColor, boolean clearTintIndex) { @@ -94,6 +96,33 @@ public static BakedQuad setColor(BakedQuad quad, int argbColor, boolean clearTin return copy; } + public static IQuadTransformer derotate() { + return quad -> { + int[] vertices = quad.getVertices(); + + int start = 0; + float minU = Float.MAX_VALUE, minV = Float.MAX_VALUE; + int[][] uvs = (int[][]) Array.newInstance(int.class, 4, 2); + + for (int i = 0; i < 4; i++) { + int offset = i * IQuadTransformer.STRIDE + IQuadTransformer.UV0; + System.arraycopy(vertices, offset, uvs[i], 0, 2); + + float u = Float.intBitsToFloat(uvs[i][0]); + float v = Float.intBitsToFloat(uvs[i][1]); + if (u <= minU && v <= minV) { + minU = Math.min(minU, u); + minV = Math.min(minV, v); + start = i; + } + } + for (int i = 0; i < 4; i++) { + int offset = i * IQuadTransformer.STRIDE + IQuadTransformer.UV0; + System.arraycopy(uvs[(i + start) % 4], 0, vertices, offset, 2); + } + }; + } + public static BakedQuad copy(BakedQuad quad) { return new BakedQuad(quad.getVertices().clone(), quad.getTintIndex(), quad.getDirection(), quad.getSprite(), quad.isShade(), quad.hasAmbientOcclusion()) diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/InterpolationHelper.java b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/InterpolationHelper.java new file mode 100644 index 00000000000..f1b1d5404fa --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/InterpolationHelper.java @@ -0,0 +1,120 @@ +/* + * This file is part of CodeChickenLib. + * Copyright (c) 2018, covers1624, All rights reserved. + * + * CodeChickenLib is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * CodeChickenLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CodeChickenLib. If not, see . + */ +package com.gregtechceu.gtceu.client.util.quad.transformers; + +import net.minecraft.util.Mth; + +/** + * @author covers1624 + */ +public class InterpolationHelper { + + private final float[][] posCache = new float[4][2]; + private final float[] valCache = new float[4]; + + private float x0; + private float x1; + private float y0; + private float y1; + + private float rX; + private float rY; + + private int p00; + private int p10; + private int p11; + private int p01; + + /** + * Resets the interpolation helper with the given quad. Does not care what order the vertices are in. + */ + public void reset(float dx0, float dy0, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) { + float[] vec0 = this.posCache[0]; + float[] vec1 = this.posCache[1]; + float[] vec2 = this.posCache[2]; + float[] vec3 = this.posCache[3]; + + vec0[0] = dx0; + vec1[0] = dx1; + vec2[0] = dx2; + vec3[0] = dx3; + + vec0[1] = dy0; + vec1[1] = dy1; + vec2[1] = dy2; + vec3[1] = dy3; + } + + /** + * Call when you are ready to use the interpolation helper. + */ + public void setup() { + this.p00 = 0; // Bottom Left is always first. + this.x0 = this.posCache[this.p00][0]; + this.y0 = this.posCache[this.p00][1]; + + for (int i = 1; i < 4; i++) { + float x = this.posCache[i][0]; + float y = this.posCache[i][1]; + + if (this.y0 == y) { + // Bottom right. + this.p10 = i; + this.x1 = x; + } else if (this.x0 == x) { + // Top left. + this.p01 = i; + this.y1 = y; + } else { + // Top right. + this.p11 = i; + } + } + } + + /** + * Computes the coefficients for the interpolation. + * + * @param x X interpolation location. + * @param y Y interpolation location. + */ + public void locate(float x, float y) { + this.rX = Mth.inverseLerp(x, this.x0, this.x1); + this.rY = Mth.inverseLerp(y, this.y0, this.y1); + } + + /** + * Interpolates using the already computed coefficients. + * + * @param q0 Value at dx0 dy0 + * @param q1 Value at dx1 dy1 + * @param q2 Value at dx2 dy2 + * @param q3 Value at dx3 dy3 + * @return The result. + */ + public float interpolate(float q0, float q1, float q2, float q3) { + this.valCache[0] = q0; + this.valCache[1] = q1; + this.valCache[2] = q2; + this.valCache[3] = q3; + float f0 = Mth.lerp(this.rX, this.valCache[this.p00], this.valCache[this.p10]); + float f1 = Mth.lerp(this.rX, this.valCache[this.p01], this.valCache[this.p11]); + + return Mth.lerp(this.rY, f0, f1); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadClamper.java b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadClamper.java new file mode 100644 index 00000000000..9ca6980a74d --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadClamper.java @@ -0,0 +1,106 @@ +/* + * This file is part of CodeChickenLib. + * Copyright (c) 2018, covers1624, All rights reserved. + * + * CodeChickenLib is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * CodeChickenLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CodeChickenLib. If not, see . + */ +package com.gregtechceu.gtceu.client.util.quad.transformers; + +import com.gregtechceu.gtceu.client.model.quad.MutableQuadView; +import com.gregtechceu.gtceu.client.model.quad.transform.QuadTransform; + +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.AABB; + +import org.joml.Vector3f; + +/** + * This transformer simply clamps the vertices inside the provided box.
+ * You probably want to Re-Interpolate the UV's, Color, and Lightmap. For that, see {@link QuadReInterpolator}. + * + * @see QuadReInterpolator + * @author covers1624 + */ +public class QuadClamper implements QuadTransform { + + private final AABB clampBounds; + + private final Vector3f pos = new Vector3f(); + + public QuadClamper(AABB clampBounds) { + this.clampBounds = clampBounds; + } + + @Override + public boolean transform(MutableQuadView quad) { + Direction.Axis axis = quad.nominalFace().getAxis(); + + clamp(quad, this.clampBounds); + + // Check if the quad would be invisible and cull it. + float x1 = quad.posByIndex(0, xCoord(axis)); + float x2 = quad.posByIndex(1, xCoord(axis)); + float x3 = quad.posByIndex(2, xCoord(axis)); + float x4 = quad.posByIndex(3, xCoord(axis)); + + float y1 = quad.posByIndex(0, yCoord(axis)); + float y2 = quad.posByIndex(1, yCoord(axis)); + float y3 = quad.posByIndex(2, yCoord(axis)); + float y4 = quad.posByIndex(3, yCoord(axis)); + + // These comparisons are safe as we are comparing clamped values. + boolean flag1 = x1 == x2 && x2 == x3 && x3 == x4; + boolean flag2 = y1 == y2 && y2 == y3 && y3 == y4; + return !flag1 && !flag2; + } + + private void clamp(MutableQuadView quad, AABB bb) { + for (int i = 0; i < 4; i++) { + quad.copyPos(i, pos); + pos.set((float) Mth.clamp(pos.x(), bb.minX, bb.maxX), + (float) Mth.clamp(pos.y(), bb.minY, bb.maxY), + (float) Mth.clamp(pos.z(), bb.minZ, bb.maxZ)); + quad.pos(i, pos); + } + } + + /** + * Gets the 2d X coordinate for the given axis. + * + * @param axis The axis. side >> 1 + * @return The x coordinate. + */ + private static int xCoord(Direction.Axis axis) { + if (axis == Direction.Axis.Y) { + return 0; + } else { + return 2; + } + } + + /** + * Gets the 2d Y coordinate for the given axis. + * + * @param axis The axis. + * @return The y coordinate. + */ + private static int yCoord(Direction.Axis axis) { + if (axis != Direction.Axis.Y) { + return 1; + } else { + return 2; + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadCornerKicker.java b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadCornerKicker.java new file mode 100644 index 00000000000..fe849c4d525 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadCornerKicker.java @@ -0,0 +1,205 @@ +/* + * This file is part of CodeChickenLib. + * Copyright (c) 2018, covers1624, All rights reserved. + * + * CodeChickenLib is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * CodeChickenLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CodeChickenLib. If not, see . + */ +package com.gregtechceu.gtceu.client.util.quad.transformers; + +import com.gregtechceu.gtceu.client.model.quad.MutableQuadView; +import com.gregtechceu.gtceu.client.model.quad.transform.QuadTransform; +import com.gregtechceu.gtceu.client.util.quad.GeometryHelper; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.core.Vec3i; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.AABB; + +import org.jetbrains.annotations.Nullable; + +import static net.minecraft.core.Direction.*; +import static net.minecraft.core.Direction.AxisDirection.*; + +/** + * This transformer is a little complicated. + * Basically, a Facade / Cover can use this to 'kick' the edges of quads in to fix Z-fighting in the corners. + *

+ * Use it by specifying + *

    + *
  • the side of the block you are on,
  • + *
  • the bitmask for where the other Facades / Covers are,
  • + *
  • the bounding box of the facade (NOT the hole piece),
  • + *
  • and the thickness of your Facade / Cover (which is used as the kick amount).
  • + *
+ * + * @author covers1624 + */ +public class QuadCornerKicker implements QuadTransform { + + public static final QuadCornerKicker INSTANCE = new QuadCornerKicker(); + + // Simple horizonal lookups. + public static Direction[][] horizonals = new Direction[][] { + // Around Y axis, NSWE. + { NORTH, SOUTH, WEST, EAST }, + { NORTH, SOUTH, WEST, EAST }, + + // Around Z axis, DUWE. + { DOWN, UP, WEST, EAST }, + { DOWN, UP, WEST, EAST }, + + // Around X axis, DUNS. + { DOWN, UP, NORTH, SOUTH }, + { DOWN, UP, NORTH, SOUTH } }; + + private Direction mySide; + private int facadeMask; + private AABB bounds; + private double thickness; + + public QuadCornerKicker() { + super(); + } + + /** + * Set's the side this Facade / Cover is attached to. + * + * @param side The side. + */ + public void setSide(Direction side) { + this.mySide = side; + } + + /** + * Sets the bitmask of Facades / Covers in the block space. + * This is as simple as {@code mask = (1 << side)}. + * + * @param mask The mask. + */ + public void setFacadeMask(int mask) { + this.facadeMask = mask; + } + + /** + * Sets the bounding box of the Facade / Cover, this should be the full box, not just a piece of the hole's 'ring'. + * + * @param bounds The bounding box. + */ + public void setBounds(AABB bounds) { + this.bounds = bounds; + } + + /** + * Sets the amount to kick the vertex in by, this is your facades thickness. + * + * @param thickness The thickness. + */ + public void setThickness(double thickness) { + this.thickness = thickness; + } + + @Override + public boolean transform(MutableQuadView quad) { + Direction side = quad.nominalFace(); + if (side == this.mySide || side == this.mySide.getOpposite()) { + return true; + } + for (Direction hoz : horizonals[this.mySide.get3DDataValue()]) { + if (side == hoz || side == hoz.getOpposite() || (this.facadeMask & (1 << hoz.ordinal())) == 0) { + continue; + } + Corner corner = Corner.fromSides(this.mySide.getOpposite(), side, hoz); + for (int i = 0; i < 4; i++) { + float x = quad.posByIndex(i, 0); + float y = quad.posByIndex(i, 1); + float z = quad.posByIndex(i, 2); + if (Mth.equal(x, corner.pX(this.bounds)) && Mth.equal(y, corner.pY(this.bounds)) && + Mth.equal(z, corner.pZ(this.bounds))) { + Vec3i normal = hoz.getNormal(); + x -= normal.getX() * this.thickness; + y -= normal.getY() * this.thickness; + z -= normal.getZ() * this.thickness; + quad.pos(i, x, y, z); + } + } + } + + return true; + } + + @Override + public void processInPlace(BakedQuad quad) {} + + public enum Corner { + + MIN_X_MIN_Y_MIN_Z(NEGATIVE, NEGATIVE, NEGATIVE), + MIN_X_MIN_Y_MAX_Z(NEGATIVE, NEGATIVE, POSITIVE), + MIN_X_MAX_Y_MIN_Z(NEGATIVE, POSITIVE, NEGATIVE), + MIN_X_MAX_Y_MAX_Z(NEGATIVE, POSITIVE, POSITIVE), + + MAX_X_MIN_Y_MIN_Z(POSITIVE, NEGATIVE, NEGATIVE), + MAX_X_MIN_Y_MAX_Z(POSITIVE, NEGATIVE, POSITIVE), + MAX_X_MAX_Y_MIN_Z(POSITIVE, POSITIVE, NEGATIVE), + MAX_X_MAX_Y_MAX_Z(POSITIVE, POSITIVE, POSITIVE); + + private final AxisDirection xAxis; + private final AxisDirection yAxis; + private final AxisDirection zAxis; + + public static final Corner[] VALUES = values(); + private static final int[] sideMask = { 0, 2, 0, 1, 0, 4 }; + + Corner(AxisDirection xAxis, AxisDirection yAxis, AxisDirection zAxis) { + this.xAxis = xAxis; + this.yAxis = yAxis; + this.zAxis = zAxis; + } + + /** + * Used to find what corner is at the 3 sides. + * This method assumes you pass in the X axis side, Y axis side, and Z axis side, + * it will NOT complain about an invalid side, you will just get garbage data. + * This method also does not care what order the 3 axes are in. + * + * @param sideA Side one. + * @param sideB Side two. + * @param sideC Side three. + * @return The corner at the 3 sides. + */ + public static Corner fromSides(@Nullable Direction sideA, + @Nullable Direction sideB, + @Nullable Direction sideC) { + int aIndex = GeometryHelper.toFaceIndex(sideA); + int bIndex = GeometryHelper.toFaceIndex(sideB); + int cIndex = GeometryHelper.toFaceIndex(sideC); + + // <3 Chicken-Bones. + return Corner.VALUES[sideMask[aIndex] | sideMask[bIndex] | sideMask[cIndex]]; + } + + public float pX(AABB box) { + return (float) (this.xAxis == NEGATIVE ? box.minX : box.maxX); + } + + public float pY(AABB box) { + return (float) (this.yAxis == NEGATIVE ? box.minY : box.maxY); + } + + public float pZ(AABB box) { + return (float) (this.zAxis == NEGATIVE ? box.minZ : box.maxZ); + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadReInterpolator.java b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadReInterpolator.java new file mode 100644 index 00000000000..bc3cf275201 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadReInterpolator.java @@ -0,0 +1,189 @@ +/* + * This file is part of CodeChickenLib. + * Copyright (c) 2018, covers1624, All rights reserved. + * + * CodeChickenLib is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * CodeChickenLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CodeChickenLib. If not, see . + */ +package com.gregtechceu.gtceu.client.util.quad.transformers; + +import com.gregtechceu.gtceu.client.model.quad.MutableQuadView; +import com.gregtechceu.gtceu.client.model.quad.QuadView; +import com.gregtechceu.gtceu.client.model.quad.transform.QuadTransform; + +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.core.Direction; + +/** + * This transformer Re-Interpolates the Color, UV's and LightMaps. Use this after all transformations that translate + * vertices in the pipeline. + *

+ * This Transformation can only be used in the BakedPipeline. + * + * @author covers1624 + */ +public class QuadReInterpolator implements QuadTransform { + + private final InterpolationHelper interpolationHelper = new InterpolationHelper(); + + private final int[] originalSpriteColor = new int[4]; + private final float[] originalSpriteU = new float[4]; + private final float[] originalSpriteV = new float[4]; + private final int[] originalSpriteLightmap = new int[4]; + + public QuadReInterpolator() { + super(); + } + + public void setInputQuad(QuadView quad) { + Direction.Axis axis = quad.nominalFace().getAxis(); + int xIndex = xCoord(axis); + int yIndex = yCoord(axis); + + interpolationHelper.reset( + quad.posByIndex(0, xIndex), quad.posByIndex(0, yIndex), + quad.posByIndex(1, xIndex), quad.posByIndex(1, yIndex), + quad.posByIndex(2, xIndex), quad.posByIndex(2, yIndex), + quad.posByIndex(3, xIndex), quad.posByIndex(3, yIndex)); + + // Save the original properties of the quad's vertices + for (int v = 0; v < 4; v++) { + originalSpriteColor[v] = quad.color(v); + originalSpriteU[v] = quad.u(v); + originalSpriteV[v] = quad.v(v); + originalSpriteLightmap[v] = quad.lightmap(v); + } + } + + @Override + public boolean transform(MutableQuadView quad) { + Direction.Axis axis = quad.nominalFace().getAxis(); + int xIndex = xCoord(axis); + int yIndex = yCoord(axis); + + this.interpolationHelper.setup(); + for (int i = 0; i < 4; i++) { + float x = quad.posByIndex(i, xIndex); + float y = quad.posByIndex(i, yIndex); + this.interpolationHelper.locate(x, y); + interpolateColorFrom(quad, i); + interpolateUVFrom(quad, i); + interpolateLightmapFrom(quad, i); + } + return true; + } + + /** + * Interpolates the new color values for this Vertex using the others as a reference. + */ + public void interpolateColorFrom(MutableQuadView quad, int vertexIndex) { + int p1 = this.originalSpriteColor[0]; + int p2 = this.originalSpriteColor[1]; + int p3 = this.originalSpriteColor[2]; + int p4 = this.originalSpriteColor[3]; + if (p1 == p2 && p2 == p3 && p3 == p4) { + return; // Don't bother for uniformly colored quads + } + + // Interpolate each color component separately + int color = 0; + int mask = 0xFF; + for (int i = 0; i < 4; i++) { + int p1c = p1 & mask; + int p2c = p2 & mask; + int p3c = p3 & mask; + int p4c = p4 & mask; + int interpolated = (int) interpolationHelper.interpolate(p1c, p2c, p3c, p4c); + color |= interpolated & mask; + mask <<= 8; + } + + quad.color(vertexIndex, color); + } + + /** + * Interpolates the new UV values for this Vertex using the others as a reference. + */ + public void interpolateUVFrom(MutableQuadView quad, int vertexIndex) { + float p1 = originalSpriteU[0]; + float p2 = originalSpriteU[1]; + float p3 = originalSpriteU[2]; + float p4 = originalSpriteU[3]; + float u = interpolationHelper.interpolate(p1, p2, p3, p4); + + p1 = originalSpriteV[0]; + p2 = originalSpriteV[1]; + p3 = originalSpriteV[2]; + p4 = originalSpriteV[3]; + float v = interpolationHelper.interpolate(p1, p2, p3, p4); + quad.uv(vertexIndex, u, v); + } + + /** + * Interpolates the new LightMap values for this Vertex using the others as a reference. + * + * @return The same Vertex. + */ + public void interpolateLightmapFrom(MutableQuadView quad, int vertexIndex) { + int p1 = originalSpriteLightmap[0]; + int p2 = originalSpriteLightmap[1]; + int p3 = originalSpriteLightmap[2]; + int p4 = originalSpriteLightmap[3]; + if (p1 == p2 && p2 == p3 && p3 == p4) { + return; // Don't bother for uniformly lit quads + } + + // Interpolate both lightmap components separately + int p1l = LightTexture.block(p1); + int p2l = LightTexture.block(p2); + int p3l = LightTexture.block(p3); + int p4l = LightTexture.block(p4); + int block = (int) interpolationHelper.interpolate(p1l, p2l, p3l, p4l); + + p1l = LightTexture.sky(p1); + p2l = LightTexture.sky(p2); + p3l = LightTexture.sky(p3); + p4l = LightTexture.sky(p4); + int sky = (int) interpolationHelper.interpolate(p1l, p2l, p3l, p4l); + + quad.lightmap(vertexIndex, block, sky); + } + + /** + * Gets the 2d X coordinate for the given axis. + * + * @param axis The axis. side >> 1 + * @return The x coordinate. + */ + private static int xCoord(Direction.Axis axis) { + if (axis == Direction.Axis.Y) { + return 0; + } else { + return 2; + } + } + + /** + * Gets the 2d Y coordinate for the given axis. + * + * @param axis The axis. + * @return The y coordinate. + */ + private static int yCoord(Direction.Axis axis) { + if (axis != Direction.Axis.Y) { + return 1; + } else { + return 2; + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadTinter.java b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadTinter.java new file mode 100644 index 00000000000..06a50545782 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/util/quad/transformers/QuadTinter.java @@ -0,0 +1,60 @@ +/* + * This file is part of CodeChickenLib. + * Copyright (c) 2018, covers1624, All rights reserved. + * + * CodeChickenLib is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * CodeChickenLib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with CodeChickenLib. If not, see . + */ +package com.gregtechceu.gtceu.client.util.quad.transformers; + +import com.gregtechceu.gtceu.client.model.quad.MutableQuadView; +import com.gregtechceu.gtceu.client.model.quad.transform.QuadTransform; + +/** + * This transformer tints quads. + */ +public class QuadTinter implements QuadTransform { + + private final int argb; + + public QuadTinter(int rgb) { + this.argb = 0xFF000000 | rgb; + } + + @Override + public boolean transform(MutableQuadView quad) { + // Nuke tintIndex. + quad.tintIndex(-1); + for (int i = 0; i < 4; i++) { + int color = quad.color(i); + color = multiplyColor(color, argb); + quad.color(i, color); + } + return true; + } + + private static int multiplyColor(int color1, int color2) { + if (color1 == -1) { + return color2; + } else if (color2 == -1) { + return color1; + } + + final int alpha = ((color1 >> 24) & 0xFF) * ((color2 >> 24) & 0xFF) / 0xFF; + final int red = ((color1 >> 16) & 0xFF) * ((color2 >> 16) & 0xFF) / 0xFF; + final int green = ((color1 >> 8) & 0xFF) * ((color2 >> 8) & 0xFF) / 0xFF; + final int blue = (color1 & 0xFF) * (color2 & 0xFF) / 0xFF; + + return (alpha << 24) | (red << 16) | (green << 8) | blue; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java index 0fb295c79ce..92698e130bd 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java @@ -19,6 +19,7 @@ import com.gregtechceu.gtceu.common.block.*; import com.gregtechceu.gtceu.common.block.explosive.IndustrialTNTBlock; import com.gregtechceu.gtceu.common.block.explosive.PowderbarrelBlock; +import com.gregtechceu.gtceu.common.data.blocks.GTDevBlocks; import com.gregtechceu.gtceu.common.data.models.GTModels; import com.gregtechceu.gtceu.common.item.LampBlockItem; import com.gregtechceu.gtceu.common.item.LaserPipeBlockItem; @@ -1425,6 +1426,11 @@ public static void init() { // GCYM GCYMBlocks.init(); + + // Dev-only test blocks + if (GTCEu.isDev()) { + GTDevBlocks.init(); + } } private static void initializeCobbleReplacements() { diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/blocks/GTDevBlocks.java b/src/main/java/com/gregtechceu/gtceu/common/data/blocks/GTDevBlocks.java new file mode 100644 index 00000000000..e0cca005d91 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/data/blocks/GTDevBlocks.java @@ -0,0 +1,19 @@ +package com.gregtechceu.gtceu.common.data.blocks; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SoundType; + +import com.tterrag.registrate.util.entry.BlockEntry; + +import static com.gregtechceu.gtceu.common.registry.GTRegistration.REGISTRATE; + +public class GTDevBlocks { + + public static final BlockEntry CTM_TEST = REGISTRATE.block("ctm_test", Block::new) + .lang("Connected Texture Test Block") + .properties(p -> p.noLootTable().sound(SoundType.SCULK)) + .simpleItem() + .register(); + + public static void init() {} +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/ReloadableResourceManagerAccessor.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/ReloadableResourceManagerAccessor.java new file mode 100644 index 00000000000..1aae111b199 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/ReloadableResourceManagerAccessor.java @@ -0,0 +1,16 @@ +package com.gregtechceu.gtceu.core.mixins; + +import net.minecraft.server.packs.resources.PreparableReloadListener; +import net.minecraft.server.packs.resources.ReloadableResourceManager; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Mixin(ReloadableResourceManager.class) +public interface ReloadableResourceManagerAccessor { + + @Accessor + List getListeners(); +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/ModelBakerImplMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/ModelBakerImplMixin.java new file mode 100644 index 00000000000..bd8aef34c66 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/ModelBakerImplMixin.java @@ -0,0 +1,31 @@ +package com.gregtechceu.gtceu.core.mixins.client; + +import com.gregtechceu.gtceu.client.util.SpriteFunctionWrapper; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.Material; +import net.minecraft.client.resources.model.ModelState; +import net.minecraft.resources.ResourceLocation; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import java.util.function.Function; + +@Mixin(targets = { "net.minecraft.client.resources.model.ModelBakery$ModelBakerImpl" }) +public abstract class ModelBakerImplMixin { + + // the parameters aren't remapped because Parchment can't remap Forge's patches + @SuppressWarnings("NameDoesntMatchTargetClass") + // Note: We don't remap this method as it's added by forge + @ModifyVariable(at = @At("HEAD"), + method = "bake(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/client/resources/model/ModelState;Ljava/util/function/Function;)Lnet/minecraft/client/resources/model/BakedModel;", + argsOnly = true, + remap = false) + private Function gtceu$injectTextureScraper(Function spriteGetter, + ResourceLocation modelLocation, + ModelState transform) { + return new SpriteFunctionWrapper(spriteGetter, modelLocation); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/TextureAtlasMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/TextureAtlasMixin.java new file mode 100644 index 00000000000..e06a756efb9 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/TextureAtlasMixin.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gregtechceu.gtceu.core.mixins.client; + +import com.gregtechceu.gtceu.client.model.quad.SpriteFinder; + +import net.minecraft.client.renderer.texture.SpriteLoader; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.resources.ResourceLocation; + +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Map; + +@Mixin(TextureAtlas.class) +public class TextureAtlasMixin implements SpriteFinder.SpriteFinderAccess { + + @Shadow + private Map texturesByName; + + @Unique + private SpriteFinder gtceu$spriteFinder = null; + + @Inject(at = @At("TAIL"), method = "upload") + private void uploadHook(SpriteLoader.Preparations preparations, CallbackInfo info) { + gtceu$spriteFinder = null; + } + + @Override + public @NotNull SpriteFinder gtceu$spriteFinder() { + if (this.gtceu$spriteFinder == null) { + this.gtceu$spriteFinder = new SpriteFinder(texturesByName, (TextureAtlas) (Object) this); + } + return this.gtceu$spriteFinder; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/integration/modernfix/GTModernFixIntegration.java b/src/main/java/com/gregtechceu/gtceu/integration/modernfix/GTModernFixIntegration.java index a36f05bde92..6946e0c45b5 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/modernfix/GTModernFixIntegration.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/modernfix/GTModernFixIntegration.java @@ -1,8 +1,7 @@ package com.gregtechceu.gtceu.integration.modernfix; -import com.gregtechceu.gtceu.client.model.machine.MachineModel; - -import com.lowdragmc.lowdraglib.client.model.custommodel.CustomBakedModel; +import com.gregtechceu.gtceu.client.util.AssetEventListener; +import com.gregtechceu.gtceu.client.util.ModelEventHelper; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.*; @@ -41,15 +40,14 @@ public void onDynamicResourcesStatusChange(boolean enabled) { } @Override - public BakedModel onBakedModelLoad(ResourceLocation location, UnbakedModel baseModel, - BakedModel originalModel, ModelState state, ModelBakery bakery, + public BakedModel onBakedModelLoad(ResourceLocation modelLocation, UnbakedModel baseModel, + BakedModel model, ModelState state, ModelBakery bakery, Function textureGetter) { - if (originalModel instanceof CustomBakedModel ctmModel) { - // Unwrap all machine models from LDLib CTM models so we don't need to be as aggressive with mixins - if (ctmModel.getParent() instanceof MachineModel machineModel) { - return machineModel; - } + // process all model replacers + for (var listener : ModelEventHelper.EVENT_LISTENERS) { + if (!(listener.listener() instanceof AssetEventListener.BakedModelReplacement modelReplacement)) continue; + model = modelReplacement.modifyBakedModel(modelLocation, model, baseModel, bakery); } - return originalModel; + return model; } } diff --git a/src/main/java/com/gregtechceu/gtceu/utils/ArrayHelpers.java b/src/main/java/com/gregtechceu/gtceu/utils/ArrayHelpers.java new file mode 100644 index 00000000000..b1722d9620b --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/utils/ArrayHelpers.java @@ -0,0 +1,45 @@ +package com.gregtechceu.gtceu.utils; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Array; + +public class ArrayHelpers { + + /** + * Returns a copy of the specified array object, deeply copying multidimensional arrays. + * If the specified object is null, the return value is null. + * + *

+ * Note: if the array object has an element type which is a reference type that is not an array type, + * the elements themselves are not deeply copied. This method only copies array objects. + * + * @param array the array object to deep copy + * @param the type of the array to deep copy + * @return a copy of the specified array object, deeply copying multidimensional arrays, or null if the object is + * null + */ + @Contract(value = "!null -> !null; _ -> null", pure = true) + public static T @Nullable [] deepCopy(T @Nullable [] array) { + if (array == null) { + return null; + } + + Class componentType = array.getClass().getComponentType(); + + @SuppressWarnings("unchecked") + T[] copy = (T[]) Array.newInstance(componentType, array.length); + + if (componentType.isArray()) { + for (int i = 0; i < array.length; ++i) { + // noinspection unchecked + Array.set(copy, i, deepCopy((T[]) array[i])); + } + } else { + System.arraycopy(array, 0, copy, 0, array.length); + } + + return copy; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/utils/GTMatrixUtils.java b/src/main/java/com/gregtechceu/gtceu/utils/GTMatrixUtils.java index 44f6ad29e34..b5b9d31a626 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/GTMatrixUtils.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/GTMatrixUtils.java @@ -6,7 +6,6 @@ import net.minecraft.util.Mth; import com.google.common.collect.HashBasedTable; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Table; import com.google.common.collect.Tables; import org.jetbrains.annotations.Contract; @@ -14,7 +13,8 @@ import java.lang.Math; import java.security.InvalidParameterException; -import java.util.Objects; +import java.util.EnumMap; +import java.util.Map; import javax.annotation.ParametersAreNonnullByDefault; @@ -22,13 +22,10 @@ @MethodsReturnNonnullByDefault public class GTMatrixUtils { - @SuppressWarnings("UnstableApiUsage") - private static final ImmutableMap directionAxises = Util.make(() -> { - ImmutableMap.Builder map = ImmutableMap.builderWithExpectedSize(6); + private static final Map directionAxes = Util.make(new EnumMap<>(Direction.class), map -> { for (Direction dir : GTUtil.DIRECTIONS) { map.put(dir, dir.step()); } - return map.build(); }); private static final Table rotations = Tables .synchronizedTable(HashBasedTable.create()); @@ -160,6 +157,6 @@ public static Matrix4fc createRotationState(Direction frontFace, Direction upwar } public static Vector3fc getDirectionAxis(Direction dir) { - return Objects.requireNonNull(directionAxises.get(dir)); + return directionAxes.get(dir); } } diff --git a/src/main/java/com/gregtechceu/gtceu/utils/GTStringUtils.java b/src/main/java/com/gregtechceu/gtceu/utils/GTStringUtils.java index 70912110719..32d503a7f57 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/GTStringUtils.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/GTStringUtils.java @@ -1,6 +1,7 @@ package com.gregtechceu.gtceu.utils; import net.minecraft.ChatFormatting; +import net.minecraft.Util; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.ListTag; import net.minecraft.network.chat.Component; @@ -8,6 +9,7 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.properties.Property; import net.minecraftforge.fluids.FluidStack; import org.jetbrains.annotations.NotNull; @@ -15,6 +17,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; public class GTStringUtils { @@ -222,4 +225,18 @@ public static Component toComponent(ListTag arr) { component.append("]"); return component; } + + public static String getPropertyValueString(Map.Entry, Comparable> entry) { + Property property = entry.getKey(); + Comparable value = entry.getValue(); + + String valueString = Util.getPropertyName(property, value); + if (Boolean.TRUE.equals(value)) { + valueString = ChatFormatting.GREEN + valueString; + } else if (Boolean.FALSE.equals(value)) { + valueString = ChatFormatting.RED + valueString; + } + + return property.getName() + ": " + valueString; + } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/filter_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/filter_casing.png.mcmeta index 679654e7450..197e174c743 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/filter_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/filter_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/cleanroom/filter_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/cleanroom/filter_casing_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/plascrete.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/plascrete.png.mcmeta index 0b6135d2c98..bcfe132b2ef 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/plascrete.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/plascrete.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/cleanroom/plascrete_ctm" - } + "gtceu": { + "connection_texture": "gtceu:block/casings/cleanroom/plascrete_ctm" + } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/sterilizing_filter_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/sterilizing_filter_casing.png.mcmeta index 0e1b3e83e63..bb26602ecf7 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/sterilizing_filter_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/cleanroom/sterilizing_filter_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/cleanroom/sterilizing_filter_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/cleanroom/sterilizing_filter_casing_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel.png.mcmeta index d611cacb4ef..78607c6ca08 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_cupronickel_ctm" - } + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_cupronickel_ctm" + } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel_bloom.png.mcmeta index b1e5096ccb5..419344f2357 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_cupronickel_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_cupronickel_bloom_ctm", "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_cupronickel_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg.png.mcmeta index d0eb5a1b4e0..2f8b0f3c606 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_hssg_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_hssg_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg_bloom.png.mcmeta index a3d39d70b26..7007fd7d399 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_hssg_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_hssg_bloom_ctm", "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_hssg_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal.png.mcmeta index a543d938427..7323ad0e179 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_kanthal_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_kanthal_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal_bloom.png.mcmeta index 5f77e5af023..369076e1f9d 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_kanthal_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_kanthal_bloom_ctm", "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_kanthal_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide.png.mcmeta index cdf115622d5..ee713eaaf40 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_molybdenum_disilicide_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_molybdenum_disilicide_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide_bloom.png.mcmeta index e5d9efbf204..15eded51a94 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_molybdenum_disilicide_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_molybdenum_disilicide_bloom_ctm", "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_molybdenum_disilicide_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah.png.mcmeta index 2e4b0f7663e..8d778222e5f 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_naquadah_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_naquadah_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah_bloom.png.mcmeta index 89be208adcf..4e7c10b2cff 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_naquadah_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_naquadah_bloom_ctm", "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_naquadah_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome.png.mcmeta index 4ea55aec150..b769004afbd 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_nichrome_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_nichrome_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome_bloom.png.mcmeta index d454af3ff67..8afaa449311 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_nichrome_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_nichrome_bloom_ctm", "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_nichrome_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy.png.mcmeta index 746da5c90c5..6b2870c83a6 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_rtm_alloy_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_rtm_alloy_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy_bloom.png.mcmeta index 527eb9bb051..6d09c673e6f 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_rtm_alloy_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_rtm_alloy_bloom_ctm", "bloom": true } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_rtm_alloy_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor.png.mcmeta index 5e76601ac3e..a604c36f15e 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_superconductor_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_superconductor_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor_bloom.png.mcmeta index 2f5edd2ed74..824306dde04 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_superconductor_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_superconductor_bloom_ctm", "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_superconductor_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium.png.mcmeta index 6ae83eb0551..17e24d0d0f3 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_trinium_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_trinium_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium_bloom.png.mcmeta index 0d93c95e458..75e5e226e1f 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_trinium_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_trinium_bloom_ctm", "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_trinium_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium.png.mcmeta index 49409f48da5..76d31028072 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_tritanium_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_tritanium_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium_bloom.png.mcmeta index 1aa566dca58..5153271f7ba 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_tritanium_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_tritanium_bloom_ctm", "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tritanium_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel.png.mcmeta index 274e5147e1d..66a136186c5 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_tungstensteel_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_tungstensteel_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel_bloom.png.mcmeta index 11a9a3bcd34..df8fd23d60c 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_tungstensteel_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_tungstensteel_bloom_ctm", "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/coils/machine_coil_tungstensteel_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_bronze.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_bronze.png.mcmeta index 618e068e4dd..653afb29006 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_bronze.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_bronze.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/firebox/machine_casing_firebox_bronze_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/firebox/machine_casing_firebox_bronze_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_steel.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_steel.png.mcmeta index f07082f52f5..f120eaf9032 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_steel.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_steel.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/firebox/machine_casing_firebox_steel_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/firebox/machine_casing_firebox_steel_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_titanium.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_titanium.png.mcmeta index 06e9796abed..afe2869054b 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_titanium.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_titanium.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/firebox/machine_casing_firebox_titanium_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/firebox/machine_casing_firebox_titanium_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_tungstensteel.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_tungstensteel.png.mcmeta index fdd57cb4a7a..6ee0e5eb3d5 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_tungstensteel.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/firebox/machine_casing_firebox_tungstensteel.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/firebox/machine_casing_firebox_tungstensteel_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/firebox/machine_casing_firebox_tungstensteel_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing.png.mcmeta index 60ef8c970be..42c81b1632c 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/fusion/fusion_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/fusion/fusion_casing_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_bloom.png.mcmeta index d63d26a280c..72d1a0104b4 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/fusion/fusion_casing_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/fusion/fusion_casing_bloom_ctm", "bloom": true } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_mk2.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_mk2.png.mcmeta index 266021414e4..f8063da866f 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_mk2.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_mk2.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/fusion/fusion_casing_mk2_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/fusion/fusion_casing_mk2_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_mk3.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_mk3.png.mcmeta index 8b45a91c06a..4fd16130b5c 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_mk3.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/fusion/fusion_casing_mk3.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/fusion/fusion_casing_mk3_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/fusion/fusion_casing_mk3_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil.png.mcmeta index 0efbe8cd43c..e8fd0abfc97 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/fusion/superconducting_coil_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/fusion/superconducting_coil_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil_bloom.png.mcmeta index 2f5edd2ed74..824306dde04 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/coils/machine_coil_superconductor_bloom_ctm", - "emissive": true - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/casings/coils/machine_coil_superconductor_bloom_ctm", "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil_bloom_ctm.png.mcmeta index e333118814e..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/fusion/superconducting_coil_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/atomic_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/atomic_casing.png.mcmeta index ec7ee024889..4e544655bb0 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/atomic_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/atomic_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/atomic_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/atomic_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/corrosion_proof_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/corrosion_proof_casing.png.mcmeta index c5ad2294e42..34dd301c21d 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/corrosion_proof_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/corrosion_proof_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/corrosion_proof_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/corrosion_proof_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/high_temperature_smelting_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/high_temperature_smelting_casing.png.mcmeta index 2457291b40f..c5fa362c0f9 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/high_temperature_smelting_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/high_temperature_smelting_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/high_temperature_smelting_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/high_temperature_smelting_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/industrial_steam_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/industrial_steam_casing.png.mcmeta index 0f942a68354..cebb04f9e44 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/industrial_steam_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/industrial_steam_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/industrial_steam_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/industrial_steam_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/large_scale_assembling_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/large_scale_assembling_casing.png.mcmeta index 306854983f3..67a616a6316 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/large_scale_assembling_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/large_scale_assembling_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/large_scale_assembling_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/large_scale_assembling_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/laser_safe_engraving_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/laser_safe_engraving_casing.png.mcmeta index df8cb84ff6f..24476332093 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/laser_safe_engraving_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/laser_safe_engraving_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/laser_safe_engraving_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/laser_safe_engraving_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/nonconducting_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/nonconducting_casing.png.mcmeta index eafb895c281..1e3827124a1 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/nonconducting_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/nonconducting_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/nonconducting_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/nonconducting_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/reaction_safe_mixing_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/reaction_safe_mixing_casing.png.mcmeta index ae09e8eb280..5b62e5ce35d 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/reaction_safe_mixing_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/reaction_safe_mixing_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/reaction_safe_mixing_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/reaction_safe_mixing_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/secure_maceration_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/secure_maceration_casing.png.mcmeta index 3768093e52a..f6ec7e514b4 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/secure_maceration_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/secure_maceration_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/secure_maceration_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/secure_maceration_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/shock_proof_cutting_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/shock_proof_cutting_casing.png.mcmeta index cf058736156..b13d57a26f7 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/shock_proof_cutting_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/shock_proof_cutting_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/shock_proof_cutting_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/shock_proof_cutting_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/sifter_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/sifter_casing.png.mcmeta index 58804a3f988..f3cd3b2d23c 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/sifter_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/sifter_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/sifter_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/sifter_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/stress_proof_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/stress_proof_casing.png.mcmeta index 19fb6ad2f8f..bf95820d5b5 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/stress_proof_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/stress_proof_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/stress_proof_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/stress_proof_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/vibration_safe_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/vibration_safe_casing.png.mcmeta index 20efcbc319f..1e13a18a0da 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/vibration_safe_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/vibration_safe_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/vibration_safe_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/vibration_safe_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/gcym/watertight_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/gcym/watertight_casing.png.mcmeta index 4a3033b0362..01c2c216764 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/gcym/watertight_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/gcym/watertight_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/gcym/watertight_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/gcym/watertight_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/back.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/back.png.mcmeta index 42e07d2dea7..184b499a8ba 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/back.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/back.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/advanced_computer_casing/back_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/advanced_computer_casing/back_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/bottom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/bottom.png.mcmeta index 8c187a0684a..8cd3c5a5935 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/bottom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/bottom.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/advanced_computer_casing/bottom_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/advanced_computer_casing/bottom_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/front.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/front.png.mcmeta index c57c972dc1c..5f54ab8dbe8 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/front.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/front.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/advanced_computer_casing/front_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/advanced_computer_casing/front_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/side.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/side.png.mcmeta index 961092b3f9e..7435e5af674 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/side.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/side.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/advanced_computer_casing/side_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/advanced_computer_casing/side_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/top.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/top.png.mcmeta index 7e23f5cded5..693c691f8d1 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/top.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/advanced_computer_casing/top.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/advanced_computer_casing/top_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/advanced_computer_casing/top_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/back.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/back.png.mcmeta index 5878953ae0d..6e6e8c6bb63 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/back.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/back.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/computer_casing/back_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/computer_casing/back_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/bottom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/bottom.png.mcmeta index 9fb2a643fdb..eddb4850067 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/bottom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/bottom.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/computer_casing/bottom_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/computer_casing/bottom_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/front.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/front.png.mcmeta index 303678ceb2d..ab496cd7ff0 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/front.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/front.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/computer_casing/front_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/computer_casing/front_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/side.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/side.png.mcmeta index cc1c5d48c57..7ad5ef7f1ea 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/side.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/side.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/computer_casing/side_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/computer_casing/side_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/top.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/top.png.mcmeta index d4805c14851..e5d8d808ff4 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/top.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_casing/top.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/computer_casing/top_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/computer_casing/top_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_heat_vent_side.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_heat_vent_side.png.mcmeta index c50ce958d8a..714dd86272f 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_heat_vent_side.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_heat_vent_side.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/computer_heat_vent_side_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/computer_heat_vent_side_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_heat_vent_top_bot.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_heat_vent_top_bot.png.mcmeta index f41eea02b1d..a5dbe2bc9c0 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_heat_vent_top_bot.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/computer_heat_vent_top_bot.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/computer_heat_vent_top_bot_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/computer_heat_vent_top_bot_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/hpca/high_power_casing.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/hpca/high_power_casing.png.mcmeta index 787770c3abd..07dec6c8212 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/hpca/high_power_casing.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/hpca/high_power_casing.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/hpca/high_power_casing_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/hpca/high_power_casing_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_assembly_line_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_assembly_line_bloom.png.mcmeta index f2e939b3527..a3edcb551d9 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_assembly_line_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_assembly_line_bloom.png.mcmeta @@ -2,10 +2,7 @@ "animation":{ "frametime":2 }, - "ldlib": { - "emissive": true - }, - "shimmer": { + "gtceu": { "bloom": true } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_stainless_steel.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_stainless_steel.png.mcmeta index aa9b988334d..5e2dd444e27 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_stainless_steel.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_stainless_steel.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/mechanic/machine_casing_turbine_stainless_steel_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/mechanic/machine_casing_turbine_stainless_steel_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_steel.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_steel.png.mcmeta index a7fd421b3b3..72c1a53ba16 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_steel.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_steel.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/mechanic/machine_casing_turbine_steel_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/mechanic/machine_casing_turbine_steel_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_titanium.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_titanium.png.mcmeta index 728b371f290..a79cc793f76 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_titanium.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_titanium.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/mechanic/machine_casing_turbine_titanium_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/mechanic/machine_casing_turbine_titanium_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_tungstensteel.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_tungstensteel.png.mcmeta index 4a128ac164e..d23695359ad 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_tungstensteel.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/mechanic/machine_casing_turbine_tungstensteel.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/mechanic/machine_casing_turbine_tungstensteel_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/mechanic/machine_casing_turbine_tungstensteel_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_a.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_a.png.mcmeta index 7e7c3fcc388..edb2af3afa7 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_a.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_a.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/signs/machine_casing_stripes_a_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/signs/machine_casing_stripes_a_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_b.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_b.png.mcmeta index 41f9c4fca66..1e4a835fdfd 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_b.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_b.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/signs/machine_casing_stripes_b_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/signs/machine_casing_stripes_b_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_c.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_c.png.mcmeta index 24ae068cdf3..58c74e507cf 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_c.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_c.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/signs/machine_casing_stripes_c_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/signs/machine_casing_stripes_c_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_d.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_d.png.mcmeta index be0c3b09523..31d57035871 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_d.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/signs/machine_casing_stripes_d.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/signs/machine_casing_stripes_d_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/signs/machine_casing_stripes_d_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/bottom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/bottom.png.mcmeta index 752d89be69b..27d8682d91a 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/bottom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/bottom.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/slicing_blades/bottom_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/slicing_blades/bottom_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/side.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/side.png.mcmeta index 2e013feb3a1..92fe24d573a 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/side.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/side.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/slicing_blades/side_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/slicing_blades/side_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/top.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/top.png.mcmeta index fe5e643f07c..7716663f87c 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/top.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/slicing_blades/top.png.mcmeta @@ -1,6 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/slicing_blades/top_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/slicing_blades/top_ctm" }, "animation": { "interpolate": false, diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_bronze_plated_bricks.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_bronze_plated_bricks.png.mcmeta index 84d6ac55955..f7bc18370f4 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_bronze_plated_bricks.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_bronze_plated_bricks.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_bronze_plated_bricks_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_bronze_plated_bricks_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_clean_stainless_steel.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_clean_stainless_steel.png.mcmeta index 87b382c8442..37fdc7ef59f 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_clean_stainless_steel.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_clean_stainless_steel.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_clean_stainless_steel_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_clean_stainless_steel_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_frost_proof.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_frost_proof.png.mcmeta index 06e68458b87..063daa7f6df 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_frost_proof.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_frost_proof.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_frost_proof_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_frost_proof_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_heatproof.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_heatproof.png.mcmeta index 46a7987cfed..6a69dafbaed 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_heatproof.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_heatproof.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_heatproof_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_heatproof_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_inert_ptfe.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_inert_ptfe.png.mcmeta index df90ab84c03..af024fa07e3 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_inert_ptfe.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_inert_ptfe.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_inert_ptfe_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_inert_ptfe_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_palladium_substation.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_palladium_substation.png.mcmeta index 7cdf09342f4..6960d04e965 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_palladium_substation.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_palladium_substation.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_palladium_substation_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_palladium_substation_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_robust_tungstensteel.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_robust_tungstensteel.png.mcmeta index 854f8df3dbe..1a2b15bb41b 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_robust_tungstensteel.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_robust_tungstensteel.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_robust_tungstensteel_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_robust_tungstensteel_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_solid_steel.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_solid_steel.png.mcmeta index 12cc1053c71..ad374a7d98d 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_solid_steel.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_solid_steel.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_solid_steel_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_solid_steel_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stable_titanium.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stable_titanium.png.mcmeta index 97014a06a14..bb8fdf80156 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stable_titanium.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stable_titanium.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_stable_titanium_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_stable_titanium_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation.png.mcmeta index 53b118fbefe..e5b5ae4c3e4 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_stainless_evaporation_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_stainless_evaporation_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_sturdy_hsse.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_sturdy_hsse.png.mcmeta index 225285146b7..6299e80252e 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_sturdy_hsse.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_sturdy_hsse.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_sturdy_hsse_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_sturdy_hsse_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_sturdy_hsse_green.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_sturdy_hsse_green.png.mcmeta index 225285146b7..6299e80252e 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_sturdy_hsse_green.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_sturdy_hsse_green.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/solid/machine_casing_sturdy_hsse_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/solid/machine_casing_sturdy_hsse_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/transparent/cleanroom_glass.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/transparent/cleanroom_glass.png.mcmeta index 4e88ec7cc0c..26a4910f29a 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/transparent/cleanroom_glass.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/transparent/cleanroom_glass.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/transparent/cleanroom_glass_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/transparent/cleanroom_glass_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/transparent/fusion_glass.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/transparent/fusion_glass.png.mcmeta index d193e57fef1..6264f382525 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/transparent/fusion_glass.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/transparent/fusion_glass.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/transparent/fusion_glass_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/transparent/fusion_glass_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/transparent/laminated_glass.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/transparent/laminated_glass.png.mcmeta index 0a0ee21c685..b4319b49730 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/transparent/laminated_glass.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/transparent/laminated_glass.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/transparent/laminated_glass_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/transparent/laminated_glass_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/transparent/tempered_glass.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/transparent/tempered_glass.png.mcmeta index 502bb849399..ff94fb81b10 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/transparent/tempered_glass.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/transparent/tempered_glass.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/transparent/tempered_glass_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/transparent/tempered_glass_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/unique/crushing_wheels.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/unique/crushing_wheels.png.mcmeta index 17b629c309c..71c9206ffbd 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/unique/crushing_wheels.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/unique/crushing_wheels.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/unique/crushing_wheels_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/unique/crushing_wheels_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/unique/crushing_wheels_active.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/unique/crushing_wheels_active.png.mcmeta index cbe1abf13b7..b4a2ed95093 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/unique/crushing_wheels_active.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/unique/crushing_wheels_active.png.mcmeta @@ -1,6 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/unique/crushing_wheels_active_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/unique/crushing_wheels_active_ctm" }, "animation": { "interpolate": false, diff --git a/src/main/resources/assets/gtceu/textures/block/casings/unique/heat_vent_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/unique/heat_vent_bloom.png.mcmeta index 89d89e9d079..8d624c1275a 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/unique/heat_vent_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/unique/heat_vent_bloom.png.mcmeta @@ -2,7 +2,7 @@ "animation": { "frametime": 1 }, - "shimmer": { + "gtceu": { "bloom": true } } diff --git a/src/main/resources/assets/gtceu/textures/block/casings/unique/slicing_blades.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/unique/slicing_blades.png.mcmeta index 39765a1c5d6..60a0eb8b058 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/unique/slicing_blades.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/unique/slicing_blades.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/casings/unique/slicing_blades_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/unique/slicing_blades_ctm" } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/casings/unique/slicing_blades_active.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/unique/slicing_blades_active.png.mcmeta index 1440c3a3821..721f4cb651e 100644 --- a/src/main/resources/assets/gtceu/textures/block/casings/unique/slicing_blades_active.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/casings/unique/slicing_blades_active.png.mcmeta @@ -1,6 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/casings/unique/slicing_blades_active_ctm" + "gtceu": { + "connection_texture": "gtceu:block/casings/unique/slicing_blades_active_ctm" }, "animation": { "interpolate": false, diff --git a/src/main/resources/assets/gtceu/textures/block/ctm_test.png b/src/main/resources/assets/gtceu/textures/block/ctm_test.png new file mode 100644 index 00000000000..88ea914d2f3 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/ctm_test.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/ctm_test.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/ctm_test.png.mcmeta new file mode 100644 index 00000000000..34afddbda20 --- /dev/null +++ b/src/main/resources/assets/gtceu/textures/block/ctm_test.png.mcmeta @@ -0,0 +1,5 @@ +{ + "gtceu": { + "connection_texture": "gtceu:block/ctm_test_ctm" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/ctm_test_ctm.png b/src/main/resources/assets/gtceu/textures/block/ctm_test_ctm.png new file mode 100644 index 00000000000..7e4b5d08300 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/ctm_test_ctm.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/black_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/black_bloom.png.mcmeta index ff453012c57..c301a7a8f5a 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/black_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/black_bloom.png.mcmeta @@ -1,9 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/black_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/black_bloom_ctm", "bloom": true } -} - +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/black_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/black_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/black_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/black_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/black_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/black_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/black_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/black_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/black_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/black_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/black_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/black_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/black_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/black_off.png.mcmeta index 28943d615fd..d540f92e9d4 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/black_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/black_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/black_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/black_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/black_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/black_on.png.mcmeta index 5c13fcde49a..12347ec4d5f 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/black_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/black_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/black_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/black_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/black_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/black_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/black_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/black_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/blue_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/blue_bloom.png.mcmeta index 313de4456f9..c889309fb30 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/blue_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/blue_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/blue_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/blue_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/blue_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/blue_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/blue_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/blue_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/blue_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/blue_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/blue_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/blue_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/blue_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/blue_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/blue_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/blue_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/blue_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/blue_off.png.mcmeta index e6c3f4b96e9..623d823821b 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/blue_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/blue_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/blue_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/blue_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/blue_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/blue_on.png.mcmeta index 116a33b1c75..ec7799a58b0 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/blue_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/blue_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/blue_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/blue_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/blue_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/blue_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/blue_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/blue_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/brown_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/brown_bloom.png.mcmeta index 5db8b403bd9..1e23d5f8fb0 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/brown_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/brown_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/brown_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/brown_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/brown_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/brown_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/brown_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/brown_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/brown_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/brown_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/brown_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/brown_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/brown_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/brown_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/brown_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/brown_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/brown_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/brown_off.png.mcmeta index 8115cf5c3cb..1eff63925b0 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/brown_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/brown_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/brown_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/brown_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/brown_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/brown_on.png.mcmeta index 16ca1f1305f..2d910f7b266 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/brown_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/brown_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/brown_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/brown_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/brown_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/brown_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/brown_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/brown_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_bloom.png.mcmeta index 65522bdc8fb..9eab8949a7c 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/cyan_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/cyan_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_off.png.mcmeta index edcb44542fe..251dd85873d 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/cyan_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/cyan_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_on.png.mcmeta index 1e35d272972..d04fd0d6097 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/cyan_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/cyan_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/cyan_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/cyan_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/gray_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/gray_bloom.png.mcmeta index ce76a054ea7..0299bf9dc14 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/gray_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/gray_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/gray_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/gray_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/gray_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/gray_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/gray_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/gray_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/gray_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/gray_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/gray_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/gray_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/gray_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/gray_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/gray_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/gray_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/gray_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/gray_off.png.mcmeta index 3ec9391d805..5196d6cddbb 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/gray_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/gray_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/gray_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/gray_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/gray_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/gray_on.png.mcmeta index cbc26838129..9943bf7c836 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/gray_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/gray_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/gray_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/gray_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/gray_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/gray_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/gray_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/gray_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/green_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/green_bloom.png.mcmeta index 38fe7740e76..2a60822bd60 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/green_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/green_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/green_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/green_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/green_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/green_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/green_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/green_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/green_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/green_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/green_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/green_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/green_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/green_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/green_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/green_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/green_ctm_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/green_ctm_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/green_ctm_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/green_ctm_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/green_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/green_off.png.mcmeta index 34ae9f7ae18..3ee9471d4cf 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/green_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/green_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/green_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/green_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/green_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/green_on.png.mcmeta index 6074941a516..85469151a79 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/green_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/green_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/green_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/green_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_bloom.png.mcmeta index 00958024c4a..b4f85d2b175 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/light_blue_ctm_emissive" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/light_blue_ctm_emissive", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_off.png.mcmeta index 4bcde263e5f..ebc03338d1d 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/light_blue_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/light_blue_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_on.png.mcmeta index dafb5e4a108..97a3aa4b3ca 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/light_blue_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/light_blue_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_blue_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_bloom.png.mcmeta index 3b30d57e8c1..52d15b67196 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/light_gray_ctm_emissive" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/light_gray_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_off.png.mcmeta index 5cfccb7226f..32ae60ef967 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/light_gray_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/light_gray_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_on.png.mcmeta index 3761d1c9e64..f8cdf3acb09 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/light_gray_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/light_gray_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/light_gray_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/lime_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/lime_bloom.png.mcmeta index 4b238ac69c1..3cdad29c52f 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/lime_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/lime_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/lime_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/lime_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/lime_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/lime_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/lime_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/lime_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/lime_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/lime_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/lime_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/lime_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/lime_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/lime_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/lime_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/lime_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/lime_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/lime_off.png.mcmeta index 52dfcbae47c..6bb707d9745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/lime_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/lime_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/lime_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/lime_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/lime_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/lime_on.png.mcmeta index 41bab1624eb..761e6e27029 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/lime_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/lime_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/lime_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/lime_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/lime_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/lime_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/lime_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/lime_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_bloom.png.mcmeta index b4e1d4d53b6..8f0f1bde4df 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/magenta_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/magenta_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_off.png.mcmeta index 5809d1c23a4..eb754db1014 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/magenta_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/magenta_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_on.png.mcmeta index 0278b6ccc48..a485f4942bd 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/magenta_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/magenta_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/magenta_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/magenta_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/orange_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/orange_bloom.png.mcmeta index eb9d61c06c6..b163cbbcb96 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/orange_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/orange_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/orange_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/orange_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/orange_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/orange_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/orange_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/orange_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/orange_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/orange_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/orange_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/orange_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/orange_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/orange_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/orange_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/orange_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/orange_ctm_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/orange_ctm_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/orange_ctm_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/orange_ctm_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/orange_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/orange_off.png.mcmeta index eabf6bb2656..c790daf2e7d 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/orange_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/orange_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/orange_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/orange_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/orange_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/orange_on.png.mcmeta index 17eea4ce1ed..d0e1825998f 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/orange_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/orange_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/orange_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/orange_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/pink_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/pink_bloom.png.mcmeta index 29c10bfe24d..1a5c77f6d2b 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/pink_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/pink_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/pink_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/pink_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/pink_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/pink_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/pink_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/pink_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/pink_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/pink_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/pink_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/pink_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/pink_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/pink_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/pink_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/pink_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/pink_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/pink_off.png.mcmeta index ce444d36c89..df209795670 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/pink_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/pink_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/pink_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/pink_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/pink_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/pink_on.png.mcmeta index cf9b95eb37d..0bc33c2b6e5 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/pink_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/pink_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/pink_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/pink_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/pink_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/pink_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/pink_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/pink_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/purple_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/purple_bloom.png.mcmeta index 942e844eaa7..a99d5e93fd9 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/purple_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/purple_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/purple_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/purple_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/purple_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/purple_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/purple_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/purple_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/purple_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/purple_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/purple_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/purple_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/purple_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/purple_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/purple_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/purple_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/purple_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/purple_off.png.mcmeta index 067da7a4996..c23cbdc43e8 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/purple_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/purple_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/purple_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/purple_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/purple_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/purple_on.png.mcmeta index e2f7fcfda8a..d9a7215ea62 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/purple_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/purple_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/purple_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/purple_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/purple_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/purple_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/purple_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/purple_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/red_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/red_bloom.png.mcmeta index 70de0198151..e7bc790288d 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/red_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/red_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/red_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/red_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/red_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/red_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/red_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/red_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/red_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/red_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/red_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/red_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/red_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/red_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/red_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/red_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/red_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/red_off.png.mcmeta index be15cc2a979..a8f33bceb6d 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/red_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/red_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/red_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/red_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/red_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/red_on.png.mcmeta index bb34744e74d..b0d0d50508e 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/red_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/red_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/red_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/red_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/red_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/red_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/red_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/red_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/white_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/white_bloom.png.mcmeta index 8a579d67dd6..19bf97f06f1 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/white_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/white_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/white_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/white_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/white_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/white_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/white_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/white_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/white_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/white_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/white_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/white_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/white_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/white_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/white_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/white_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/white_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/white_off.png.mcmeta index 2c90d5cde00..5d2e3d36601 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/white_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/white_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/white_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/white_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/white_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/white_on.png.mcmeta index 9c7a3a147a8..a3c0b0de9d9 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/white_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/white_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/white_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/white_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/white_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/white_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/white_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/white_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_bloom.png.mcmeta index 99638cdc659..93d4e56f77c 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_bloom.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/yellow_bloom_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/yellow_bloom_ctm", "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_bloom_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_bloom_ctm.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_bloom_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_bloom_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_borderless_bloom.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_borderless_bloom.png.mcmeta index 4da3f5f1299..c29eace5074 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_borderless_bloom.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_borderless_bloom.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": true } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_borderless_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_borderless_on.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_borderless_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_borderless_on.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_off.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_off.png.mcmeta index d582a53eb12..09f1c035f6b 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_off.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_off.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/yellow_off_ctm" + "gtceu": { + "connection_texture": "gtceu:block/lamps/yellow_off_ctm" } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_on.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_on.png.mcmeta index ebf371f8d42..57f5d1f2f42 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_on.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_on.png.mcmeta @@ -1,8 +1,6 @@ { - "ldlib": { - "connection": "gtceu:block/lamps/yellow_on_ctm" - }, - "shimmer": { + "gtceu": { + "connection_texture": "gtceu:block/lamps/yellow_on_ctm", "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_on_ctm.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_on_ctm.png.mcmeta index 4662e246aa1..7eef7f8b745 100644 --- a/src/main/resources/assets/gtceu/textures/block/lamps/yellow_on_ctm.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/lamps/yellow_on_ctm.png.mcmeta @@ -1,5 +1,5 @@ { - "shimmer": { + "gtceu": { "bloom": false } -} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/overlay/machine/overlay_monitor.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/overlay/machine/overlay_monitor.png.mcmeta index 38c2c75c408..deb8a6cb565 100644 --- a/src/main/resources/assets/gtceu/textures/block/overlay/machine/overlay_monitor.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/overlay/machine/overlay_monitor.png.mcmeta @@ -1,5 +1,5 @@ { - "ldlib": { - "connection": "gtceu:block/overlay/machine/overlay_monitor_ctm" + "gtceu": { + "connection_texture": "gtceu:block/overlay/machine/overlay_monitor_ctm" } } diff --git a/src/main/resources/assets/gtceu/textures/block/pipe/ld_fluid_pipe/overlay_emissive.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/pipe/ld_fluid_pipe/overlay_emissive.png.mcmeta index 53a9815890b..352db4d3be4 100644 --- a/src/main/resources/assets/gtceu/textures/block/pipe/ld_fluid_pipe/overlay_emissive.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/pipe/ld_fluid_pipe/overlay_emissive.png.mcmeta @@ -1,8 +1,5 @@ { - "ldlib": { - "emissive": true - }, - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/pipe/ld_item_pipe/overlay_emissive.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/pipe/ld_item_pipe/overlay_emissive.png.mcmeta index 53a9815890b..352db4d3be4 100644 --- a/src/main/resources/assets/gtceu/textures/block/pipe/ld_item_pipe/overlay_emissive.png.mcmeta +++ b/src/main/resources/assets/gtceu/textures/block/pipe/ld_item_pipe/overlay_emissive.png.mcmeta @@ -1,8 +1,5 @@ { - "ldlib": { - "emissive": true - }, - "shimmer": { + "gtceu": { "bloom": true } } \ No newline at end of file diff --git a/src/main/resources/gtceu.mixins.json b/src/main/resources/gtceu.mixins.json index 84336bfed86..8f990fbaa9a 100644 --- a/src/main/resources/gtceu.mixins.json +++ b/src/main/resources/gtceu.mixins.json @@ -17,9 +17,11 @@ "client.GuiHeartTypeMixin", "client.HumanoidArmorLayerMixin", "client.LevelRendererMixin", + "client.ModelBakerImplMixin", "client.ModelManagerMixin", "client.MultiPlayerGameModeMixin", "client.PlayerInfoAccessor", + "client.TextureAtlasMixin", "client.VariantDeserializerMixin", "dev.client.KeyboardHandlerMixin", "ftbchunks.FTBChunksClientMixin", @@ -54,6 +56,7 @@ "PotionBrewingAccessor", "PrimedTntAccessor", "RecipeManagerMixin", + "ReloadableResourceManagerAccessor", "RepairItemRecipeMixin", "ServerChunkProviderMixin", "ServerGamePacketListenerImplAccessor",