mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
140 lines
4.4 KiB
Rust
140 lines
4.4 KiB
Rust
|
use common::{
|
||
|
comp::{
|
||
|
inventory::item::MaterialStatManifest,
|
||
|
skills::{GeneralSkill, Skill},
|
||
|
Auras, Buffs, CharacterState, Collider, Combo, Controller, Energy, Health, Ori, Pos, Stats,
|
||
|
Vel,
|
||
|
},
|
||
|
resources::{DeltaTime, GameMode, Time},
|
||
|
skillset_builder::SkillSetBuilder,
|
||
|
terrain::{Block, BlockKind, SpriteKind, TerrainChunk, TerrainChunkMeta, TerrainGrid},
|
||
|
};
|
||
|
use common_ecs::{dispatch, System};
|
||
|
use common_net::sync::WorldSyncExt;
|
||
|
use common_state::State;
|
||
|
use rand::{prelude::*, rngs::SmallRng};
|
||
|
use specs::{Builder, Entity, WorldExt};
|
||
|
use std::{error::Error, sync::Arc, time::Duration};
|
||
|
use vek::{Rgb, Vec2, Vec3};
|
||
|
use veloren_common_systems::{character_behavior, phys};
|
||
|
|
||
|
pub const EPSILON: f32 = 0.00002;
|
||
|
const DT_MILLIS: u64 = 10;
|
||
|
const MILLIS_PER_SEC: f64 = 1_000.0;
|
||
|
pub const DT: Duration = Duration::from_millis(DT_MILLIS);
|
||
|
pub const DT_F64: f64 = DT_MILLIS as f64 / MILLIS_PER_SEC;
|
||
|
|
||
|
pub fn setup() -> State {
|
||
|
let mut state = State::new(GameMode::Server);
|
||
|
state.ecs_mut().insert(MaterialStatManifest::with_empty());
|
||
|
state.ecs_mut().read_resource::<Time>();
|
||
|
state.ecs_mut().read_resource::<DeltaTime>();
|
||
|
state.ecs_mut().insert(TerrainGrid::new());
|
||
|
for x in 0..2 {
|
||
|
for y in 0..2 {
|
||
|
generate_chunk(&mut state, Vec2::new(x, y));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
state
|
||
|
}
|
||
|
|
||
|
pub fn tick(state: &mut State, dt: Duration) {
|
||
|
state.tick(
|
||
|
dt,
|
||
|
|dispatch_builder| {
|
||
|
dispatch::<character_behavior::Sys>(dispatch_builder, &[]);
|
||
|
dispatch::<phys::Sys>(dispatch_builder, &[&character_behavior::Sys::sys_name()]);
|
||
|
},
|
||
|
false,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
pub fn set_control(
|
||
|
state: &mut State,
|
||
|
entity: Entity,
|
||
|
control: Controller,
|
||
|
) -> Result<(), specs::error::Error> {
|
||
|
let mut storage = state.ecs_mut().write_storage::<Controller>();
|
||
|
storage.insert(entity, control).map(|_| ())
|
||
|
}
|
||
|
|
||
|
pub fn get_transform(state: &State, entity: Entity) -> Result<(Pos, Vel, Ori), Box<dyn Error>> {
|
||
|
let storage = state.ecs().read_storage::<Pos>();
|
||
|
let pos = *storage
|
||
|
.get(entity)
|
||
|
.ok_or("Storage does not contain Entity Pos")?;
|
||
|
let storage = state.ecs().read_storage::<Vel>();
|
||
|
let vel = *storage
|
||
|
.get(entity)
|
||
|
.ok_or("Storage does not contain Entity Vel")?;
|
||
|
let storage = state.ecs().read_storage::<Ori>();
|
||
|
let ori = *storage
|
||
|
.get(entity)
|
||
|
.ok_or("Storage does not contain Entity Ori")?;
|
||
|
|
||
|
Ok((pos, vel, ori))
|
||
|
}
|
||
|
|
||
|
pub fn create_player(state: &mut State) -> Entity {
|
||
|
let body = common::comp::Body::Humanoid(common::comp::humanoid::Body::random_with(
|
||
|
&mut thread_rng(),
|
||
|
&common::comp::humanoid::Species::Human,
|
||
|
));
|
||
|
let (p0, p1, radius) = body.sausage();
|
||
|
let collider = Collider::CapsulePrism {
|
||
|
p0,
|
||
|
p1,
|
||
|
radius,
|
||
|
z_min: 0.0,
|
||
|
z_max: body.height(),
|
||
|
};
|
||
|
let skill_set = SkillSetBuilder::default().build();
|
||
|
|
||
|
state
|
||
|
.ecs_mut()
|
||
|
.create_entity_synced()
|
||
|
.with(Pos(Vec3::new(16.0, 16.0, 265.0)))
|
||
|
.with(Vel::default())
|
||
|
.with(Ori::default())
|
||
|
.with(body.mass())
|
||
|
.with(body.density())
|
||
|
.with(collider)
|
||
|
.with(body)
|
||
|
.with(Controller::default())
|
||
|
.with(CharacterState::default())
|
||
|
.with(Buffs::default())
|
||
|
.with(Combo::default())
|
||
|
.with(Auras::default())
|
||
|
.with(Energy::new(
|
||
|
body,
|
||
|
skill_set
|
||
|
.skill_level(Skill::General(GeneralSkill::EnergyIncrease))
|
||
|
.unwrap_or(0),
|
||
|
))
|
||
|
.with(Health::new(body, body.base_health()))
|
||
|
.with(skill_set)
|
||
|
.with(Stats::empty())
|
||
|
.build()
|
||
|
}
|
||
|
|
||
|
pub fn generate_chunk(state: &mut State, chunk_pos: Vec2<i32>) {
|
||
|
let (x, y) = chunk_pos.map(|e| e.to_le_bytes()).into_tuple();
|
||
|
let mut rng = SmallRng::from_seed([
|
||
|
x[0], x[1], x[2], x[3], y[0], y[1], y[2], y[3], x[0], x[1], x[2], x[3], y[0], y[1], y[2],
|
||
|
y[3], x[0], x[1], x[2], x[3], y[0], y[1], y[2], y[3], x[0], x[1], x[2], x[3], y[0], y[1],
|
||
|
y[2], y[3],
|
||
|
]);
|
||
|
let height = rng.gen::<i32>() % 8;
|
||
|
|
||
|
state.ecs().write_resource::<TerrainGrid>().insert(
|
||
|
chunk_pos,
|
||
|
Arc::new(TerrainChunk::new(
|
||
|
256 + if rng.gen::<u8>() < 64 { height } else { 0 },
|
||
|
Block::new(BlockKind::Grass, Rgb::new(11, 102, 35)),
|
||
|
Block::air(SpriteKind::Empty),
|
||
|
TerrainChunkMeta::void(),
|
||
|
)),
|
||
|
);
|
||
|
}
|