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;
|
use std::time::Duration;
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
use common::LocalState;
|
use common::state::State;
|
||||||
|
|
||||||
pub enum ClientErr {
|
pub enum ClientErr {
|
||||||
ServerShutdown,
|
ServerShutdown,
|
||||||
@ -14,7 +14,7 @@ pub struct Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
state: LocalState,
|
state: State,
|
||||||
|
|
||||||
// TODO: Add "meta" state here
|
// TODO: Add "meta" state here
|
||||||
}
|
}
|
||||||
@ -22,7 +22,7 @@ pub struct Client {
|
|||||||
impl Client {
|
impl Client {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: LocalState::new(),
|
state: State::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,3 +6,4 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
specs = "0.14"
|
specs = "0.14"
|
||||||
|
vek = "0.9"
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
|
pub mod phys;
|
||||||
|
|
||||||
// External
|
// External
|
||||||
use specs::{World as EcsWorld, Builder};
|
use specs::{World as EcsWorld, Builder};
|
||||||
|
|
||||||
pub fn register_local_components(ecs_world: &mut EcsWorld) {
|
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;
|
pub mod comp;
|
||||||
|
pub mod state;
|
||||||
// Standard
|
pub mod terrain;
|
||||||
use std::time::Duration;
|
pub mod volumes;
|
||||||
|
pub mod vol;
|
||||||
// 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!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
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;
|
use std::time::Duration;
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
use common::LocalState;
|
use common::state::State;
|
||||||
|
|
||||||
pub enum ClientErr {
|
pub enum ClientErr {
|
||||||
ServerShutdown,
|
ServerShutdown,
|
||||||
@ -14,7 +14,7 @@ pub struct Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
state: LocalState,
|
state: State,
|
||||||
|
|
||||||
// TODO: Add "meta" state here
|
// TODO: Add "meta" state here
|
||||||
}
|
}
|
||||||
@ -22,7 +22,7 @@ pub struct Server {
|
|||||||
impl Server {
|
impl Server {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: LocalState::new(),
|
state: State::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user