mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
6c6b9181a5
* use version of shred that has an added SendDispatcher so we can construct the dispatcher and send it between threads (only State to remain sendable) * move closure for adding systems from State::tick to the creation functions * this does mean some voxygen systems always run instead of just in the session state, but that should not cause issues and we can always configure them to do nothing if needed
131 lines
4.5 KiB
Rust
131 lines
4.5 KiB
Rust
#[cfg(test)]
|
|
mod tests {
|
|
use common::{
|
|
comp::{
|
|
item::MaterialStatManifest, skills::GeneralSkill, tool::AbilityMap, CharacterActivity,
|
|
CharacterState, Controller, Energy, Ori, PhysicsState, Poise, Pos, Skill, Stats, Vel,
|
|
},
|
|
resources::{DeltaTime, GameMode, Time},
|
|
shared_server_config::ServerConstants,
|
|
terrain::{MapSizeLg, TerrainChunk},
|
|
uid::Uid,
|
|
util::Dir,
|
|
SkillSetBuilder,
|
|
};
|
|
use common_ecs::dispatch;
|
|
use common_state::State;
|
|
use rand::thread_rng;
|
|
use specs::{Builder, Entity, WorldExt};
|
|
use std::{sync::Arc, time::Duration};
|
|
use vek::{approx::AbsDiffEq, Vec2, Vec3};
|
|
use veloren_common_systems::character_behavior;
|
|
|
|
const DEFAULT_WORLD_CHUNKS_LG: MapSizeLg =
|
|
if let Ok(map_size_lg) = MapSizeLg::new(Vec2 { x: 1, y: 1 }) {
|
|
map_size_lg
|
|
} else {
|
|
panic!("Default world chunk size does not satisfy required invariants.");
|
|
};
|
|
|
|
fn setup() -> State {
|
|
let pools = State::pools(GameMode::Server);
|
|
let mut state = State::new(
|
|
GameMode::Server,
|
|
pools,
|
|
DEFAULT_WORLD_CHUNKS_LG,
|
|
Arc::new(TerrainChunk::water(0)),
|
|
|dispatch_builder| {
|
|
dispatch::<character_behavior::Sys>(dispatch_builder, &[]);
|
|
},
|
|
);
|
|
let msm = MaterialStatManifest::load().cloned();
|
|
state.ecs_mut().insert(msm);
|
|
state.ecs_mut().insert(AbilityMap::load().cloned());
|
|
state.ecs_mut().read_resource::<Time>();
|
|
state.ecs_mut().read_resource::<DeltaTime>();
|
|
state
|
|
}
|
|
|
|
fn create_entity(state: &mut State, ori: Ori) -> Entity {
|
|
let body = common::comp::Body::Humanoid(common::comp::humanoid::Body::random_with(
|
|
&mut thread_rng(),
|
|
&common::comp::humanoid::Species::Human,
|
|
));
|
|
let skill_set = SkillSetBuilder::default().build();
|
|
state
|
|
.ecs_mut()
|
|
.create_entity()
|
|
.with(CharacterState::Idle(common::states::idle::Data::default()))
|
|
.with(CharacterActivity::default())
|
|
.with(Pos(Vec3::zero()))
|
|
.with(Vel::default())
|
|
.with(ori)
|
|
.with(body.mass())
|
|
.with(body.density())
|
|
.with(body)
|
|
.with(Energy::new(
|
|
body,
|
|
skill_set
|
|
.skill_level(Skill::General(GeneralSkill::EnergyIncrease))
|
|
.unwrap_or(0),
|
|
))
|
|
.with(Controller::default())
|
|
.with(Poise::new(body))
|
|
.with(skill_set)
|
|
.with(PhysicsState::default())
|
|
.with(Stats::empty(body))
|
|
.with(Uid(1))
|
|
.build()
|
|
}
|
|
|
|
fn tick(state: &mut State, dt: Duration) {
|
|
state.tick(
|
|
dt,
|
|
false,
|
|
None,
|
|
&ServerConstants {
|
|
day_cycle_coefficient: 24.0,
|
|
},
|
|
|_, _| {},
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn orientation_shortcut() {
|
|
let mut state = setup();
|
|
const TESTCASES: usize = 5;
|
|
let testcases: [(Vec3<f32>, Vec3<f32>); TESTCASES] = [
|
|
// horizontal is unchanged
|
|
(Vec3::unit_x(), Vec3::unit_x()),
|
|
// nearly vertical takes time to adjust
|
|
(Vec3::new(0.1, 0.1, 1.0), Vec3::new(0.149, 0.149, 0.978)),
|
|
// intermediate case
|
|
(Vec3::new(0.6, 0.6, 0.1), Vec3::new(0.706, 0.706, 0.052)),
|
|
// edge case: nearly horizontal after system
|
|
(Vec3::new(0.6, 0.6, 0.0556), Vec3::new(0.707, 0.707, 0.000)),
|
|
// small enough to be horizontal in one step
|
|
(Vec3::new(0.6, 0.6, 0.04), Vec3::new(0.707, 0.707, 0.000)),
|
|
];
|
|
let mut entities: [Option<Entity>; TESTCASES] = [None; TESTCASES];
|
|
for i in 0..TESTCASES {
|
|
entities[i] = Some(create_entity(
|
|
&mut state,
|
|
Ori::from_unnormalized_vec(testcases[i].0).unwrap_or_default(),
|
|
));
|
|
}
|
|
tick(&mut state, Duration::from_secs_f32(0.033));
|
|
let results = state.ecs().read_storage::<Ori>();
|
|
for i in 0..TESTCASES {
|
|
if let Some(e) = entities[i] {
|
|
let result = Dir::from(*results.get(e).expect("Ori missing"));
|
|
assert!(
|
|
result.abs_diff_eq(&testcases[i].1, 0.0005),
|
|
"{:?} != {:?}",
|
|
result,
|
|
testcases[i].1
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|