mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'master' into 'master'
Started work on adding terrain See merge request veloren/fresh!2
This commit is contained in:
commit
7d308b53ce
@ -2,7 +2,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
// Internal
|
||||
use common::LocalState;
|
||||
use common::state::State;
|
||||
|
||||
pub enum ClientErr {
|
||||
ServerShutdown,
|
||||
@ -14,7 +14,7 @@ pub struct Input {
|
||||
}
|
||||
|
||||
pub struct Client {
|
||||
state: LocalState,
|
||||
state: State,
|
||||
|
||||
// TODO: Add "meta" state here
|
||||
}
|
||||
@ -22,7 +22,7 @@ pub struct Client {
|
||||
impl Client {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
state: LocalState::new(),
|
||||
state: State::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,3 +6,4 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
specs = "0.14"
|
||||
vek = "0.9"
|
||||
|
@ -1,6 +1,10 @@
|
||||
pub mod phys;
|
||||
|
||||
// External
|
||||
use specs::{World as EcsWorld, Builder};
|
||||
|
||||
pub fn register_local_components(ecs_world: &mut EcsWorld) {
|
||||
// TODO: Register local components here
|
||||
ecs_world.register::<phys::Pos>();
|
||||
ecs_world.register::<phys::Vel>();
|
||||
ecs_world.register::<phys::Dir>();
|
||||
}
|
||||
|
30
common/src/comp/phys.rs
Normal file
30
common/src/comp/phys.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// Library
|
||||
use specs::{Component, VecStorage};
|
||||
use vek::*;
|
||||
|
||||
// Pos
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Pos(pub Vec3<f32>);
|
||||
|
||||
impl Component for Pos {
|
||||
type Storage = VecStorage<Self>;
|
||||
}
|
||||
|
||||
// Vel
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Vel(pub Vec3<f32>);
|
||||
|
||||
impl Component for Vel {
|
||||
type Storage = VecStorage<Self>;
|
||||
}
|
||||
|
||||
// Dir
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Dir(pub Vec3<f32>);
|
||||
|
||||
impl Component for Dir {
|
||||
type Storage = VecStorage<Self>;
|
||||
}
|
@ -1,30 +1,7 @@
|
||||
#![feature(euclidean_division)]
|
||||
|
||||
pub mod comp;
|
||||
|
||||
// Standard
|
||||
use std::time::Duration;
|
||||
|
||||
// External
|
||||
use specs::{World as EcsWorld, Builder};
|
||||
|
||||
// A type used to represent game state stored on both the client and the server. This includes
|
||||
// things like entity components, terrain data, and global state like weather, time of day, etc.
|
||||
pub struct LocalState {
|
||||
ecs_world: EcsWorld
|
||||
}
|
||||
|
||||
impl LocalState {
|
||||
pub fn new() -> Self {
|
||||
let mut ecs_world = EcsWorld::new();
|
||||
|
||||
comp::register_local_components(&mut ecs_world);
|
||||
|
||||
Self {
|
||||
ecs_world,
|
||||
}
|
||||
}
|
||||
|
||||
// Execute a single tick, simulating the game state by the given duration
|
||||
pub fn tick(&mut self, dt: Duration) {
|
||||
println!("Ticked!");
|
||||
}
|
||||
}
|
||||
pub mod state;
|
||||
pub mod terrain;
|
||||
pub mod volumes;
|
||||
pub mod vol;
|
||||
|
39
common/src/state.rs
Normal file
39
common/src/state.rs
Normal file
@ -0,0 +1,39 @@
|
||||
// Standard
|
||||
use std::time::Duration;
|
||||
|
||||
// External
|
||||
use specs::World as EcsWorld;
|
||||
|
||||
// Crate
|
||||
use crate::{
|
||||
comp,
|
||||
terrain::TerrainMap,
|
||||
vol::VolSize,
|
||||
};
|
||||
|
||||
// A type used to represent game state stored on both the client and the server. This includes
|
||||
// things like entity components, terrain data, and global state like weather, time of day, etc.
|
||||
pub struct State {
|
||||
ecs_world: EcsWorld,
|
||||
terrain_map: TerrainMap,
|
||||
time: f64,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> Self {
|
||||
let mut ecs_world = EcsWorld::new();
|
||||
|
||||
comp::register_local_components(&mut ecs_world);
|
||||
|
||||
Self {
|
||||
ecs_world,
|
||||
terrain_map: TerrainMap::new(),
|
||||
time: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
// Execute a single tick, simulating the game state by the given duration
|
||||
pub fn tick(&mut self, dt: Duration) {
|
||||
println!("Ticked!");
|
||||
}
|
||||
}
|
9
common/src/terrain/biome.rs
Normal file
9
common/src/terrain/biome.rs
Normal file
@ -0,0 +1,9 @@
|
||||
pub enum BiomeKind {
|
||||
Grassland,
|
||||
Ocean,
|
||||
Mountain,
|
||||
Snowlands,
|
||||
Desert,
|
||||
Swamp,
|
||||
Forest,
|
||||
}
|
4
common/src/terrain/block.rs
Normal file
4
common/src/terrain/block.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub struct Block {
|
||||
kind: u8,
|
||||
color: [u8; 3],
|
||||
}
|
35
common/src/terrain/mod.rs
Normal file
35
common/src/terrain/mod.rs
Normal file
@ -0,0 +1,35 @@
|
||||
pub mod block;
|
||||
pub mod biome;
|
||||
|
||||
// Library
|
||||
use vek::*;
|
||||
|
||||
// Crate
|
||||
use crate::{
|
||||
vol::VolSize,
|
||||
volumes::vol_map::VolMap,
|
||||
};
|
||||
|
||||
// Local
|
||||
use self::{
|
||||
block::Block,
|
||||
biome::BiomeKind,
|
||||
};
|
||||
|
||||
// ChunkSize
|
||||
|
||||
pub struct ChunkSize;
|
||||
|
||||
impl VolSize for ChunkSize {
|
||||
const SIZE: Vec3<u32> = Vec3 { x: 32, y: 32, z: 32 };
|
||||
}
|
||||
|
||||
// ChunkMeta
|
||||
|
||||
pub struct ChunkMeta {
|
||||
biome: BiomeKind,
|
||||
}
|
||||
|
||||
// TerrainMap
|
||||
|
||||
pub type TerrainMap = VolMap<Block, ChunkSize, ChunkMeta>;
|
27
common/src/vol.rs
Normal file
27
common/src/vol.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// Library
|
||||
use vek::*;
|
||||
|
||||
pub trait BaseVol {
|
||||
type Vox;
|
||||
type Err;
|
||||
}
|
||||
|
||||
pub trait SizedVol: BaseVol {
|
||||
const SIZE: Vec3<u32>;
|
||||
}
|
||||
|
||||
pub trait ReadVol: BaseVol {
|
||||
#[inline(always)]
|
||||
fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Err>;
|
||||
}
|
||||
|
||||
pub trait WriteVol: BaseVol {
|
||||
#[inline(always)]
|
||||
fn set(&mut self, pos: Vec3<i32>, vox: Self::Vox) -> Result<(), Self::Err>;
|
||||
}
|
||||
|
||||
// Utility traits
|
||||
|
||||
pub trait VolSize {
|
||||
const SIZE: Vec3<u32>;
|
||||
}
|
91
common/src/volumes/chunk.rs
Normal file
91
common/src/volumes/chunk.rs
Normal file
@ -0,0 +1,91 @@
|
||||
// Standard
|
||||
use std::marker::PhantomData;
|
||||
|
||||
// Library
|
||||
use vek::*;
|
||||
|
||||
// Local
|
||||
use crate::vol::{
|
||||
BaseVol,
|
||||
SizedVol,
|
||||
ReadVol,
|
||||
WriteVol,
|
||||
VolSize,
|
||||
};
|
||||
|
||||
pub enum ChunkErr {
|
||||
OutOfBounds,
|
||||
}
|
||||
|
||||
// V = Voxel
|
||||
// S = Size (replace when const generics are a thing)
|
||||
// M = Metadata
|
||||
pub struct Chunk<V, S: VolSize, M> {
|
||||
vox: Vec<V>,
|
||||
meta: M,
|
||||
phantom: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> Chunk<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn idx_for(pos: Vec3<i32>) -> Option<usize> {
|
||||
if
|
||||
pos.map(|e| e >= 0).reduce_and() &&
|
||||
pos.map2(S::SIZE, |e, lim| e < lim as i32).reduce_and()
|
||||
{
|
||||
Some((
|
||||
pos.x * S::SIZE.y as i32 * S::SIZE.z as i32 +
|
||||
pos.y * S::SIZE.z as i32 +
|
||||
pos.z
|
||||
) as usize)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> BaseVol for Chunk<V, S, M> {
|
||||
type Vox = V;
|
||||
type Err = ChunkErr;
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> SizedVol for Chunk<V, S, M> {
|
||||
const SIZE: Vec3<u32> = Vec3 { x: 32, y: 32, z: 32 };
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> ReadVol for Chunk<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn get(&self, pos: Vec3<i32>) -> Result<&V, ChunkErr> {
|
||||
Self::idx_for(pos)
|
||||
.and_then(|idx| self.vox.get(idx))
|
||||
.ok_or(ChunkErr::OutOfBounds)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> WriteVol for Chunk<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn set(&mut self, pos: Vec3<i32>, vox: Self::Vox) -> Result<(), ChunkErr> {
|
||||
Self::idx_for(pos)
|
||||
.and_then(|idx| self.vox.get_mut(idx))
|
||||
.map(|old_vox| *old_vox = vox)
|
||||
.ok_or(ChunkErr::OutOfBounds)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: Clone, S: VolSize, M> Chunk<V, S, M> {
|
||||
pub fn filled(vox: V, meta: M) -> Self {
|
||||
Self {
|
||||
vox: vec![vox; S::SIZE.product() as usize],
|
||||
meta,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> &M {
|
||||
&self.meta
|
||||
}
|
||||
|
||||
pub fn metadata_mut(&mut self) -> &mut M {
|
||||
&mut self.meta
|
||||
}
|
||||
}
|
2
common/src/volumes/mod.rs
Normal file
2
common/src/volumes/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod chunk;
|
||||
pub mod vol_map;
|
79
common/src/volumes/vol_map.rs
Normal file
79
common/src/volumes/vol_map.rs
Normal file
@ -0,0 +1,79 @@
|
||||
// Standard
|
||||
use std::collections::HashMap;
|
||||
|
||||
// Library
|
||||
use vek::*;
|
||||
|
||||
// Crate
|
||||
use crate::{
|
||||
vol::{
|
||||
BaseVol,
|
||||
ReadVol,
|
||||
WriteVol,
|
||||
VolSize,
|
||||
},
|
||||
volumes::chunk::{Chunk, ChunkErr},
|
||||
};
|
||||
|
||||
pub enum VolMapErr {
|
||||
NoSuchChunk,
|
||||
ChunkErr(ChunkErr),
|
||||
}
|
||||
|
||||
// V = Voxel
|
||||
// S = Size (replace with a const when const generics is a thing)
|
||||
// M = Chunk metadata
|
||||
pub struct VolMap<V, S: VolSize, M> {
|
||||
chunks: HashMap<Vec3<i32>, Chunk<V, S, M>>,
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> VolMap<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn chunk_key(pos: Vec3<i32>) -> Vec3<i32> {
|
||||
pos.map2(S::SIZE, |e, sz| e.div_euclid(sz as i32))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn chunk_offs(pos: Vec3<i32>) -> Vec3<i32> {
|
||||
pos.map2(S::SIZE, |e, sz| e.rem_euclid(sz as i32))
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> BaseVol for VolMap<V, S, M> {
|
||||
type Vox = V;
|
||||
type Err = VolMapErr;
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> ReadVol for VolMap<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn get(&self, pos: Vec3<i32>) -> Result<&V, VolMapErr> {
|
||||
let ck = Self::chunk_key(pos);
|
||||
self.chunks.get(&ck)
|
||||
.ok_or(VolMapErr::NoSuchChunk)
|
||||
.and_then(|chunk| {
|
||||
let co = Self::chunk_offs(pos);
|
||||
chunk.get(co).map_err(|err| VolMapErr::ChunkErr(err))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> WriteVol for VolMap<V, S, M> {
|
||||
#[inline(always)]
|
||||
fn set(&mut self, pos: Vec3<i32>, vox: V) -> Result<(), VolMapErr> {
|
||||
let ck = Self::chunk_key(pos);
|
||||
self.chunks.get_mut(&ck)
|
||||
.ok_or(VolMapErr::NoSuchChunk)
|
||||
.and_then(|chunk| {
|
||||
let co = Self::chunk_offs(pos);
|
||||
chunk.set(co, vox).map_err(|err| VolMapErr::ChunkErr(err))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, S: VolSize, M> VolMap<V, S, M> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
chunks: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
// Internal
|
||||
use common::LocalState;
|
||||
use common::state::State;
|
||||
|
||||
pub enum ClientErr {
|
||||
ServerShutdown,
|
||||
@ -14,7 +14,7 @@ pub struct Input {
|
||||
}
|
||||
|
||||
pub struct Server {
|
||||
state: LocalState,
|
||||
state: State,
|
||||
|
||||
// TODO: Add "meta" state here
|
||||
}
|
||||
@ -22,7 +22,7 @@ pub struct Server {
|
||||
impl Server {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
state: LocalState::new(),
|
||||
state: State::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user