apply vanilla uvlock under blockstate x/y rotations and face zero-thickness elements towards the ray

x rotations without uvlock already sampled the model-space element like
vanilla (lying logs/pillars, vertical observers/dispensers verified against
FaceBakery for every blockstate variant). The remaining divergence was
uvlock: faces kept model-extent UVs and were sampled in world orientation,
so top stairs, ceiling buttons, fences/walls and ceiling vines showed
shifted or rotated textures. Rotated uvlocked elements now also go through
the model-space path, with each face's final UVs mapped by vanilla's
BlockMath face transformation (inverted, as in FaceBakery).

Zero-thickness elements (vine, lichen) always reported their low face;
pick the face turned towards the ray instead.

Edge-case test plugin: xrot/xrot2 scenes (lying pillars, vertical
observers/dispensers/droppers, top stairs, ceiling buttons).
This commit is contained in:
MineTec committed 2026-11-04 14:11:40 +01:00
1 parent 5852d4b367
commit a0b7ec3a90
6 files changed
+123 -13

No files matched your search

+35
View File
@@ -56,6 +56,9 @@ public class PPTest extends JavaPlugin {
scenes.put("pistondown", new Scene("pistondown", this::piston, -1.6, 2.6, -1.6, 0.5, 1.4, 0.5));
scenes.put("pistonup", new Scene("pistonup", this::piston, 0.4, 2.6, -1.6, 2.5, 1.4, 0.5));
scenes.put("vehicles", new Scene("vehicles", this::vehicles, 5, 3, -7, 5, 0.6, 1.5));
// Blockstate x rotations (+ x/y combined, uvlock): lying pillars, vertical observers/dispensers, top stairs.
scenes.put("xrot", new Scene("xrot", this::xrot, 3.5, 5.5, -4.5, 6, 0.5, 3.5));
scenes.put("xrot2", new Scene("xrot2", this::xrot, 11, 5, 10.5, 6, 0.5, 3.5));
// Chests: same layout seen from all four sides (single/double per facing, trapped, ender, copper).
scenes.put("chests_s", new Scene("chests_s", this::chests, 4.5, 5, 13, 4.5, 0, 3));
scenes.put("chests_n", new Scene("chests_n", this::chests, 4.5, 5, -7, 4.5, 0, 3));
@@ -491,6 +494,38 @@ public class PPTest extends JavaPlugin {
o.clone().add(4, 0, -2).getBlock().setBlockData(Bukkit.createBlockData("minecraft:furnace[facing=north]"), false);
}
/**
* Row z=0: oak log, basalt, quartz pillar, hay bale lying along x (x=90,y=90) and z (x=90). Row z=3: observer,
* dispenser, dropper facing up and down. Row z=6: oak and stone-brick stairs half=top in all four facings
* (x=180 + uvlock), oak buttons on the ceiling. A stone column at z=-2 marks north.
*/
private void xrot(Location o) {
java.util.function.BiConsumer<int[], String> put = (p, data) -> o.clone().add(p[0], p[1], p[2]).getBlock()
.setBlockData(Bukkit.createBlockData("minecraft:" + data), false);
String[] pillars = {"oak_log", "basalt", "quartz_pillar", "hay_block"};
for (int i = 0; i < pillars.length; i++) {
put.accept(new int[] {i * 3, 0, 0}, pillars[i] + "[axis=x]");
put.accept(new int[] {i * 3 + 1, 0, 0}, pillars[i] + "[axis=z]");
}
String[] vertical = {"observer", "dispenser", "dropper"};
for (int i = 0; i < vertical.length; i++) {
put.accept(new int[] {i * 3, 0, 3}, vertical[i] + "[facing=up]");
put.accept(new int[] {i * 3 + 1, 1, 3}, vertical[i] + "[facing=down]");
put.accept(new int[] {i * 3 + 1, 0, 3}, "glass");
}
String[] f = {"north", "east", "south", "west"};
for (int i = 0; i < f.length; i++) {
put.accept(new int[] {i * 2, 0, 6}, "oak_stairs[facing=" + f[i] + ",half=top]");
put.accept(new int[] {i * 2 + 1, 0, 6}, "stone_brick_stairs[facing=" + f[i] + ",half=top]");
}
put.accept(new int[] {9, 1, 6}, "stone");
put.accept(new int[] {9, 0, 6}, "oak_button[face=ceiling,facing=north]");
put.accept(new int[] {10, 1, 6}, "stone");
put.accept(new int[] {10, 0, 6}, "oak_button[face=ceiling,facing=east]");
put.accept(new int[] {0, 0, -2}, "stone");
put.accept(new int[] {0, 1, -2}, "stone");
}
private void vehicles(Location o) {
spawn(o, 0, 0, 0, 0, EntityType.CHEST_MINECART);
spawn(o, 1.8, 0, 0, 90, EntityType.FURNACE_MINECART);