From 202485332bfc16ff43763c7778d37355a683d569 Mon Sep 17 00:00:00 2001 From: Maik Marschner Date: Sun, 3 May 2026 18:39:50 +0200 Subject: [PATCH 1/3] Add sulfur spikes. --- .../chunky/block/MinecraftBlockProvider.java | 3 ++ .../block/minecraft/PointedDripstone.java | 40 +++++++------------ .../chunky/block/minecraft/SulfurSpike.java | 37 +++++++++++++++++ .../se/llbit/chunky/resources/Texture.java | 20 ++++++++++ 4 files changed, 74 insertions(+), 26 deletions(-) create mode 100644 chunky/src/java/se/llbit/chunky/block/minecraft/SulfurSpike.java diff --git a/chunky/src/java/se/llbit/chunky/block/MinecraftBlockProvider.java b/chunky/src/java/se/llbit/chunky/block/MinecraftBlockProvider.java index b6b0c78d4..b42972cf5 100644 --- a/chunky/src/java/se/llbit/chunky/block/MinecraftBlockProvider.java +++ b/chunky/src/java/se/llbit/chunky/block/MinecraftBlockProvider.java @@ -1266,6 +1266,9 @@ private static void addBlock(String name, Texture texture) { addBlock("polished_sulfur_slab", (name, tag) -> slab(tag, Texture.polishedSulfur)); addBlock("polished_sulfur_stairs", (name, tag) -> stairs(tag, Texture.polishedSulfur)); addBlock("polished_sulfur_wall", (name, tag) -> wall(tag, Texture.polishedSulfur)); + addBlock("sulfur_spike", (name, tag) -> new SulfurSpike( + tag.get("Properties").get("thickness").stringValue("tip"), + tag.get("Properties").get("vertical_direction").stringValue("up"))); } @Override diff --git a/chunky/src/java/se/llbit/chunky/block/minecraft/PointedDripstone.java b/chunky/src/java/se/llbit/chunky/block/minecraft/PointedDripstone.java index 83192113d..7560cf66b 100644 --- a/chunky/src/java/se/llbit/chunky/block/minecraft/PointedDripstone.java +++ b/chunky/src/java/se/llbit/chunky/block/minecraft/PointedDripstone.java @@ -30,33 +30,21 @@ public PointedDripstone(String thickness, String verticalDirection) { private static Texture getTexture(String thickness, String verticalDirection) { if (verticalDirection.equals("down")) { - switch (thickness) { - case "tip_merge": - return Texture.pointedDripstoneDownTipMerge; - case "frustum": - return Texture.pointedDripstoneDownFrustum; - case "middle": - return Texture.pointedDripstoneDownMiddle; - case "base": - return Texture.pointedDripstoneDownBase; - default: - case "tip": - return Texture.pointedDripstoneDownTip; - } + return switch (thickness) { + case "tip_merge" -> Texture.pointedDripstoneDownTipMerge; + case "frustum" -> Texture.pointedDripstoneDownFrustum; + case "middle" -> Texture.pointedDripstoneDownMiddle; + case "base" -> Texture.pointedDripstoneDownBase; + default -> Texture.pointedDripstoneDownTip; // tip + }; } else { - switch (thickness) { - case "tip_merge": - return Texture.pointedDripstoneUpTipMerge; - case "frustum": - return Texture.pointedDripstoneUpFrustum; - case "middle": - return Texture.pointedDripstoneUpMiddle; - case "base": - return Texture.pointedDripstoneUpBase; - default: - case "tip": - return Texture.pointedDripstoneUpTip; - } + return switch (thickness) { + case "tip_merge" -> Texture.pointedDripstoneUpTipMerge; + case "frustum" -> Texture.pointedDripstoneUpFrustum; + case "middle" -> Texture.pointedDripstoneUpMiddle; + case "base" -> Texture.pointedDripstoneUpBase; + default -> Texture.pointedDripstoneUpTip; // tip + }; } } diff --git a/chunky/src/java/se/llbit/chunky/block/minecraft/SulfurSpike.java b/chunky/src/java/se/llbit/chunky/block/minecraft/SulfurSpike.java new file mode 100644 index 000000000..e54bd91e9 --- /dev/null +++ b/chunky/src/java/se/llbit/chunky/block/minecraft/SulfurSpike.java @@ -0,0 +1,37 @@ +package se.llbit.chunky.block.minecraft; + +import se.llbit.chunky.resources.Texture; + +public class SulfurSpike extends SpriteBlock { + private final String description; + + public SulfurSpike(String thickness, String verticalDirection) { + super("sulfur_spike", getTexture(thickness, verticalDirection)); + description = "thickness=" + thickness + ", vertical_direction=" + verticalDirection; + } + + private static Texture getTexture(String thickness, String verticalDirection) { + if (verticalDirection.equals("down")) { + return switch (thickness) { + case "tip_merge" -> Texture.sulfurSpikeDownTipMerge; + case "frustum" -> Texture.sulfurSpikeDownFrustum; + case "middle" -> Texture.sulfurSpikeDownMiddle; + case "base" -> Texture.sulfurSpikeDownBase; + default -> Texture.sulfurSpikeDownTip; // tip + }; + } else { + return switch (thickness) { + case "tip_merge" -> Texture.sulfurSpikeUpTipMerge; + case "frustum" -> Texture.sulfurSpikeUpFrustum; + case "middle" -> Texture.sulfurSpikeUpMiddle; + case "base" -> Texture.sulfurSpikeUpBase; + default -> Texture.sulfurSpikeUpTip; // tip + }; + } + } + + @Override + public String description() { + return description; + } +} diff --git a/chunky/src/java/se/llbit/chunky/resources/Texture.java b/chunky/src/java/se/llbit/chunky/resources/Texture.java index 2f3655672..ff1d07250 100644 --- a/chunky/src/java/se/llbit/chunky/resources/Texture.java +++ b/chunky/src/java/se/llbit/chunky/resources/Texture.java @@ -1753,6 +1753,26 @@ public class Texture { public static final Texture potentSulfur = new Texture(); @TexturePath("assets/minecraft/textures/block/polished_sulfur") public static final Texture polishedSulfur = new Texture(); + @TexturePath("assets/minecraft/textures/block/sulfur_spike_down_base") + public static final Texture sulfurSpikeDownBase = new Texture(); + @TexturePath("assets/minecraft/textures/block/sulfur_spike_down_frustum") + public static final Texture sulfurSpikeDownFrustum = new Texture(); + @TexturePath("assets/minecraft/textures/block/sulfur_spike_down_middle") + public static final Texture sulfurSpikeDownMiddle = new Texture(); + @TexturePath("assets/minecraft/textures/block/sulfur_spike_down_tip") + public static final Texture sulfurSpikeDownTip = new Texture(); + @TexturePath("assets/minecraft/textures/block/sulfur_spike_down_tip_merge") + public static final Texture sulfurSpikeDownTipMerge = new Texture(); + @TexturePath("assets/minecraft/textures/block/sulfur_spike_up_base") + public static final Texture sulfurSpikeUpBase = new Texture(); + @TexturePath("assets/minecraft/textures/block/sulfur_spike_up_frustum") + public static final Texture sulfurSpikeUpFrustum = new Texture(); + @TexturePath("assets/minecraft/textures/block/sulfur_spike_up_middle") + public static final Texture sulfurSpikeUpMiddle = new Texture(); + @TexturePath("assets/minecraft/textures/block/sulfur_spike_up_tip") + public static final Texture sulfurSpikeUpTip = new Texture(); + @TexturePath("assets/minecraft/textures/block/sulfur_spike_up_tip_merge") + public static final Texture sulfurSpikeUpTipMerge = new Texture(); @TexturePath("assets/minecraft/textures/entity/equipment/wings/elytra") public static final Texture elytra = new Texture(); From 35e8a1b55ca1dc10c2c40924d0d7f0135d8b82dc Mon Sep 17 00:00:00 2001 From: Maik Marschner Date: Thu, 14 May 2026 22:28:41 +0200 Subject: [PATCH 2/3] Add the new bed models and refactor loading bed textures to map old textures to the new format. --- .../chunky/block/MinecraftBlockProvider.java | 5 +- .../se/llbit/chunky/block/minecraft/Bed.java | 21 +- .../chunky/model/minecraft/BedFootModel.java | 126 ++++++++++ .../chunky/model/minecraft/BedHeadModel.java | 126 ++++++++++ .../chunky/model/minecraft/BedModel.java | 215 ------------------ .../llbit/chunky/resources/BitmapImage.java | 43 +++- .../se/llbit/chunky/resources/Texture.java | 33 +-- .../chunky/resources/TexturePackLoader.java | 65 +++--- .../resources/texturepack/BedTexture.java | 63 +++++ ...dapter.java => BedTextureAdapter1_12.java} | 149 ++++++------ .../texturepack/BedTextureAdapter26_2.java | 107 +++++++++ 11 files changed, 594 insertions(+), 359 deletions(-) create mode 100644 chunky/src/java/se/llbit/chunky/model/minecraft/BedFootModel.java create mode 100644 chunky/src/java/se/llbit/chunky/model/minecraft/BedHeadModel.java delete mode 100644 chunky/src/java/se/llbit/chunky/model/minecraft/BedModel.java create mode 100644 chunky/src/java/se/llbit/chunky/resources/texturepack/BedTexture.java rename chunky/src/java/se/llbit/chunky/resources/texturepack/{BedTextureAdapter.java => BedTextureAdapter1_12.java} (62%) create mode 100644 chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter26_2.java diff --git a/chunky/src/java/se/llbit/chunky/block/MinecraftBlockProvider.java b/chunky/src/java/se/llbit/chunky/block/MinecraftBlockProvider.java index b42972cf5..d6607f718 100644 --- a/chunky/src/java/se/llbit/chunky/block/MinecraftBlockProvider.java +++ b/chunky/src/java/se/llbit/chunky/block/MinecraftBlockProvider.java @@ -10,6 +10,7 @@ import se.llbit.chunky.model.minecraft.FlowerPotModel; import se.llbit.chunky.resources.ShulkerTexture; import se.llbit.chunky.resources.Texture; +import se.llbit.chunky.resources.texturepack.BedTexture; import se.llbit.nbt.ListTag; import se.llbit.nbt.Tag; @@ -2485,7 +2486,7 @@ public Block getBlockByTag(String namespacedName, Tag tag) { case "gray_bed": return bed(tag, Texture.bedGray); case "light_gray_bed": - return bed(tag, Texture.bedSilver); + return bed(tag, Texture.bedLightGray); case "cyan_bed": return bed(tag, Texture.bedCyan); case "purple_bed": @@ -3283,7 +3284,7 @@ private static Block glazedTerracotta(Tag tag, Texture texture) { return new GlazedTerracotta(name, texture, facing); } - private static Block bed(Tag tag, Texture texture) { + private static Block bed(Tag tag, BedTexture.Textures texture) { String name = BlockProvider.blockName(tag); String part = tag.get("Properties").get("part").stringValue("head"); String facing = BlockProvider.facing(tag, "south"); diff --git a/chunky/src/java/se/llbit/chunky/block/minecraft/Bed.java b/chunky/src/java/se/llbit/chunky/block/minecraft/Bed.java index 9160c0943..c877f1b5d 100644 --- a/chunky/src/java/se/llbit/chunky/block/minecraft/Bed.java +++ b/chunky/src/java/se/llbit/chunky/block/minecraft/Bed.java @@ -19,34 +19,37 @@ package se.llbit.chunky.block.minecraft; import se.llbit.chunky.block.AbstractModelBlock; -import se.llbit.chunky.model.minecraft.BedModel; -import se.llbit.chunky.resources.Texture; +import se.llbit.chunky.model.minecraft.BedFootModel; +import se.llbit.chunky.model.minecraft.BedHeadModel; +import se.llbit.chunky.resources.texturepack.BedTexture; public class Bed extends AbstractModelBlock { private final String description; - public Bed(String name, Texture texture, String part, String facing) { - super(name, texture); + public Bed(String name, BedTexture.Textures texture, String part, String facing) { + super(name, part.equals("head") ? texture.headUp : texture.footUp); this.description = String.format("part=%s, facing=%s", part, facing); boolean head = part.equals("head"); int direction; switch (facing) { default: case "north": - direction = 2; + direction = 0; break; case "east": - direction = 3; + direction = 1; break; case "south": - direction = 0; + direction = 2; break; case "west": - direction = 1; + direction = 3; break; } - model = new BedModel(head, direction, texture); + model = head + ? new BedHeadModel(direction, texture) + : new BedFootModel(direction, texture); solid = false; } diff --git a/chunky/src/java/se/llbit/chunky/model/minecraft/BedFootModel.java b/chunky/src/java/se/llbit/chunky/model/minecraft/BedFootModel.java new file mode 100644 index 000000000..6df2174bc --- /dev/null +++ b/chunky/src/java/se/llbit/chunky/model/minecraft/BedFootModel.java @@ -0,0 +1,126 @@ +package se.llbit.chunky.model.minecraft; + +import se.llbit.chunky.model.Model; +import se.llbit.chunky.model.QuadModel; +import se.llbit.chunky.resources.Texture; +import se.llbit.chunky.resources.texturepack.BedTexture; +import se.llbit.math.Quad; +import se.llbit.math.Vector3; +import se.llbit.math.Vector4; + +public class BedFootModel extends QuadModel { + private static final Quad[] quadsNorth = new Quad[]{ + new Quad( + new Vector3(0 / 16.0, 9 / 16.0, 16 / 16.0), + new Vector3(16 / 16.0, 9 / 16.0, 16 / 16.0), + new Vector3(0 / 16.0, 9 / 16.0, 0 / 16.0), + new Vector4(0 / 16.0, 16 / 16.0, 0 / 16.0, 16 / 16.0) + ), + new Quad( + new Vector3(0 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(16 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(0 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector4(0 / 16.0, 16 / 16.0, 0 / 16.0, 16 / 16.0) + ), + new Quad( + new Vector3(0 / 16.0, 9 / 16.0, 16 / 16.0), + new Vector3(0 / 16.0, 9 / 16.0, 0 / 16.0), + new Vector3(0 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector4(16 / 16.0, 0 / 16.0, 9 / 16.0, 3 / 16.0) + ), + new Quad( + new Vector3(16 / 16.0, 9 / 16.0, 0 / 16.0), + new Vector3(16 / 16.0, 9 / 16.0, 16 / 16.0), + new Vector3(16 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector4(16 / 16.0, 0 / 16.0, 9 / 16.0, 3 / 16.0) + ), + new Quad( + new Vector3(16 / 16.0, 9 / 16.0, 16 / 16.0), + new Vector3(0 / 16.0, 9 / 16.0, 16 / 16.0), + new Vector3(16 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector4(16 / 16.0, 0 / 16.0, 9 / 16.0, 3 / 16.0) + ), + new Quad( + new Vector3(0 / 16.0, 0 / 16.0, 13 / 16.0), + new Vector3(3 / 16.0, 0 / 16.0, 13 / 16.0), + new Vector3(0 / 16.0, 0 / 16.0, 16 / 16.0), + new Vector4(7 / 16.0, 10 / 16.0, 0 / 16.0, 3 / 16.0) + ), + new Quad( + new Vector3(0 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector3(0 / 16.0, 3 / 16.0, 13 / 16.0), + new Vector3(0 / 16.0, 0 / 16.0, 16 / 16.0), + new Vector4(16 / 16.0, 13 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(3 / 16.0, 3 / 16.0, 13 / 16.0), + new Vector3(3 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector3(3 / 16.0, 0 / 16.0, 13 / 16.0), + new Vector4(6 / 16.0, 3 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(0 / 16.0, 3 / 16.0, 13 / 16.0), + new Vector3(3 / 16.0, 3 / 16.0, 13 / 16.0), + new Vector3(0 / 16.0, 0 / 16.0, 13 / 16.0), + new Vector4(13 / 16.0, 10 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(3 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector3(0 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector3(3 / 16.0, 0 / 16.0, 16 / 16.0), + new Vector4(3 / 16.0, 0 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(13 / 16.0, 0 / 16.0, 13 / 16.0), + new Vector3(16 / 16.0, 0 / 16.0, 13 / 16.0), + new Vector3(13 / 16.0, 0 / 16.0, 16 / 16.0), + new Vector4(6 / 16.0, 9 / 16.0, 0 / 16.0, 3 / 16.0) + ), + new Quad( + new Vector3(13 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector3(13 / 16.0, 3 / 16.0, 13 / 16.0), + new Vector3(13 / 16.0, 0 / 16.0, 16 / 16.0), + new Vector4(13 / 16.0, 10 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(16 / 16.0, 3 / 16.0, 13 / 16.0), + new Vector3(16 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector3(16 / 16.0, 0 / 16.0, 13 / 16.0), + new Vector4(3 / 16.0, 0 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(13 / 16.0, 3 / 16.0, 13 / 16.0), + new Vector3(16 / 16.0, 3 / 16.0, 13 / 16.0), + new Vector3(13 / 16.0, 0 / 16.0, 13 / 16.0), + new Vector4(6 / 16.0, 3 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(16 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector3(13 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector3(16 / 16.0, 0 / 16.0, 16 / 16.0), + new Vector4(16 / 16.0, 13 / 16.0, 3 / 16.0, 0 / 16.0) + ) + }; + + private final Texture[] textures; + private final Quad[] quads; + + public BedFootModel(int facing, BedTexture.Textures textures) { + this.textures = new Texture[]{ + textures.footUp, textures.footDown, textures.footWest, textures.footEast, + textures.footSouth, textures.footWest, textures.footWest, textures.footSouth, + textures.footWest, textures.footSouth, textures.footEast, textures.footSouth, + textures.footEast, textures.footEast, textures.footSouth}; + quads = Model.rotateY(quadsNorth, -Math.toRadians(90 * facing)); + } + + @Override + public Quad[] getQuads() { + return quads; + } + + @Override + public Texture[] getTextures() { + return textures; + } +} diff --git a/chunky/src/java/se/llbit/chunky/model/minecraft/BedHeadModel.java b/chunky/src/java/se/llbit/chunky/model/minecraft/BedHeadModel.java new file mode 100644 index 000000000..14931c309 --- /dev/null +++ b/chunky/src/java/se/llbit/chunky/model/minecraft/BedHeadModel.java @@ -0,0 +1,126 @@ +package se.llbit.chunky.model.minecraft; + +import se.llbit.chunky.model.Model; +import se.llbit.chunky.model.QuadModel; +import se.llbit.chunky.resources.Texture; +import se.llbit.chunky.resources.texturepack.BedTexture; +import se.llbit.math.Quad; +import se.llbit.math.Vector3; +import se.llbit.math.Vector4; + +public class BedHeadModel extends QuadModel { + private static final Quad[] quadsNorth = new Quad[]{ + new Quad( + new Vector3(0 / 16.0, 9 / 16.0, 16 / 16.0), + new Vector3(16 / 16.0, 9 / 16.0, 16 / 16.0), + new Vector3(0 / 16.0, 9 / 16.0, 0 / 16.0), + new Vector4(0 / 16.0, 16 / 16.0, 0 / 16.0, 16 / 16.0) + ), + new Quad( + new Vector3(0 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(16 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(0 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector4(0 / 16.0, 16 / 16.0, 0 / 16.0, 16 / 16.0) + ), + new Quad( + new Vector3(0 / 16.0, 9 / 16.0, 16 / 16.0), + new Vector3(0 / 16.0, 9 / 16.0, 0 / 16.0), + new Vector3(0 / 16.0, 3 / 16.0, 16 / 16.0), + new Vector4(16 / 16.0, 0 / 16.0, 9 / 16.0, 3 / 16.0) + ), + new Quad( + new Vector3(16 / 16.0, 9 / 16.0, 0 / 16.0), + new Vector3(16 / 16.0, 9 / 16.0, 16 / 16.0), + new Vector3(16 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector4(16 / 16.0, 0 / 16.0, 9 / 16.0, 3 / 16.0) + ), + new Quad( + new Vector3(0 / 16.0, 9 / 16.0, 0 / 16.0), + new Vector3(16 / 16.0, 9 / 16.0, 0 / 16.0), + new Vector3(0 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector4(16 / 16.0, 0 / 16.0, 9 / 16.0, 3 / 16.0) + ), + new Quad( + new Vector3(0 / 16.0, 0 / 16.0, 0 / 16.0), + new Vector3(3 / 16.0, 0 / 16.0, 0 / 16.0), + new Vector3(0 / 16.0, 0 / 16.0, 3 / 16.0), + new Vector4(6 / 16.0, 9 / 16.0, 0 / 16.0, 3 / 16.0) + ), + new Quad( + new Vector3(0 / 16.0, 3 / 16.0, 3 / 16.0), + new Vector3(0 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(0 / 16.0, 0 / 16.0, 3 / 16.0), + new Vector4(3 / 16.0, 0 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(3 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(3 / 16.0, 3 / 16.0, 3 / 16.0), + new Vector3(3 / 16.0, 0 / 16.0, 0 / 16.0), + new Vector4(13 / 16.0, 10 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(0 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(3 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(0 / 16.0, 0 / 16.0, 0 / 16.0), + new Vector4(16 / 16.0, 13 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(3 / 16.0, 3 / 16.0, 3 / 16.0), + new Vector3(0 / 16.0, 3 / 16.0, 3 / 16.0), + new Vector3(3 / 16.0, 0 / 16.0, 3 / 16.0), + new Vector4(6 / 16.0, 3 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(13 / 16.0, 0 / 16.0, 0 / 16.0), + new Vector3(16 / 16.0, 0 / 16.0, 0 / 16.0), + new Vector3(13 / 16.0, 0 / 16.0, 3 / 16.0), + new Vector4(7 / 16.0, 10 / 16.0, 0 / 16.0, 3 / 16.0) + ), + new Quad( + new Vector3(13 / 16.0, 3 / 16.0, 3 / 16.0), + new Vector3(13 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(13 / 16.0, 0 / 16.0, 3 / 16.0), + new Vector4(6 / 16.0, 3 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(16 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(16 / 16.0, 3 / 16.0, 3 / 16.0), + new Vector3(16 / 16.0, 0 / 16.0, 0 / 16.0), + new Vector4(16 / 16.0, 13 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(13 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(16 / 16.0, 3 / 16.0, 0 / 16.0), + new Vector3(13 / 16.0, 0 / 16.0, 0 / 16.0), + new Vector4(3 / 16.0, 0 / 16.0, 3 / 16.0, 0 / 16.0) + ), + new Quad( + new Vector3(16 / 16.0, 3 / 16.0, 3 / 16.0), + new Vector3(13 / 16.0, 3 / 16.0, 3 / 16.0), + new Vector3(16 / 16.0, 0 / 16.0, 3 / 16.0), + new Vector4(13 / 16.0, 10 / 16.0, 3 / 16.0, 0 / 16.0) + ) + }; + + private final Texture[] textures; + private final Quad[] quads; + + public BedHeadModel(int facing, BedTexture.Textures textures) { + this.textures = new Texture[]{ + textures.headUp, textures.headDown, textures.headWest, textures.headEast, + textures.headNorth, textures.headWest, textures.headWest, textures.headNorth, + textures.headNorth, textures.headWest, textures.headEast, textures.headNorth, + textures.headEast, textures.headNorth, textures.headEast}; + quads = Model.rotateY(quadsNorth, -Math.toRadians(90 * facing)); + } + + @Override + public Quad[] getQuads() { + return quads; + } + + @Override + public Texture[] getTextures() { + return textures; + } +} diff --git a/chunky/src/java/se/llbit/chunky/model/minecraft/BedModel.java b/chunky/src/java/se/llbit/chunky/model/minecraft/BedModel.java deleted file mode 100644 index defbdeed2..000000000 --- a/chunky/src/java/se/llbit/chunky/model/minecraft/BedModel.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2012-2023 Chunky contributors - * - * This file is part of Chunky. - * - * Chunky is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Chunky 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 Chunky. If not, see . - */ -package se.llbit.chunky.model.minecraft; - -import se.llbit.chunky.model.Model; -import se.llbit.chunky.model.QuadModel; -import se.llbit.chunky.resources.Texture; -import se.llbit.math.Quad; -import se.llbit.math.Vector3; -import se.llbit.math.Vector4; - -import java.util.Arrays; - -public class BedModel extends QuadModel { - //region Bed Foot - private static final Quad[] foot = { - // Mattress: - new Quad( - new Vector3(0, 9 / 16.0, 16 / 16.0), - new Vector3(16 / 16.0, 9 / 16.0, 16 / 16.0), - new Vector3(0, 9 / 16.0, 0), - new Vector4(22 / 64.0, 6 / 64.0, 36 / 64.0, 20 / 64.0)), - new Quad( - new Vector3(0, 3 / 16.0, 0), - new Vector3(16 / 16.0, 3 / 16.0, 0), - new Vector3(0, 3 / 16.0, 16 / 16.0), - new Vector4(28 / 64.0, 44 / 64.0, 20 / 64.0, 36 / 64.0)), - new Quad( - new Vector3(16 / 16.0, 9 / 16.0, 16 / 16.0), - new Vector3(16 / 16.0, 3 / 16.0, 16 / 16.0), - new Vector3(16 / 16.0, 9 / 16.0, 0), - new Vector4(6 / 64.0, 0, 36 / 64.0, 20 / 64.0)), - new Quad( - new Vector3(0, 3 / 16.0, 16 / 16.0), - new Vector3(0, 9 / 16.0, 16 / 16.0), - new Vector3(0, 3 / 16.0, 0), - new Vector4(28 / 64.0, 22 / 64.0, 36 / 64.0, 20 / 64.0)), - new Quad( - new Vector3(16 / 16.0, 3 / 16.0, 0), - new Vector3(0, 3 / 16.0, 0), - new Vector3(16 / 16.0, 9 / 16.0, 0), - new Vector4(22 / 64.0, 38 / 64.0, 42 / 64.0, 36 / 64.0)), - // Leg 1 (left when facing back end): - new Quad( - new Vector3(16 / 16.0, 0, 3 / 16.0), - new Vector3(13 / 16.0, 0, 3 / 16.0), - new Vector3(16 / 16.0, 0, 0), - new Vector4(56 / 64.0, 59 / 64.0, 52 / 64.0, 49 / 64.0)), - new Quad( - new Vector3(16 / 16.0, 0, 3 / 16.0), - new Vector3(16 / 16.0, 0, 0), - new Vector3(16 / 16.0, 3 / 16.0, 3 / 16.0), - new Vector4(50 / 64.0, 53 / 64.0, 61 / 64.0, 58 / 64.0)), - new Quad( - new Vector3(13 / 16.0, 0, 0), - new Vector3(13 / 16.0, 0, 3 / 16.0), - new Vector3(13 / 16.0, 3 / 16.0, 0), - new Vector4(56 / 64.0, 59 / 64.0, 61 / 64.0, 58 / 64.0)), - new Quad( - new Vector3(16 / 16.0, 0, 0), - new Vector3(13 / 16.0, 0, 0), - new Vector3(16 / 16.0, 3 / 16.0, 0), - new Vector4(53 / 64.0, 56 / 64.0, 61 / 64.0, 58 / 64.0)), - new Quad( - new Vector3(13 / 16.0, 0, 3 / 16.0), - new Vector3(16 / 16.0, 0, 3 / 16.0), - new Vector3(13 / 16.0, 3 / 16.0, 3 / 16.0), - new Vector4(59 / 64.0, 62 / 64.0, 61 / 64.0, 58 / 64.0)), - // Leg 3 (right when facing back end): - new Quad( - new Vector3(3 / 16.0, 0, 0), - new Vector3(3 / 16.0, 0, 3 / 16.0), - new Vector3(0, 0, 0), - new Vector4(56 / 64.0, 59 / 64.0, 52 / 64.0, 49 / 64.0)), - new Quad( - new Vector3(3 / 16.0, 0, 3 / 16.0), - new Vector3(3 / 16.0, 0, 0), - new Vector3(3 / 16.0, 3 / 16.0, 3 / 16.0), - new Vector4(59 / 64.0, 62 / 64.0, 49 / 64.0, 46 / 64.0)), - new Quad( - new Vector3(0, 0, 0), - new Vector3(0, 0, 3 / 16.0), - new Vector3(0, 3 / 16.0, 0), - new Vector4(53 / 64.0, 56 / 64.0, 49 / 64.0, 46 / 64.0)), - new Quad( - new Vector3(3 / 16.0, 0, 0), - new Vector3(0, 0, 0), - new Vector3(3 / 16.0, 3 / 16.0, 0), - new Vector4(50 / 64.0, 53 / 64.0, 49 / 64.0, 46 / 64.0)), - new Quad( - new Vector3(0, 0, 3 / 16.0), - new Vector3(3 / 16.0, 0, 3 / 16.0), - new Vector3(0, 3 / 16.0, 3 / 16.0), - new Vector4(56 / 64.0, 59 / 64.0, 49 / 64.0, 46 / 64.0)), - }; - //endregion - - //region Bed Head - private static final Quad[] head = { - // Mattress: - new Quad( - new Vector3(0, 9 / 16.0, 16 / 16.0), - new Vector3(16 / 16.0, 9 / 16.0, 16 / 16.0), - new Vector3(0, 9 / 16.0, 0), - new Vector4(22 / 64.0, 6 / 64.0, 58 / 64.0, 42 / 64.0)), - new Quad( - new Vector3(0, 3 / 16.0, 0), - new Vector3(16 / 16.0, 3 / 16.0, 0), - new Vector3(0, 3 / 16.0, 16 / 16.0), - new Vector4(28 / 64.0, 44 / 64.0, 58 / 64.0, 42 / 64.0)), - new Quad( - new Vector3(16 / 16.0, 9 / 16.0, 16 / 16.0), - new Vector3(16 / 16.0, 3 / 16.0, 16 / 16.0), - new Vector3(16 / 16.0, 9 / 16.0, 0), - new Vector4(6 / 64.0, 0 / 64.0, 58 / 64.0, 42 / 64.0)), - new Quad( - new Vector3(0, 3 / 16.0, 16 / 16.0), - new Vector3(0, 9 / 16.0, 16 / 16.0), - new Vector3(0, 3 / 16.0, 0), - new Vector4(0 / 64.0, 6 / 64.0, 58 / 64.0, 42 / 64.0)), - new Quad( - new Vector3(0, 3 / 16.0, 16 / 16.0), - new Vector3(16 / 16.0, 3 / 16.0, 16 / 16.0), - new Vector3(0, 9 / 16.0, 16 / 16.0), - new Vector4(6 / 64.0, 22 / 64.0, 64 / 64.0, 58 / 64.0)), - // Leg 4 (left when facing front end). - new Quad( - new Vector3(0, 0, 13 / 16.0), - new Vector3(3 / 16.0, 0, 13 / 16.0), - new Vector3(0, 0, 16 / 16.0), - new Vector4(56 / 64.0, 59 / 64.0, 61 / 64.0, 64 / 64.0)), - new Quad( - new Vector3(3 / 16.0, 0, 16 / 16.0), - new Vector3(3 / 16.0, 0, 13 / 16.0), - new Vector3(3 / 16.0, 3 / 16.0, 16 / 16.0), - new Vector4(56 / 64.0, 59 / 64.0, 40 / 64.0, 43 / 64.0)), - new Quad( - new Vector3(0, 0, 13 / 16.0), - new Vector3(0, 0, 16 / 16.0), - new Vector3(0, 3 / 16.0, 13 / 16.0), - new Vector4(50 / 64.0, 53 / 64.0, 40 / 64.0, 43 / 64.0)), - new Quad( - new Vector3(3 / 16.0, 0, 13 / 16.0), - new Vector3(0, 0, 13 / 16.0), - new Vector3(3 / 16.0, 3 / 16.0, 13 / 16.0), - new Vector4(59 / 64.0, 62 / 64.0, 40 / 64.0, 43 / 64.0)), - new Quad( - new Vector3(0, 0, 16 / 16.0), - new Vector3(3 / 16.0, 0, 16 / 16.0), - new Vector3(0, 3 / 16.0, 16 / 16.0), - new Vector4(53 / 64.0, 56 / 64.0, 40 / 64.0, 43 / 64.0)), - // Leg 2 (right when facing front end). - new Quad( - new Vector3(13 / 16.0, 0, 13 / 16.0), - new Vector3(16 / 16.0, 0, 13 / 16.0), - new Vector3(13 / 16.0, 0, 16 / 16.0), - new Vector4(56 / 64.0, 59 / 64.0, 61 / 64.0, 64 / 64.0)), - new Quad( - new Vector3(16 / 16.0, 0, 16 / 16.0), - new Vector3(16 / 16.0, 0, 13 / 16.0), - new Vector3(16 / 16.0, 3 / 16.0, 16 / 16.0), - new Vector4(53 / 64.0, 56 / 64.0, 52 / 64.0, 55 / 64.0)), - new Quad( - new Vector3(13 / 16.0, 0, 13 / 16.0), - new Vector3(13 / 16.0, 0, 16 / 16.0), - new Vector3(13 / 16.0, 3 / 16.0, 13 / 16.0), - new Vector4(59 / 64.0, 62 / 64.0, 52 / 64.0, 55 / 64.0)), - new Quad( - new Vector3(16 / 16.0, 0, 13 / 16.0), - new Vector3(13 / 16.0, 0, 13 / 16.0), - new Vector3(16 / 16.0, 3 / 16.0, 13 / 16.0), - new Vector4(56 / 64.0, 59 / 64.0, 52 / 64.0, 55 / 64.0)), - new Quad( - new Vector3(13 / 16.0, 0, 16 / 16.0), - new Vector3(16 / 16.0, 0, 16 / 16.0), - new Vector3(13 / 16.0, 3 / 16.0, 16 / 16.0), - new Vector4(50 / 64.0, 53 / 64.0, 52 / 64.0, 55 / 64.0)), - }; - //endregion - - private final Texture[] textures; - private final Quad[] quads; - - public BedModel(boolean isHead, int facing, Texture color) { - quads = Model.rotateY(isHead ? head : foot, -Math.toRadians(90 * facing)); - - textures = new Texture[quads.length]; - Arrays.fill(textures, color); - } - - @Override - public Quad[] getQuads() { - return quads; - } - - @Override - public Texture[] getTextures() { - return textures; - } -} diff --git a/chunky/src/java/se/llbit/chunky/resources/BitmapImage.java b/chunky/src/java/se/llbit/chunky/resources/BitmapImage.java index 50c7df3f5..9d4c1e277 100644 --- a/chunky/src/java/se/llbit/chunky/resources/BitmapImage.java +++ b/chunky/src/java/se/llbit/chunky/resources/BitmapImage.java @@ -78,19 +78,48 @@ public void blit(BitmapImage source, int x0, int y0) { } /** - * Copies a region of the source bitmap into this bitmap at the given (x0, y0) position. + * Copies a region of the source bitmap into this bitmap at the given (x0, y0) position and optionally flip it. * @param x0 destination x position * @param y0 destination y position * @param sx0 source x start position * @param sy0 source y start position - * @param sx1 source x end position - * @param sy1 source y end position + * @param sx1 source x end position (if smaller than sx0, it will be horizontally flipped) + * @param sy1 source y end position (if smaller than sy0, it will be vertically flipped) */ public void blit(BitmapImage source, int x0, int y0, int sx0, int sy0, int sx1, int sy1) { - for (int y = 0; y < sy1 - sy0; ++y) { - System.arraycopy(source.data, (sy0 + y) * source.width + sx0, - data, (y0 + y) * width + x0, - sx1 - sx0); + int w = Math.abs(sx1 - sx0); + int h = Math.abs(sy1 - sy0); + + int xStep = (sx1 >= sx0) ? 1 : -1; + int yStep = (sy1 >= sy0) ? 1 : -1; + + if (xStep == 1) { + for (int y = 0; y < h; y++) { + int srcY = sy0 + y * yStep; + if (sy0 > sy1) { + srcY -= 1; + } + System.arraycopy( + source.data, + srcY * source.width + sx0, + data, + (y0 + y) * width + x0, + w + ); + } + } else { + for (int y = 0; y < h; y++) { + int srcY = sy0 + y * yStep; + if (sy0 > sy1) { + srcY -= 1; + } + int dstIndex = (y0 + y) * width + x0; + for (int x = 0; x < w; x++) { + int srcX = sx0 + x * xStep - 1; + data[dstIndex + x] = + source.data[srcY * source.width + srcX]; + } + } } } diff --git a/chunky/src/java/se/llbit/chunky/resources/Texture.java b/chunky/src/java/se/llbit/chunky/resources/Texture.java index ff1d07250..ee5db432f 100644 --- a/chunky/src/java/se/llbit/chunky/resources/Texture.java +++ b/chunky/src/java/se/llbit/chunky/resources/Texture.java @@ -20,6 +20,7 @@ import org.apache.commons.math3.util.FastMath; import se.llbit.chunky.PersistentSettings; import se.llbit.chunky.renderer.scene.Scene; +import se.llbit.chunky.resources.texturepack.BedTexture; import se.llbit.chunky.resources.texturepack.ChestTexture; import se.llbit.chunky.resources.texturepack.FontTexture; import se.llbit.chunky.resources.texturepack.TexturePath; @@ -670,22 +671,22 @@ public class Texture { public static final Texture strippedAcaciaLog = new Texture(); public static final Texture strippedAcaciaLogTop = new Texture(); - public static final Texture bedWhite = new Texture(); - public static final Texture bedOrange = new Texture(); - public static final Texture bedMagenta = new Texture(); - public static final Texture bedLightBlue = new Texture(); - public static final Texture bedYellow = new Texture(); - public static final Texture bedLime = new Texture(); - public static final Texture bedPink = new Texture(); - public static final Texture bedGray = new Texture(); - public static final Texture bedSilver = new Texture(); - public static final Texture bedCyan = new Texture(); - public static final Texture bedPurple = new Texture(); - public static final Texture bedBlue = new Texture(); - public static final Texture bedBrown = new Texture(); - public static final Texture bedGreen = new Texture(); - public static final Texture bedRed = new Texture(); - public static final Texture bedBlack = new Texture(); + public static final BedTexture.Textures bedWhite = new BedTexture.Textures(); + public static final BedTexture.Textures bedOrange = new BedTexture.Textures(); + public static final BedTexture.Textures bedMagenta = new BedTexture.Textures(); + public static final BedTexture.Textures bedLightBlue = new BedTexture.Textures(); + public static final BedTexture.Textures bedYellow = new BedTexture.Textures(); + public static final BedTexture.Textures bedLime = new BedTexture.Textures(); + public static final BedTexture.Textures bedPink = new BedTexture.Textures(); + public static final BedTexture.Textures bedGray = new BedTexture.Textures(); + public static final BedTexture.Textures bedLightGray = new BedTexture.Textures(); + public static final BedTexture.Textures bedCyan = new BedTexture.Textures(); + public static final BedTexture.Textures bedPurple = new BedTexture.Textures(); + public static final BedTexture.Textures bedBlue = new BedTexture.Textures(); + public static final BedTexture.Textures bedBrown = new BedTexture.Textures(); + public static final BedTexture.Textures bedGreen = new BedTexture.Textures(); + public static final BedTexture.Textures bedRed = new BedTexture.Textures(); + public static final BedTexture.Textures bedBlack = new BedTexture.Textures(); // [1.13] public static final Texture kelp = new Texture(); diff --git a/chunky/src/java/se/llbit/chunky/resources/TexturePackLoader.java b/chunky/src/java/se/llbit/chunky/resources/TexturePackLoader.java index 578620ad4..474a07ef2 100644 --- a/chunky/src/java/se/llbit/chunky/resources/TexturePackLoader.java +++ b/chunky/src/java/se/llbit/chunky/resources/TexturePackLoader.java @@ -2977,42 +2977,22 @@ public class TexturePackLoader { new SimpleTexture("assets/minecraft/textures/blocks/beetroots_stage_3", Texture.beets3))); - ALL_TEXTURES.put("bed_white", - new SimpleTexture("assets/minecraft/textures/entity/bed/white", Texture.bedWhite)); - ALL_TEXTURES.put("bed_orange", - new SimpleTexture("assets/minecraft/textures/entity/bed/orange", Texture.bedOrange)); - ALL_TEXTURES.put("bed_magenta", - new SimpleTexture("assets/minecraft/textures/entity/bed/magenta", Texture.bedMagenta)); - ALL_TEXTURES.put("bed_light_blue", - new SimpleTexture("assets/minecraft/textures/entity/bed/light_blue", Texture.bedLightBlue)); - ALL_TEXTURES.put("bed_yellow", - new SimpleTexture("assets/minecraft/textures/entity/bed/yellow", Texture.bedYellow)); - ALL_TEXTURES.put("bed_lime", - new SimpleTexture("assets/minecraft/textures/entity/bed/lime", Texture.bedLime)); - ALL_TEXTURES.put("bed_pink", - new SimpleTexture("assets/minecraft/textures/entity/bed/pink", Texture.bedPink)); - ALL_TEXTURES.put("bed_gray", - new SimpleTexture("assets/minecraft/textures/entity/bed/gray", Texture.bedGray)); - ALL_TEXTURES.put("bed_silver", new AlternateTextures( - new SimpleTexture("assets/minecraft/textures/entity/bed/light_gray", Texture.bedSilver), - new SimpleTexture("assets/minecraft/textures/entity/bed/silver", Texture.bedSilver))); - ALL_TEXTURES.put("bed_cyan", - new SimpleTexture("assets/minecraft/textures/entity/bed/cyan", Texture.bedCyan)); - ALL_TEXTURES.put("bed_purple", - new SimpleTexture("assets/minecraft/textures/entity/bed/purple", Texture.bedPurple)); - ALL_TEXTURES.put("bed_blue", - new SimpleTexture("assets/minecraft/textures/entity/bed/blue", Texture.bedBlue)); - ALL_TEXTURES.put("bed_brown", - new SimpleTexture("assets/minecraft/textures/entity/bed/brown", Texture.bedBrown)); - ALL_TEXTURES.put("bed_green", - new SimpleTexture("assets/minecraft/textures/entity/bed/green", Texture.bedGreen)); - ALL_TEXTURES.put("bed_red", - new AlternateTextures( - new SimpleTexture("assets/minecraft/textures/entity/bed/red", Texture.bedRed), - new BedTextureAdapter() - )); - ALL_TEXTURES.put("bed_black", - new SimpleTexture("assets/minecraft/textures/entity/bed/black", Texture.bedBlack)); + ALL_TEXTURES.put("bed_white", BedTexture.createTextureLoader("white", Texture.bedWhite)); + ALL_TEXTURES.put("bed_orange", BedTexture.createTextureLoader("orange", Texture.bedOrange)); + ALL_TEXTURES.put("bed_magenta", BedTexture.createTextureLoader("magenta", Texture.bedMagenta)); + ALL_TEXTURES.put("bed_light_blue", BedTexture.createTextureLoader("light_blue", Texture.bedLightBlue)); + ALL_TEXTURES.put("bed_yellow", BedTexture.createTextureLoader("yellow", Texture.bedYellow)); + ALL_TEXTURES.put("bed_lime", BedTexture.createTextureLoader("lime", Texture.bedLime)); + ALL_TEXTURES.put("bed_pink", BedTexture.createTextureLoader("pink", Texture.bedPink)); + ALL_TEXTURES.put("bed_gray", BedTexture.createTextureLoader("gray", Texture.bedGray)); + ALL_TEXTURES.put("bed_light_gray", BedTexture.createTextureLoader("light_gray", Texture.bedLightGray)); + ALL_TEXTURES.put("bed_cyan", BedTexture.createTextureLoader("cyan", Texture.bedCyan)); + ALL_TEXTURES.put("bed_purple", BedTexture.createTextureLoader("purple", Texture.bedPurple)); + ALL_TEXTURES.put("bed_blue", BedTexture.createTextureLoader("blue", Texture.bedBlue)); + ALL_TEXTURES.put("bed_brown", BedTexture.createTextureLoader("brown", Texture.bedBrown)); + ALL_TEXTURES.put("bed_green", BedTexture.createTextureLoader("green", Texture.bedGreen)); + ALL_TEXTURES.put("bed_red", BedTexture.createTextureLoader("red", Texture.bedRed)); + ALL_TEXTURES.put("bed_black", BedTexture.createTextureLoader("black", Texture.bedBlack)); ALL_TEXTURES.put("banner_base", new SimpleTexture("assets/minecraft/textures/entity/banner_base", Texture.bannerBase)); @@ -3632,8 +3612,17 @@ public class TexturePackLoader { "assets/minecraft/textures/block/chiseled_bookshelf_empty", "assets/minecraft/textures/block/chiseled_bookshelf_occupied")); - for (Field field : Texture.class.getFields()) { - if (Texture.class.isAssignableFrom(field.getType())) { + registerTextureFields(Texture.class); + } + + /** + * Register all public static fields annotated with {@link TexturePath} to be loaded. + * @param clazz Class to register + * @param Type of the class + */ + public static void registerTextureFields(Class clazz) { + for (Field field : clazz.getFields()) { + if (clazz.isAssignableFrom(field.getType())) { addTextureLoader(field); } } diff --git a/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTexture.java b/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTexture.java new file mode 100644 index 000000000..30c6fa4d0 --- /dev/null +++ b/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTexture.java @@ -0,0 +1,63 @@ +package se.llbit.chunky.resources.texturepack; + +import se.llbit.chunky.resources.Texture; + +public class BedTexture { + public static class Textures { + public final Texture headUp = new Texture(); + public final Texture headDown = new Texture(); + public final Texture headNorth = new Texture(); + public final Texture headEast = new Texture(); + public final Texture headWest = new Texture(); + public final Texture footUp = new Texture(); + public final Texture footDown = new Texture(); + public final Texture footSouth = new Texture(); + public final Texture footEast = new Texture(); + public final Texture footWest = new Texture(); + } + + private BedTexture() { + } + + /** + * Create a texture loader for the given bed color that uses the 26.2 textures by default and falls back to + * older texture formats if they don't exist. + * + * @param color Bed color + * @return Texture loader for these bed colors + */ + public static TextureLoader createTextureLoader(String color, BedTexture.Textures textures) { + TextureLoader chaosCubedTextureLoader = new AllTextures( + new SimpleTexture("assets/minecraft/textures/block/bed_head_north", textures.headNorth), + new SimpleTexture("assets/minecraft/textures/block/bed_down", textures.headDown), + new SimpleTexture("assets/minecraft/textures/block/" + color + "_bed_head_east", textures.headEast), + new SimpleTexture("assets/minecraft/textures/block/" + color + "_bed_head_west", textures.headWest), + new SimpleTexture("assets/minecraft/textures/block/" + color + "_bed_head_up", textures.headUp), + new SimpleTexture("assets/minecraft/textures/block/" + color + "_bed_foot_south", textures.footSouth), + new SimpleTexture("assets/minecraft/textures/block/" + color + "_bed_foot_east", textures.footEast), + new SimpleTexture("assets/minecraft/textures/block/" + color + "_bed_foot_west", textures.footWest), + new SimpleTexture("assets/minecraft/textures/block/" + color + "_bed_foot_up", textures.footUp)); + + if ("red".equals(color)) { // only red existed before 1.12 + return new AlternateTextures( + chaosCubedTextureLoader, + new BedTextureAdapter26_2(textures, targetTexture -> new AlternateTextures( + new SimpleTexture("assets/minecraft/textures/entity/bed/red", targetTexture), + new BedTextureAdapter1_12(targetTexture) + ))); + } + if ("light_gray".equals(color)) { // light_gray was silver before 1.13 + return new AlternateTextures( + chaosCubedTextureLoader, + new BedTextureAdapter26_2(textures, targetTexture -> new AlternateTextures( + new SimpleTexture("assets/minecraft/textures/entity/bed/light_gray", targetTexture), + new SimpleTexture("assets/minecraft/textures/entity/bed/silver", targetTexture) + ))); + } + return new AlternateTextures( + chaosCubedTextureLoader, + new BedTextureAdapter26_2(textures, targetTexture -> + new SimpleTexture("assets/minecraft/textures/entity/bed/" + color, targetTexture) + )); + } +} diff --git a/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter.java b/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter1_12.java similarity index 62% rename from chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter.java rename to chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter1_12.java index 43471d78d..42bf79639 100644 --- a/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter.java +++ b/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter1_12.java @@ -24,7 +24,6 @@ import java.io.IOException; import java.io.InputStream; -import java.nio.file.Path; /** * This texture loader is an adapter for the pre-1.12 bed textures. @@ -32,7 +31,7 @@ * *

This texture loader is only used if a post-1.12 red bed texture is not found. */ -public class BedTextureAdapter extends TextureLoader { +public class BedTextureAdapter1_12 extends TextureLoader { private final Texture bedHeadTop = new Texture(); private final Texture bedFootTop = new Texture(); private final Texture bedFootEnd = new Texture(); @@ -48,38 +47,42 @@ public class BedTextureAdapter extends TextureLoader { private final AlternateTextures headSideLoader; private final AlternateTextures headEndLoader; - public BedTextureAdapter() { + private final Texture targetTexture; + + public BedTextureAdapter1_12(Texture targetTexture) { + this.targetTexture = targetTexture; bottomLoader = new AlternateTextures( - new SimpleTexture("assets/minecraft/textures/blocks/planks_oak", bottom), - new SimpleTexture("textures/blocks/wood", bottom), - new IndexedTexture(0x04, bottom)); + new SimpleTexture("assets/minecraft/textures/blocks/planks_oak", bottom), + new SimpleTexture("textures/blocks/wood", bottom), + new IndexedTexture(0x04, bottom)); footTopLoader = new AlternateTextures( - new SimpleTexture("assets/minecraft/textures/blocks/bed_feet_top", bedFootTop), - new SimpleTexture("textures/blocks/bed_feet_top", bedFootTop), - new IndexedTexture(0x86, bedFootTop)); + new SimpleTexture("assets/minecraft/textures/blocks/bed_feet_top", bedFootTop), + new SimpleTexture("textures/blocks/bed_feet_top", bedFootTop), + new IndexedTexture(0x86, bedFootTop)); headTopLoader = new AlternateTextures( - new SimpleTexture("assets/minecraft/textures/blocks/bed_head_top", bedHeadTop), - new SimpleTexture("textures/blocks/bed_head_top", bedHeadTop), - new IndexedTexture(0x87, bedHeadTop)); + new SimpleTexture("assets/minecraft/textures/blocks/bed_head_top", bedHeadTop), + new SimpleTexture("textures/blocks/bed_head_top", bedHeadTop), + new IndexedTexture(0x87, bedHeadTop)); footEndLoader = new AlternateTextures( - new SimpleTexture("assets/minecraft/textures/blocks/bed_feet_end", bedFootEnd), - new SimpleTexture("textures/blocks/bed_feet_end", bedFootEnd), - new IndexedTexture(0x95, bedFootEnd)); + new SimpleTexture("assets/minecraft/textures/blocks/bed_feet_end", bedFootEnd), + new SimpleTexture("textures/blocks/bed_feet_end", bedFootEnd), + new IndexedTexture(0x95, bedFootEnd)); footSideLoader = new AlternateTextures( - new SimpleTexture("assets/minecraft/textures/blocks/bed_feet_side", bedFootSide), - new SimpleTexture("textures/blocks/bed_feet_side", bedFootSide), - new IndexedTexture(0x96, bedFootSide)); + new SimpleTexture("assets/minecraft/textures/blocks/bed_feet_side", bedFootSide), + new SimpleTexture("textures/blocks/bed_feet_side", bedFootSide), + new IndexedTexture(0x96, bedFootSide)); headSideLoader = new AlternateTextures( - new SimpleTexture("assets/minecraft/textures/blocks/bed_head_side", bedHeadSide), - new SimpleTexture("textures/blocks/bed_head_side", bedHeadSide), - new IndexedTexture(0x97, bedHeadSide)); + new SimpleTexture("assets/minecraft/textures/blocks/bed_head_side", bedHeadSide), + new SimpleTexture("textures/blocks/bed_head_side", bedHeadSide), + new IndexedTexture(0x97, bedHeadSide)); headEndLoader = new AlternateTextures( - new SimpleTexture("assets/minecraft/textures/blocks/bed_head_end", bedHeadEnd), - new SimpleTexture("textures/blocks/bed_head_end", bedHeadEnd), - new IndexedTexture(0x98, bedHeadEnd)); + new SimpleTexture("assets/minecraft/textures/blocks/bed_head_end", bedHeadEnd), + new SimpleTexture("textures/blocks/bed_head_end", bedHeadEnd), + new IndexedTexture(0x98, bedHeadEnd)); } - @Override public boolean load(LayeredResourcePacks texturePack) { + @Override + public boolean load(LayeredResourcePacks texturePack) { boolean allLoaded = true; int scale = 1; BitmapImage bitmap = new BitmapImage(64, 64); @@ -89,7 +92,7 @@ public BedTextureAdapter() { scale = bottom.getWidth() / 16; if (16 * scale != bottom.getWidth()) { Log.warn("Can't load pre-1.12 bed texture: oak plank texture size must be " - + "an even multiple of 16."); + + "an even multiple of 16."); return false; } bitmap = new BitmapImage(64 * scale, 64 * scale); @@ -100,41 +103,41 @@ public BedTextureAdapter() { } if (footEndLoader.load(texturePack) && checkSize(bedFootEnd, scale)) { bitmap.blit(bedFootEnd.getBitmap().vFlipped(), - 22 * scale, 22 * scale, - 0, 3 * scale, - 16 * scale, 9 * scale); + 22 * scale, 22 * scale, + 0, 3 * scale, + 16 * scale, 9 * scale); // Leg 1 (left): bitmap.blit(bedFootEnd.getBitmap(), - 53 * scale, 3 * scale, - 0, 13 * scale, - 3 * scale, 16 * scale); + 53 * scale, 3 * scale, + 0, 13 * scale, + 3 * scale, 16 * scale); // Leg 3 (right): bitmap.blit(bedFootEnd.getBitmap(), - 50 * scale, 15 * scale, - 13 * scale, 13 * scale, - 16 * scale, 16 * scale); + 50 * scale, 15 * scale, + 13 * scale, 13 * scale, + 16 * scale, 16 * scale); } else { allLoaded = false; } if (footSideLoader.load(texturePack) && checkSize(bedFootSide, scale)) { bitmap.blit(bedFootSide.getBitmap().rotated().vFlipped(), - 0, 28 * scale, - 3 * scale, 0, - 9 * scale, 16 * scale); + 0, 28 * scale, + 3 * scale, 0, + 9 * scale, 16 * scale); bitmap.blit(bedFootSide.getBitmap().rotated270(), - 22 * scale, 28 * scale, - 7 * scale, 0, - 13 * scale, 16 * scale); + 22 * scale, 28 * scale, + 7 * scale, 0, + 13 * scale, 16 * scale); // Leg 1 (bottom left): bitmap.blit(bedFootSide.getBitmap().hFlipped(), - 50 * scale, 3 * scale, - 13 * scale, 13 * scale, - 16 * scale, 16 * scale); + 50 * scale, 3 * scale, + 13 * scale, 13 * scale, + 16 * scale, 16 * scale); // Leg 3 (bottom right): bitmap.blit(bedFootSide.getBitmap(), - 53 * scale, 15 * scale, - 0, 13 * scale, - 3 * scale, 16 * scale); + 53 * scale, 15 * scale, + 0, 13 * scale, + 3 * scale, 16 * scale); } else { allLoaded = false; } @@ -145,41 +148,41 @@ public BedTextureAdapter() { } if (headEndLoader.load(texturePack) && checkSize(bedHeadEnd, scale)) { bitmap.blit(bedHeadEnd.getBitmap().vFlipped(), - 6 * scale, 0, - 0, 3 * scale, - 16 * scale, 9 * scale); + 6 * scale, 0, + 0, 3 * scale, + 16 * scale, 9 * scale); // Leg 4 (left): bitmap.blit(bedHeadEnd.getBitmap(), - 53 * scale, 21 * scale, - 0, 13 * scale, - 3 * scale, 16 * scale); + 53 * scale, 21 * scale, + 0, 13 * scale, + 3 * scale, 16 * scale); // Leg 2 (right): bitmap.blit(bedHeadEnd.getBitmap(), - 50 * scale, 9 * scale, - 13 * scale, 13 * scale, - 16 * scale, 16 * scale); + 50 * scale, 9 * scale, + 13 * scale, 13 * scale, + 16 * scale, 16 * scale); } else { allLoaded = false; } if (headSideLoader.load(texturePack) && checkSize(bedHeadSide, scale)) { bitmap.blit(bedHeadSide.getBitmap().rotated().vFlipped(), - 0, 6 * scale, - 3 * scale, 0, - 9 * scale, 16 * scale); + 0, 6 * scale, + 3 * scale, 0, + 9 * scale, 16 * scale); bitmap.blit(bedHeadSide.getBitmap().rotated270(), - 22 * scale, 6 * scale, - 7 * scale, 0, - 13 * scale, 16 * scale); + 22 * scale, 6 * scale, + 7 * scale, 0, + 13 * scale, 16 * scale); // Leg 4 (top left): bitmap.blit(bedHeadSide.getBitmap(), - 50 * scale, 21 * scale, - 13 * scale, 13 * scale, - 16 * scale, 16 * scale); + 50 * scale, 21 * scale, + 13 * scale, 13 * scale, + 16 * scale, 16 * scale); // Leg 2 (top right): bitmap.blit(bedHeadSide.getBitmap().hFlipped(), - 53 * scale, 9 * scale, - 0, 13 * scale, - 3 * scale, 16 * scale); + 53 * scale, 9 * scale, + 0, 13 * scale, + 3 * scale, 16 * scale); } else { allLoaded = false; } @@ -188,29 +191,31 @@ public BedTextureAdapter() { } else { allLoaded = false; } - Texture.bedRed.setTexture(bitmap); + this.targetTexture.setTexture(bitmap); return allLoaded; } /** * Ensures that the bed texture part has the right dimensions. + * * @return {@code true} if the texture has the correct size */ private boolean checkSize(Texture texture, int scale) { if (texture.getWidth() != 16 * scale) { Log.warnf("Bed texture has wrong scale: expected %d, but was %d.", - 16 * scale, texture.getWidth()); + 16 * scale, texture.getWidth()); return false; } if (texture.getWidth() != texture.getHeight()) { Log.warnf("Bed texture is not square: %dx%d", - texture.getWidth(), texture.getHeight()); + texture.getWidth(), texture.getHeight()); return false; } return true; } - @Override protected boolean load(InputStream imageStream) throws IOException, TextureFormatError { + @Override + protected boolean load(InputStream imageStream) throws IOException, TextureFormatError { return false; } } diff --git a/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter26_2.java b/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter26_2.java new file mode 100644 index 000000000..4ff6b74ad --- /dev/null +++ b/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter26_2.java @@ -0,0 +1,107 @@ +package se.llbit.chunky.resources.texturepack; + +import se.llbit.chunky.resources.BitmapImage; +import se.llbit.chunky.resources.LayeredResourcePacks; +import se.llbit.chunky.resources.Texture; + +import java.io.IOException; +import java.io.InputStream; +import java.util.function.Function; + +/** + * This texture loader is an adapter for the 26.2-snapshot-3 (or later) bed textures. + * It composes post 26.2-snapshot-3 textures from post-1.12 bed textures. + */ +public class BedTextureAdapter26_2 extends TextureLoader { + private final BedTexture.Textures targetTextures; + private final Function originalTextureLoader; + + public BedTextureAdapter26_2(BedTexture.Textures targetTextures, Function originalTextureLoader) { + this.targetTextures = targetTextures; + this.originalTextureLoader = originalTextureLoader; + } + + @Override + public boolean load(LayeredResourcePacks resourcePacks) { + Texture originalTexture = new Texture(); + if (!originalTextureLoader.apply(originalTexture).load(resourcePacks)) { + return false; + } + + int scale = 1; + BitmapImage headUp = new BitmapImage(16 * scale, 16 * scale); + headUp.blit(originalTexture.getBitmap(), 0, 0, 6 * scale, 6 * scale, 22 * scale, 22 * scale); + targetTextures.headUp.setTexture(headUp); + + BitmapImage headDown = new BitmapImage(16 * scale, 16 * scale); + headDown.blit(originalTexture.getBitmap(), 0, 0, 44 * scale, 22 * scale, 28 * scale, 6 * scale); + targetTextures.headDown.setTexture(headDown); + + BitmapImage headNorth = new BitmapImage(16 * scale, 16 * scale); + headNorth.blit(originalTexture.getBitmap(), 0, 7 * scale, 22 * scale, 6 * scale, 6 * scale, 0); + headNorth.blit(originalTexture.getBitmap(), 0, 13 * scale, 53 * scale, 3 * scale, 59 * scale, 6 * scale); + headNorth.blit(originalTexture.getBitmap(), 10 * scale, 13 * scale, 59 * scale, 3 * scale, 62 * scale, 6 * scale); + headNorth.blit(originalTexture.getBitmap(), 13 * scale, 13 * scale, 50 * scale, 3 * scale, 53 * scale, 6 * scale); + targetTextures.headNorth.setTexture(headNorth); + + BitmapImage headEast = new BitmapImage(16 * scale, 16 * scale); + BitmapImage tmp = new BitmapImage(6 * scale, 16 * scale); + tmp.blit(originalTexture.getBitmap(), 0, 0, 22 * scale, 6 * scale, 28 * scale, 22 * scale); + headEast.blit(tmp.rotated(), 0, 7 * scale); + headEast.blit(originalTexture.getBitmap(), 13 * scale, 13 * scale, 50 * scale, 3 * scale, 53 * scale, 6 * scale); + headEast.blit(originalTexture.getBitmap(), 10 * scale, 13 * scale, 59 * scale, 3 * scale, 62 * scale, 6 * scale); + headEast.blit(originalTexture.getBitmap(), 7 * scale, 13 * scale, 59 * scale, 0, 56 * scale, 3 * scale); + targetTextures.headEast.setTexture(headEast); + + BitmapImage headWest = new BitmapImage(16 * scale, 16 * scale); + tmp = new BitmapImage(6 * scale, 16 * scale); + tmp.blit(originalTexture.getBitmap(), 0, 0, 0, 6 * scale, 6 * scale, 22 * scale); + headWest.blit(tmp.rotated270(), 0, 7 * scale); + headWest.blit(originalTexture.getBitmap(), 0, 13 * scale, 53 * scale, 3 * scale, 59 * scale, 6 * scale); + tmp = new BitmapImage(3 * scale, 3 * scale); + tmp.blit(originalTexture.getBitmap(), 0, 0, 56 * scale, 0, 59 * scale, 3 * scale); + headWest.blit(tmp.rotated270(), 6 * scale, 13 * scale); + targetTextures.headWest.setTexture(headWest); + + BitmapImage footUp = new BitmapImage(16 * scale, 16 * scale); + footUp.blit(originalTexture.getBitmap(), 0, 0, 6 * scale, 28 * scale, 22 * scale, 44 * scale); + targetTextures.footUp.setTexture(footUp); + + BitmapImage footDown = new BitmapImage(16 * scale, 16 * scale); + footDown.blit(originalTexture.getBitmap(), 0, 0, 44 * scale, 44 * scale, 28 * scale, 28 * scale); + targetTextures.footDown.setTexture(footDown); + + BitmapImage footSouth = new BitmapImage(16 * scale, 16 * scale); + footSouth.blit(originalTexture.getBitmap(), 0, 7 * scale, 22 * scale, 28 * scale, 38 * scale, 22 * scale); + footSouth.blit(originalTexture.getBitmap(), 0, 13 * scale, 53 * scale, 3 * scale, 59 * scale, 6 * scale); + footSouth.blit(originalTexture.getBitmap(), 10 * scale, 13 * scale, 59 * scale, 3 * scale, 62 * scale, 6 * scale); + footSouth.blit(originalTexture.getBitmap(), 13 * scale, 13 * scale, 50 * scale, 3 * scale, 53 * scale, 6 * scale); + targetTextures.footSouth.setTexture(footSouth); + + BitmapImage footEast = new BitmapImage(16 * scale, 16 * scale); + tmp = new BitmapImage(6 * scale, 16 * scale); + tmp.blit(originalTexture.getBitmap(), 0, 0, 22 * scale, 28 * scale, 28 * scale, 44 * scale); + footEast.blit(tmp.rotated(), 0, 7 * scale); + footEast.blit(originalTexture.getBitmap(), 0, 13 * scale, 53 * scale, 3 * scale, 59 * scale, 6 * scale); + tmp = new BitmapImage(3 * scale, 3 * scale); + tmp.blit(originalTexture.getBitmap(), 0, 0, 56 * scale, 0, 59 * scale, 3 * scale); + footEast.blit(tmp.rotated(), 6 * scale, 13 * scale); + targetTextures.footEast.setTexture(footEast); + + BitmapImage footWest = new BitmapImage(16 * scale, 16 * scale); + tmp = new BitmapImage(6 * scale, 16 * scale); + tmp.blit(originalTexture.getBitmap(), 0, 0, 0, 28 * scale, 6 * scale, 44 * scale); + footWest.blit(tmp.rotated270(), 0, 7 * scale); + footWest.blit(originalTexture.getBitmap(), 10 * scale, 13 * scale, 59 * scale, 3 * scale, 62 * scale, 6 * scale); + footWest.blit(originalTexture.getBitmap(), 13 * scale, 13 * scale, 50 * scale, 3 * scale, 53 * scale, 6 * scale); + footWest.blit(originalTexture.getBitmap(), 7 * scale, 13 * scale, 56 * scale, 0, 59 * scale, 3 * scale); + targetTextures.footWest.setTexture(footWest); + + return true; + } + + @Override + protected boolean load(InputStream imageStream) throws IOException, TextureFormatError { + return false; + } +} From 679c18e81d1f302c033e2939fecf96aa8056803b Mon Sep 17 00:00:00 2001 From: Maik Marschner Date: Sun, 17 May 2026 15:43:34 +0200 Subject: [PATCH 3/3] Fix hard-coded legacy bed texture scale. --- .../chunky/resources/texturepack/BedTextureAdapter26_2.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter26_2.java b/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter26_2.java index 4ff6b74ad..b96cd8870 100644 --- a/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter26_2.java +++ b/chunky/src/java/se/llbit/chunky/resources/texturepack/BedTextureAdapter26_2.java @@ -28,7 +28,7 @@ public boolean load(LayeredResourcePacks resourcePacks) { return false; } - int scale = 1; + int scale = originalTexture.getWidth() / 64; BitmapImage headUp = new BitmapImage(16 * scale, 16 * scale); headUp.blit(originalTexture.getBitmap(), 0, 0, 6 * scale, 6 * scale, 22 * scale, 22 * scale); targetTextures.headUp.setTexture(headUp);