mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 17:21:49 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43b029b5d9 |
No files matched your search
@@ -1192,6 +1192,7 @@ mod preview_tests {
|
||||
entity_tags: Default::default(),
|
||||
villager_hats: Default::default(),
|
||||
pois: Default::default(),
|
||||
species_placements: Default::default(),
|
||||
};
|
||||
let draw = |body: bool| {
|
||||
let mut out = Vec::new();
|
||||
|
||||
@@ -33,7 +33,7 @@ pub struct StateData {
|
||||
/// Collision shape top (0 when the shape is empty).
|
||||
pub top: f32,
|
||||
}
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Placement {
|
||||
OnGround,
|
||||
InWater,
|
||||
@@ -55,6 +55,9 @@ pub struct MobData {
|
||||
/// The villager POI type of every block state (`PoiTypes.forState`),
|
||||
/// worked out the first time a villager looks for one.
|
||||
pub pois: std::sync::OnceLock<Vec<Option<super::villager_brain::Poi>>>,
|
||||
/// [`MobData::placement`] of each species' entity type (by `Species as
|
||||
/// usize`), worked out the first time a spawn asks.
|
||||
pub species_placements: std::sync::OnceLock<Vec<Placement>>,
|
||||
}
|
||||
impl MobData {
|
||||
pub fn load(root: &Path, facts: &BlockFacts) -> Self {
|
||||
@@ -145,6 +148,7 @@ impl MobData {
|
||||
biome_tags: HashMap::new(),
|
||||
entity_tags: HashMap::new(),
|
||||
pois: Default::default(),
|
||||
species_placements: Default::default(),
|
||||
}
|
||||
}
|
||||
/// Without the export, approximate path types from the gameplay facts.
|
||||
@@ -201,6 +205,7 @@ impl MobData {
|
||||
biome_tags: HashMap::new(),
|
||||
entity_tags: HashMap::new(),
|
||||
pois: Default::default(),
|
||||
species_placements: Default::default(),
|
||||
}
|
||||
}
|
||||
pub fn state(&self, id: horizon_world::registry::BlockStateId) -> StateData {
|
||||
@@ -222,7 +227,28 @@ impl MobData {
|
||||
pub fn placement(&self, entity: &str) -> Placement {
|
||||
self.placements
|
||||
.get(entity)
|
||||
.cloned()
|
||||
.copied()
|
||||
.unwrap_or(Placement::OnGround)
|
||||
}
|
||||
/// [`MobData::placement`] of the species' entity type, without building
|
||||
/// its id: natural spawning asks it for every position it tries.
|
||||
pub fn species_placement(&self, s: super::Species) -> Placement {
|
||||
let table = self.species_placements.get_or_init(|| {
|
||||
let defs = super::species::ALL;
|
||||
let len = defs
|
||||
.iter()
|
||||
.map(|d| d.species as usize + 1)
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
let mut table = vec![Placement::OnGround; len];
|
||||
// `species::def` takes a species' first definition: so does this.
|
||||
for d in defs.iter().rev() {
|
||||
table[d.species as usize] = self.placement(&format!("minecraft:{}", d.name));
|
||||
}
|
||||
table
|
||||
});
|
||||
table.get(s as usize).copied().unwrap_or_else(|| {
|
||||
self.placement(&format!("minecraft:{}", super::species::def(s).name))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1887,6 +1887,7 @@ mod tests {
|
||||
entity_tags: Default::default(),
|
||||
villager_hats: Default::default(),
|
||||
pois: Default::default(),
|
||||
species_placements: Default::default(),
|
||||
};
|
||||
let atlas = |name: &str| {
|
||||
Some(if name.contains("_inner") {
|
||||
@@ -1975,6 +1976,7 @@ mod tests {
|
||||
entity_tags: Default::default(),
|
||||
villager_hats: Default::default(),
|
||||
pois: Default::default(),
|
||||
species_placements: Default::default(),
|
||||
};
|
||||
let atlas = |name: &str| {
|
||||
Some(if name.contains("copper_golem_eyes") {
|
||||
@@ -2027,6 +2029,7 @@ mod tests {
|
||||
entity_tags: Default::default(),
|
||||
villager_hats: Default::default(),
|
||||
pois: Default::default(),
|
||||
species_placements: Default::default(),
|
||||
};
|
||||
for left in [false, true] {
|
||||
let t = held_item_transform(&mob, 0.5, glam::DVec3::ZERO, &data, left).unwrap();
|
||||
@@ -2112,6 +2115,7 @@ mod tests {
|
||||
entity_tags: Default::default(),
|
||||
villager_hats: Default::default(),
|
||||
pois: Default::default(),
|
||||
species_placements: Default::default(),
|
||||
};
|
||||
let atlas = |_: &str| Some([0.0, 0.0, 0.25, 0.25]);
|
||||
let part = &kind.model;
|
||||
|
||||
@@ -244,8 +244,7 @@ pub fn is_valid_empty_spawn<L: SpawnLevel>(s: Species, l: &L, x: i32, y: i32, z:
|
||||
}
|
||||
/// `SpawnPlacements.isSpawnPositionOk`.
|
||||
pub fn is_spawn_position_ok<L: SpawnLevel>(s: Species, l: &L, x: i32, y: i32, z: i32) -> bool {
|
||||
let id = format!("minecraft:{}", super::species::def(s).name);
|
||||
match l.mob_data().placement(&id) {
|
||||
match l.mob_data().species_placement(s) {
|
||||
data::Placement::OnGround => {
|
||||
is_valid_spawn(s, l, x, y - 1, z)
|
||||
&& is_valid_empty_spawn(s, l, x, y, z)
|
||||
|
||||
@@ -1209,6 +1209,13 @@ fn valid_position_for_type<L: NaturalLevel, R: RandomSource>(
|
||||
return false;
|
||||
}
|
||||
let [x, y, z] = pos;
|
||||
// `canSpawnMobAt` comes first in vanilla, but it and `isSpawnPositionOk`
|
||||
// only read the level, so their order cannot change the answer: the few
|
||||
// block reads of the placement turn most positions away before the spawn
|
||||
// list (structures, biome) is looked up again.
|
||||
if !spawn_rules::is_spawn_position_ok(species, l, x, y, z) {
|
||||
return false;
|
||||
}
|
||||
if !listed
|
||||
&& !mobs_at(l, category, x, y, z)
|
||||
.iter()
|
||||
@@ -1216,9 +1223,6 @@ fn valid_position_for_type<L: NaturalLevel, R: RandomSource>(
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if !spawn_rules::is_spawn_position_ok(species, l, x, y, z) {
|
||||
return false;
|
||||
}
|
||||
if !spawn_rules::check_spawn_rules(species, l, Reason::Natural, random, x, y, z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user