Merge branch 'master' into 'master'

Started work on adding terrain

See merge request veloren/fresh!2
This commit is contained in:
Joshua Barretto 2019-01-02 19:22:41 +00:00
commit 7d308b53ce
14 changed files with 334 additions and 36 deletions

View File

@ -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(),
}
}

View File

@ -6,3 +6,4 @@ edition = "2018"
[dependencies]
specs = "0.14"
vek = "0.9"

View File

@ -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
View 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>;
}

View File

@ -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
View 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!");
}
}

View File

@ -0,0 +1,9 @@
pub enum BiomeKind {
Grassland,
Ocean,
Mountain,
Snowlands,
Desert,
Swamp,
Forest,
}

View File

@ -0,0 +1,4 @@
pub struct Block {
kind: u8,
color: [u8; 3],
}

35
common/src/terrain/mod.rs Normal file
View 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
View 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>;
}

View 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
}
}

View File

@ -0,0 +1,2 @@
pub mod chunk;
pub mod vol_map;

View 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(),
}
}
}

View File

@ -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(),
}
}