mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Merge pull request #2547 from kacpherek/fix/variant-textures
🤖 Agent: Merged by Ludovic's AI agent (Claude, contrib-gate-19). Thanks @kacpherek: Draw mob variants: rabbit, parrot, axolotl, salmon size and baby models. I checked it against vanilla 26.3, and it passed every harness it reaches in a union with your other PRs, plus lan_e2e in both modes.
This commit is contained in:
2 files changed
+132
-4
No files matched your search
@@ -491,7 +491,36 @@ pub fn mob_to_nbt(m: &Mob, uuid: [i32; 4], raw: Option<&Tag>) -> Tag {
|
||||
crate::mobs::villager::write_nbt(m, map);
|
||||
}
|
||||
"minecraft:wandering_trader" => put_offers(map, m),
|
||||
"minecraft:axolotl" => write_axolotl_memories(m, map),
|
||||
"minecraft:axolotl" => {
|
||||
write_axolotl_memories(m, map);
|
||||
map.insert(
|
||||
"Variant".into(),
|
||||
Tag::Int(i32::from(m.extra.variant.min(4))),
|
||||
);
|
||||
}
|
||||
// Rabbit.addAdditionalSaveData (the legacy id; 99 is the killer bunny).
|
||||
"minecraft:rabbit" => {
|
||||
map.insert("RabbitType".into(), Tag::Int(i32::from(m.extra.variant)));
|
||||
}
|
||||
"minecraft:parrot" => {
|
||||
map.insert(
|
||||
"Variant".into(),
|
||||
Tag::Int(i32::from(m.extra.variant.min(4))),
|
||||
);
|
||||
}
|
||||
"minecraft:salmon" => {
|
||||
let size = SALMON_SIZES[usize::from(m.extra.variant).min(2)];
|
||||
map.insert("type".into(), string(size));
|
||||
}
|
||||
// TropicalFish.addAdditionalSaveData: the packed variant.
|
||||
"minecraft:tropical_fish" => {
|
||||
let pattern = m.extra.variant.min(11);
|
||||
let packed = i32::from(pattern >= 6)
|
||||
| i32::from(pattern % 6) << 8
|
||||
| i32::from(m.extra.variant2 & 15) << 16
|
||||
| i32::from(m.extra.variant3 & 15) << 24;
|
||||
map.insert("Variant".into(), Tag::Int(packed));
|
||||
}
|
||||
"minecraft:allay" => {
|
||||
// InventoryCarrier: the fetched stack; the liked player memory.
|
||||
let mut inv = Vec::new();
|
||||
@@ -1092,6 +1121,7 @@ pub fn mob_from_nbt(tag: &Tag, types: &HashMap<String, Arc<MobType>>, id: u32) -
|
||||
if m.species() == crate::mobs::Species::Axolotl {
|
||||
restore_axolotl_memories(&mut m, tag);
|
||||
}
|
||||
read_variant(&mut m, tag);
|
||||
m.fire_ticks = number(tag.get("Fire")).unwrap_or(0) as i32;
|
||||
m.air = number(tag.get("Air")).unwrap_or(300) as i32;
|
||||
if m.species() == crate::mobs::Species::Allay {
|
||||
@@ -2273,6 +2303,41 @@ fn write_axolotl_memories(m: &Mob, map: &mut Compound) {
|
||||
}
|
||||
}
|
||||
}
|
||||
/// The variant tags `Axolotl`, `Rabbit`, `Parrot`, `Salmon` and
|
||||
/// `TropicalFish` read; a missing tag is the default variant (a medium
|
||||
/// salmon, otherwise index 0).
|
||||
fn read_variant(m: &mut Mob, tag: &Tag) {
|
||||
use crate::mobs::Species as S;
|
||||
let int = |key| number(tag.get(key)).unwrap_or(0) as i32;
|
||||
match m.species() {
|
||||
S::Axolotl | S::Parrot => m.extra.variant = int("Variant").clamp(0, 4) as u8,
|
||||
// Rabbit.Variant.LEGACY_CODEC: an unknown id is brown.
|
||||
S::Rabbit => {
|
||||
m.extra.variant = match int("RabbitType") {
|
||||
v @ (0..=5 | 99) => v as u8,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
S::Salmon => {
|
||||
m.extra.variant = text(tag.get("type"))
|
||||
.and_then(|t| SALMON_SIZES.iter().position(|v| *v == t))
|
||||
.unwrap_or(1) as u8;
|
||||
}
|
||||
S::TropicalFish => {
|
||||
let packed = int("Variant");
|
||||
let (size, index) = (packed & 0xFF, (packed >> 8) & 0xFF);
|
||||
// TropicalFish.Pattern.byId: an unknown id is a kob.
|
||||
m.extra.variant = if size <= 1 && index < 6 {
|
||||
(size * 6 + index) as u8
|
||||
} else {
|
||||
0
|
||||
};
|
||||
m.extra.variant2 = ((packed >> 16) & 15) as u8;
|
||||
m.extra.variant3 = ((packed >> 24) & 15) as u8;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
fn restore_axolotl_memories(m: &mut Mob, tag: &Tag) {
|
||||
let memories = tag.get("Brain").and_then(|b| b.get("memories"));
|
||||
let ttl = memories
|
||||
|
||||
@@ -177,8 +177,71 @@ pub fn body(m: &Mob) -> (String, String) {
|
||||
"frog#main".into(),
|
||||
format!("entity/frog/frog_{}", climate(m)),
|
||||
),
|
||||
S::Rabbit => (
|
||||
baby_or(m, "rabbit#main", "rabbit_baby#main"),
|
||||
// RabbitRenderer.getTextureLocation: the Toast name tag, else the
|
||||
// variant (the killer bunny's id is 99).
|
||||
S::Rabbit => {
|
||||
let name = if m.custom_name.as_deref() == Some("Toast") {
|
||||
"toast"
|
||||
} else {
|
||||
match m.extra.variant {
|
||||
1 => "white",
|
||||
2 => "black",
|
||||
3 => "white_splotched",
|
||||
4 => "gold",
|
||||
5 => "salt",
|
||||
99 => "caerbannog",
|
||||
_ => "brown",
|
||||
}
|
||||
};
|
||||
(
|
||||
baby_or(m, "rabbit#main", "rabbit_baby#main"),
|
||||
b(&format!("entity/rabbit/rabbit_{name}")),
|
||||
)
|
||||
}
|
||||
// ParrotRenderer.getVariantTexture.
|
||||
S::Parrot => {
|
||||
let name = ["red_blue", "blue", "green", "yellow_blue", "grey"]
|
||||
[usize::from(m.extra.variant).min(4)];
|
||||
(m.kind.model_key(), format!("entity/parrot/parrot_{name}"))
|
||||
}
|
||||
// AxolotlRenderer.getTextureLocation.
|
||||
S::Axolotl => {
|
||||
let name =
|
||||
["lucy", "wild", "gold", "cyan", "blue"][usize::from(m.extra.variant).min(4)];
|
||||
(
|
||||
baby_or(m, "axolotl#main", "axolotl_baby#main"),
|
||||
b(&format!("entity/axolotl/axolotl_{name}")),
|
||||
)
|
||||
}
|
||||
// SalmonRenderer.submit: the model of the salmon's size.
|
||||
S::Salmon => {
|
||||
let model = match m.extra.variant {
|
||||
0 => "salmon_small#main",
|
||||
2 => "salmon_large#main",
|
||||
_ => "salmon#main",
|
||||
};
|
||||
(model.into(), "entity/fish/salmon".into())
|
||||
}
|
||||
// The baby models and textures of AgeableMobRenderer's other
|
||||
// subclasses.
|
||||
S::Goat => (
|
||||
baby_or(m, "goat#main", "goat_baby#main"),
|
||||
b(&m.kind.texture),
|
||||
),
|
||||
S::PolarBear => (
|
||||
baby_or(m, "polar_bear#main", "polar_bear_baby#main"),
|
||||
b(&m.kind.texture),
|
||||
),
|
||||
S::Ocelot => (
|
||||
baby_or(m, "ocelot#main", "ocelot_baby#main"),
|
||||
b(&m.kind.texture),
|
||||
),
|
||||
S::Turtle => (
|
||||
baby_or(m, "turtle#main", "turtle_baby#main"),
|
||||
b(&m.kind.texture),
|
||||
),
|
||||
S::Armadillo => (
|
||||
baby_or(m, "armadillo#main", "armadillo_baby#main"),
|
||||
b(&m.kind.texture),
|
||||
),
|
||||
S::Pig => {
|
||||
@@ -241,7 +304,7 @@ pub fn body(m: &Mob) -> (String, String) {
|
||||
),
|
||||
S::ZombieVillager => (
|
||||
baby_or(m, "zombie_villager#main", "zombie_villager_baby#main"),
|
||||
"entity/zombie_villager/zombie_villager".into(),
|
||||
b("entity/zombie_villager/zombie_villager"),
|
||||
),
|
||||
S::Villager => (
|
||||
baby_or(m, "villager#main", "villager_baby#main"),
|
||||
|
||||
Reference in new issue
Block a user