derive default layers, armor wearers, arms/chest pose flags and mob variant textures from the vanilla dump, drop the hardcoded lists

This commit is contained in:
MineTec committed 2026-11-04 15:48:03 +01:00
1 parent 022b080fce
commit a743dc32c7
14 files changed
+720 -162

No files matched your search

+215 -1
View File
@@ -117,6 +117,17 @@ public class PPTest extends JavaPlugin {
scenes.put("be_items", new Scene("be_items", this::beItems, 4.5, 2.6, 11, 4.5, 0.8, 3));
scenes.put("be_items_back", new Scene("be_items_back", this::beItems, 4.5, 2.6, -5, 4.5, 0.8, 3));
scenes.put("proj_stuck_sw", new Scene("proj_stuck_sw", this::projStuck, -3, 6, 10, 8, 1.5, 2));
// Data-driven variants / pose flags / armor wearers (vanilla dump: asset_id, setupAnim flags, armor layers).
scenes.put("rf_cats", new Scene("rf_cats", this::rfCats, 6.5, 2.6, -4.5, 6.5, 0.2, 1.2));
scenes.put("rf_wolves", new Scene("rf_wolves", this::rfWolves, 5.5, 3.2, -5.5, 5.5, 0.2, 1.8));
scenes.put("rf_farm", new Scene("rf_farm", this::rfFarm, 6, 3.4, -6, 6, 0.3, 1.8));
scenes.put("rf_stands", new Scene("rf_stands", this::rfStands, 5, 2.4, -4.5, 5, 0.9, 0));
scenes.put("rf_stands_back", new Scene("rf_stands_back", this::rfStands, 5, 2.4, 4.5, 5, 0.9, 0));
scenes.put("rf_chests", new Scene("rf_chests", this::rfChests, 7, 4, -7, 7, 0.8, 1));
scenes.put("rf_chests_side", new Scene("rf_chests_side", this::rfChests, 7, 2.5, 7, 7, 0.8, 1));
// Needs a datapack cat variant "pptest:ocelotcat" (asset_id entity/cat/ocelot) in the world's datapacks.
scenes.put("rf_dpcat", new Scene("rf_dpcat", this::rfDatapackCat, 1.2, 1.4, -2.2, 1.2, 0.2, 0.5));
scenes.put("rf_armor", new Scene("rf_armor", this::rfArmor, 7, 3.2, -6.5, 7, 1.0, 1.5));
}
@Override
@@ -154,7 +165,7 @@ public class PPTest extends JavaPlugin {
Location eye = o.clone().add(sc.camX, sc.camY, sc.camZ);
Vector look = o.clone().add(sc.lookX, sc.lookY, sc.lookZ).toVector().subtract(eye.toVector());
eye.setDirection(look);
RenderJob job = r.prepare(eye, sc.name.startsWith("proj_") ? new Resolution(960, 640) : new Resolution(480, 320), null);
RenderJob job = r.prepare(eye, sc.name.startsWith("proj_") || sc.name.startsWith("rf_") ? new Resolution(960, 640) : new Resolution(480, 320), null);
if (sc.name.equals("dbg")) {
try {
java.lang.reflect.Field f = DefaultScreenRenderer.class.getDeclaredField("objectBaker");
@@ -690,6 +701,209 @@ public class PPTest extends JavaPlugin {
for (Entity e : w.getNearbyEntities(o, 12, 8, 8)) if (e instanceof Wither wi) wi.setBodyYaw(180);
}
// --- data-driven variants / pose flags / armor wearers ------------------------------------------
private static <T extends Keyed> List<T> registry(io.papermc.paper.registry.RegistryKey<T> key) {
List<T> out = new ArrayList<>();
io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(key).forEach(out::add);
out.sort(Comparator.comparing(k -> k.getKey().toString()));
return out;
}
/** Spawn without vanilla's random spawn data (baby chance, jockeys, gear, biome variants): reproducible. */
private <T extends Entity> T rfSpawn(Location o, double x, double y, double z, float yaw, Class<T> type) {
Location l = o.clone().add(x, y, z);
l.setYaw(yaw);
T e = w.spawn(l, type, false, en -> {
if (en instanceof Mob m) m.setAI(false);
en.setPersistent(false);
});
if (e instanceof LivingEntity le) le.setRemoveWhenFarAway(false);
return e;
}
private Entity rfSpawn(Location o, double x, double y, double z, float yaw, EntityType type) {
Location l = o.clone().add(x, y, z);
l.setYaw(yaw);
Entity e = w.spawnEntity(l, type, false);
if (e instanceof Mob m) m.setAI(false);
return e;
}
private void faceNorth(Location o) {
for (Entity e : w.getNearbyEntities(o.clone().add(6, 0, 0), 14, 4, 12))
if (e instanceof LivingEntity le && !(e instanceof Player)) le.setBodyYaw(180);
}
private void rfCats(Location o) {
List<Cat.Type> types = registry(io.papermc.paper.registry.RegistryKey.CAT_VARIANT);
for (int i = 0; i < types.size(); i++) {
rfSpawn(o, i * 1.2, 0, 0, 180, Cat.class).setCatType(types.get(i));
Cat kit = rfSpawn(o, i * 1.2, 0, 1.6, 180, Cat.class);
kit.setCatType(types.get(i));
kit.setBaby();
if (i % 2 == 0) tame(kit, DyeColor.values()[i % 16]);
}
faceNorth(o);
}
private void rfDatapackCat(Location o) {
Cat.Type custom = io.papermc.paper.registry.RegistryAccess.registryAccess()
.getRegistry(io.papermc.paper.registry.RegistryKey.CAT_VARIANT)
.get(new NamespacedKey("pptest", "ocelotcat"));
if (custom == null) throw new IllegalStateException("datapack variant pptest:ocelotcat missing");
rfSpawn(o, 0, 0, 0, 180, Cat.class).setCatType(custom);
Cat kit = rfSpawn(o, 1.2, 0, 0, 180, Cat.class);
kit.setCatType(custom);
kit.setBaby();
rfSpawn(o, 2.4, 0, 0, 180, Cat.class).setCatType(Cat.Type.TABBY);
faceNorth(o);
}
private void rfWolves(Location o) {
List<Wolf.Variant> vs = registry(io.papermc.paper.registry.RegistryKey.WOLF_VARIANT);
for (int i = 0; i < vs.size(); i++) {
rfSpawn(o, i * 1.3, 0, 0, 180, Wolf.class).setVariant(vs.get(i));
Wolf t = rfSpawn(o, i * 1.3, 0, 1.6, 180, Wolf.class);
t.setVariant(vs.get(i));
tame(t, DyeColor.values()[i % 16]);
Wolf pup = rfSpawn(o, i * 1.3, 0, 3.0, 180, Wolf.class);
pup.setVariant(vs.get(i));
pup.setBaby();
if (i % 2 == 1) tame(pup, DyeColor.BLUE);
}
faceNorth(o);
}
private void rfFarm(Location o) {
List<Cow.Variant> cows = registry(io.papermc.paper.registry.RegistryKey.COW_VARIANT);
List<Pig.Variant> pigs = registry(io.papermc.paper.registry.RegistryKey.PIG_VARIANT);
List<Chicken.Variant> chickens = registry(io.papermc.paper.registry.RegistryKey.CHICKEN_VARIANT);
List<Frog.Variant> frogs = registry(io.papermc.paper.registry.RegistryKey.FROG_VARIANT);
List<ZombieNautilus.Variant> nautili = registry(io.papermc.paper.registry.RegistryKey.ZOMBIE_NAUTILUS_VARIANT);
for (int i = 0; i < 3; i++) {
double x = i * 4;
setVar(rfSpawn(o, x, 0, 0, 180, Cow.class), cows.get(i));
Cow cb = rfSpawn(o, x + 1.6, 0, 0, 180, Cow.class);
setVar(cb, cows.get(i));
cb.setBaby();
setVar(rfSpawn(o, x, 0, 1.8, 180, Pig.class), pigs.get(i));
Pig pb = rfSpawn(o, x + 1.4, 0, 1.8, 180, Pig.class);
setVar(pb, pigs.get(i));
pb.setBaby();
setVar(rfSpawn(o, x + 2.6, 0, 1.8, 180, Chicken.class), chickens.get(i));
Chicken chb = rfSpawn(o, x + 3.3, 0, 1.8, 180, Chicken.class);
setVar(chb, chickens.get(i));
chb.setBaby();
setVar(rfSpawn(o, x + 0.5, 0, 3.4, 180, Frog.class), frogs.get(i));
}
for (int i = 0; i < nautili.size(); i++)
setVar(rfSpawn(o, 2.5 + i * 3, 0, 4.8, 180, ZombieNautilus.class), nautili.get(i));
faceNorth(o);
}
/** setVariant via reflection (the variant setters' declaring interface differs between API and server). */
private static void setVar(Entity e, Object variant) {
for (java.lang.reflect.Method m : e.getClass().getMethods())
if (m.getName().equals("setVariant") && m.getParameterCount() == 1
&& m.getParameterTypes()[0].isInstance(variant)) {
try {
m.invoke(e, variant);
return;
} catch (ReflectiveOperationException ex) {
throw new RuntimeException(ex);
}
}
throw new IllegalStateException("no setVariant for " + variant);
}
private void rfStands(Location o) {
rfSpawn(o, 0, 0, 0, 180, ArmorStand.class);
rfSpawn(o, 1.5, 0, 0, 180, ArmorStand.class).setArms(true);
rfSpawn(o, 3, 0, 0, 180, ArmorStand.class).setSmall(true);
ArmorStand sa = rfSpawn(o, 4.2, 0, 0, 180, ArmorStand.class);
sa.setSmall(true);
sa.setArms(true);
ArmorStand full = rfSpawn(o, 5.7, 0, 0, 180, ArmorStand.class);
full.setArms(true);
diamondArmor(full);
hands(full, Material.IRON_SWORD, Material.SHIELD);
ArmorStand sfull = rfSpawn(o, 7.2, 0, 0, 180, ArmorStand.class);
sfull.setSmall(true);
sfull.setArms(true);
diamondArmor(sfull);
hands(sfull, Material.TORCH, null);
ArmorStand noArmsHeld = rfSpawn(o, 8.6, 0, 0, 180, ArmorStand.class);
hands(noArmsHeld, Material.DIAMOND, null);
ArmorStand inv = rfSpawn(o, 10, 0, 0, 180, ArmorStand.class);
inv.setArms(true);
inv.setInvisible(true);
diamondArmor(inv);
}
private static void diamondArmor(LivingEntity e) {
e.getEquipment().setHelmet(it(Material.DIAMOND_HELMET));
e.getEquipment().setChestplate(it(Material.DIAMOND_CHESTPLATE));
e.getEquipment().setLeggings(it(Material.DIAMOND_LEGGINGS));
e.getEquipment().setBoots(it(Material.DIAMOND_BOOTS));
}
private void rfChests(Location o) {
rfSpawn(o, 0, 0, 0, 180, Llama.class).setColor(Llama.Color.CREAMY);
Llama lc = rfSpawn(o, 1.6, 0, 0, 180, Llama.class);
lc.setColor(Llama.Color.BROWN);
lc.setCarryingChest(true);
Llama lcc = rfSpawn(o, 3.2, 0, 0, 180, Llama.class);
lcc.setColor(Llama.Color.GRAY);
lcc.setCarryingChest(true);
lcc.getInventory().setDecor(it(Material.RED_CARPET));
TraderLlama tl = rfSpawn(o, 4.8, 0, 0, 180, TraderLlama.class);
tl.setColor(Llama.Color.WHITE);
tl.setCarryingChest(true);
Llama bl = rfSpawn(o, 6.2, 0, 0, 180, Llama.class);
bl.setColor(Llama.Color.CREAMY);
bl.setBaby();
rfSpawn(o, 8, 0, 0, 180, Donkey.class);
Donkey dc = rfSpawn(o, 9.6, 0, 0, 180, Donkey.class);
dc.setCarryingChest(true);
Donkey dcs = rfSpawn(o, 11.2, 0, 0, 180, Donkey.class);
dcs.setCarryingChest(true);
dcs.getInventory().setSaddle(it(Material.SADDLE));
Mule mc = rfSpawn(o, 12.8, 0, 0, 180, Mule.class);
mc.setCarryingChest(true);
Mule mcs = rfSpawn(o, 14.4, 0, 0, 180, Mule.class);
mcs.setCarryingChest(true);
mcs.getInventory().setSaddle(it(Material.SADDLE));
faceNorth(o);
}
private void rfArmor(Location o) {
Class<?>[] wearers = {Zombie.class, Husk.class, Drowned.class, ZombieVillager.class, PigZombie.class,
Skeleton.class, Stray.class, WitherSkeleton.class, Bogged.class, Parched.class, Piglin.class, PiglinBrute.class};
for (int i = 0; i < wearers.length; i++) {
@SuppressWarnings("unchecked")
LivingEntity e = rfSpawn(o, i * 1.25, 0, 0, 180, (Class<LivingEntity>) wearers[i]);
diamondArmor(e);
}
LivingEntity m = (LivingEntity) rfSpawn(o, 0, 0, 2.2, 180, EntityType.MANNEQUIN);
diamondArmor(m);
Zombie bz = rfSpawn(o, 1.3, 0, 2.2, 180, Zombie.class);
bz.setBaby();
diamondArmor(bz);
Piglin bp = rfSpawn(o, 2.5, 0, 2.2, 180, Piglin.class);
bp.setBaby();
diamondArmor(bp);
// Non-wearers given armor: vanilla draws nothing.
Class<?>[] others = {Villager.class, Pillager.class, Vindicator.class, Witch.class, Evoker.class,
Creeper.class, Enderman.class, Cow.class, Fox.class};
for (int i = 0; i < others.length; i++) {
@SuppressWarnings("unchecked")
LivingEntity e = rfSpawn(o, 4 + i * 1.25, 0, 2.2, 180, (Class<LivingEntity>) others[i]);
diamondArmor(e);
}
faceNorth(o);
}
// --- projectiles -----------------------------------------------------------------------------
/** Spawns a projectile at p moving along dir, rotated like vanilla Projectile#shoot (yaw atan2(x,z), pitch up). */