Ran fmt on codebase

Former-commit-id: 7fecffa1dc66fffba4f07d45fb80960dc5178f4f
This commit is contained in:
Forest Anderson 2019-04-29 20:37:19 +00:00
parent 2bcd6b6295
commit 993388e56a
68 changed files with 1122 additions and 1117 deletions

View File

@ -1,10 +1,7 @@
use std::time::Duration; use client::{Client, Event, Input};
use common::{clock::Clock, comp};
use log::info; use log::info;
use client::{Input, Client, Event}; use std::time::Duration;
use common::{
comp,
clock::Clock,
};
const FPS: u64 = 60; const FPS: u64 = 60;
@ -18,8 +15,8 @@ fn main() {
let mut clock = Clock::new(); let mut clock = Clock::new();
// Create client // Create client
let mut client = Client::new(([127, 0, 0, 1], 59003), 300) let mut client =
.expect("Failed to create client instance"); Client::new(([127, 0, 0, 1], 59003), 300).expect("Failed to create client instance");
client.register(comp::Player::new("test".to_string())); client.register(comp::Player::new("test".to_string()));
@ -31,7 +28,7 @@ fn main() {
Err(err) => { Err(err) => {
println!("Error: {:?}", err); println!("Error: {:?}", err);
break; break;
}, }
}; };
for event in events { for event in events {

View File

@ -249,9 +249,18 @@ impl Client {
ServerMsg::Ping => self.postbox.send_message(ClientMsg::Pong), ServerMsg::Ping => self.postbox.send_message(ClientMsg::Pong),
ServerMsg::Pong => {} ServerMsg::Pong => {}
ServerMsg::Chat(msg) => frontend_events.push(Event::Chat(msg)), ServerMsg::Chat(msg) => frontend_events.push(Event::Chat(msg)),
ServerMsg::SetPlayerEntity(uid) => self.entity = self.state.ecs().entity_from_uid(uid).unwrap(), // TODO: Don't unwrap here! ServerMsg::SetPlayerEntity(uid) => {
ServerMsg::EcsSync(sync_package) => self.state.ecs_mut().sync_with_package(sync_package), self.entity = self.state.ecs().entity_from_uid(uid).unwrap()
ServerMsg::EntityPhysics { entity, pos, vel, dir } => match self.state.ecs().entity_from_uid(entity) { } // TODO: Don't unwrap here!
ServerMsg::EcsSync(sync_package) => {
self.state.ecs_mut().sync_with_package(sync_package)
}
ServerMsg::EntityPhysics {
entity,
pos,
vel,
dir,
} => match self.state.ecs().entity_from_uid(entity) {
Some(entity) => { Some(entity) => {
self.state.write_component(entity, pos); self.state.write_component(entity, pos);
self.state.write_component(entity, vel); self.state.write_component(entity, vel);
@ -259,7 +268,10 @@ impl Client {
} }
None => {} None => {}
}, },
ServerMsg::EntityAnimation { entity, animation_history } => match self.state.ecs().entity_from_uid(entity) { ServerMsg::EntityAnimation {
entity,
animation_history,
} => match self.state.ecs().entity_from_uid(entity) {
Some(entity) => { Some(entity) => {
self.state.write_component(entity, animation_history); self.state.write_component(entity, animation_history);
} }

View File

@ -1,8 +1,8 @@
use std::env; use std::env;
use std::fs; use std::fs;
use std::fs::File;
use std::io; use std::io;
use std::io::prelude::*; use std::io::prelude::*;
use std::fs::File;
fn try_load(name: &str) -> Option<File> { fn try_load(name: &str) -> Option<File> {
let basepaths = [ let basepaths = [
@ -22,25 +22,28 @@ fn try_load(name: &str) -> Option<File> {
Ok(f) => { Ok(f) => {
debug!("loading {} succedeed", filename); debug!("loading {} succedeed", filename);
return Some(f); return Some(f);
}, }
Err(e) => { Err(e) => {
debug!("loading {} did not work with error: {}", filename, e); debug!("loading {} did not work with error: {}", filename, e);
} }
}; };
}; }
return None; return None;
} }
pub fn load(name: &str) -> Result<Vec<u8>, ()> { pub fn load(name: &str) -> Result<Vec<u8>, ()> {
return match try_load(name) { return match try_load(name) {
Some(mut f) => { Some(mut f) => {
let mut content: Vec<u8> = vec!(); let mut content: Vec<u8> = vec![];
f.read_to_end(&mut content); f.read_to_end(&mut content);
info!("loaded asset successful: {}", name); info!("loaded asset successful: {}", name);
Ok(content) Ok(content)
}, }
None => { None => {
warn!("Loading asset failed, wanted to load {} but could not load it, check debug log!", name); warn!(
"Loading asset failed, wanted to load {} but could not load it, check debug log!",
name
);
Err(()) Err(())
} }
}; };

View File

@ -23,13 +23,19 @@ impl Clock {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn get_tps(&self) -> f64 { 1.0 / self.running_tps_average } pub fn get_tps(&self) -> f64 {
1.0 / self.running_tps_average
}
#[allow(dead_code)] #[allow(dead_code)]
pub fn get_last_delta(&self) -> Duration { self.last_delta.unwrap_or(Duration::new(0, 0)) } pub fn get_last_delta(&self) -> Duration {
self.last_delta.unwrap_or(Duration::new(0, 0))
}
#[allow(dead_code)] #[allow(dead_code)]
pub fn get_avg_delta(&self) -> Duration { Duration::from_secs_f64(self.running_tps_average) } pub fn get_avg_delta(&self) -> Duration {
Duration::from_secs_f64(self.running_tps_average)
}
#[allow(dead_code)] #[allow(dead_code)]
pub fn tick(&mut self, tgt: Duration) { pub fn tick(&mut self, tgt: Duration) {
@ -44,7 +50,9 @@ impl Clock {
} else { } else {
tgt.as_secs_f64() / self.running_tps_average tgt.as_secs_f64() / self.running_tps_average
}; };
thread::sleep(Duration::from_secs_f64(sleep_dur.as_secs_f64() * adjustment)); thread::sleep(Duration::from_secs_f64(
sleep_dur.as_secs_f64() * adjustment,
));
} }
let delta = SystemTime::now() let delta = SystemTime::now()
@ -56,8 +64,8 @@ impl Clock {
self.running_tps_average = if self.running_tps_average == 0.0 { self.running_tps_average = if self.running_tps_average == 0.0 {
delta.as_secs_f64() delta.as_secs_f64()
} else { } else {
CLOCK_SMOOTHING * self.running_tps_average + CLOCK_SMOOTHING * self.running_tps_average
(1.0 - CLOCK_SMOOTHING) * delta.as_secs_f64() + (1.0 - CLOCK_SMOOTHING) * delta.as_secs_f64()
}; };
} }
} }

View File

@ -1,6 +1,6 @@
use specs::{Component, VecStorage, FlaggedStorage};
use vek::*;
use rand::prelude::*; use rand::prelude::*;
use specs::{Component, FlaggedStorage, VecStorage};
use vek::*;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Race { pub enum Race {
@ -60,14 +60,14 @@ pub enum Weapon {
Staff, Staff,
} }
use Race::*;
use Gender::*;
use Head::*;
use Chest::*;
use Belt::*; use Belt::*;
use Pants::*; use Chest::*;
use Hand::*;
use Foot::*; use Foot::*;
use Gender::*;
use Hand::*;
use Head::*;
use Pants::*;
use Race::*;
use Weapon::*; use Weapon::*;
const ALL_RACES: [Race; 6] = [Danari, Dwarf, Elf, Human, Orc, Undead]; const ALL_RACES: [Race; 6] = [Danari, Dwarf, Elf, Human, Orc, Undead];

View File

@ -1,11 +1,11 @@
pub mod agent; pub mod agent;
pub mod character; pub mod character;
pub mod player;
pub mod phys; pub mod phys;
pub mod player;
// Reexports // Reexports
pub use agent::{Agent, Control}; pub use agent::{Agent, Control};
pub use character::Animation;
pub use character::AnimationHistory;
pub use character::Character; pub use character::Character;
pub use player::Player; pub use player::Player;
pub use character::AnimationHistory;
pub use character::Animation;

View File

@ -1,4 +1,4 @@
use specs::{Component, VecStorage, FlaggedStorage, NullStorage}; use specs::{Component, FlaggedStorage, NullStorage, VecStorage};
use vek::*; use vek::*;
// Pos // Pos

View File

@ -1,4 +1,4 @@
use specs::{Component, VecStorage, FlaggedStorage}; use specs::{Component, FlaggedStorage, VecStorage};
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Player { pub struct Player {
@ -7,9 +7,7 @@ pub struct Player {
impl Player { impl Player {
pub fn new(alias: String) -> Self { pub fn new(alias: String) -> Self {
Self { Self { alias }
alias,
}
} }
} }

View File

@ -1,8 +1,8 @@
pub mod cell; pub mod cell;
// Library // Library
use vek::*;
use dot_vox::DotVoxData; use dot_vox::DotVoxData;
use vek::*;
// Crate // Crate
use crate::{ use crate::{
@ -28,11 +28,7 @@ impl From<DotVoxData> for Segment {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut segment = Segment::filled( let mut segment = Segment::filled(
Vec3::new( Vec3::new(model.size.x, model.size.y, model.size.z),
model.size.x,
model.size.y,
model.size.z,
),
Cell::empty(), Cell::empty(),
(), (),
); );

View File

@ -1,4 +1,9 @@
#![feature(euclidean_division, duration_float, trait_alias, bind_by_move_pattern_guards)] #![feature(
euclidean_division,
duration_float,
trait_alias,
bind_by_move_pattern_guards
)]
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@ -10,13 +15,13 @@ pub mod clock;
pub mod comp; pub mod comp;
pub mod figure; pub mod figure;
pub mod msg; pub mod msg;
pub mod ray;
pub mod state; pub mod state;
pub mod sys; pub mod sys;
pub mod terrain; pub mod terrain;
pub mod util; pub mod util;
pub mod volumes;
pub mod vol; pub mod vol;
pub mod ray; pub mod volumes;
// TODO: unignore the code here, for some reason it refuses to compile here while has no problems copy-pasted elsewhere // TODO: unignore the code here, for some reason it refuses to compile here while has no problems copy-pasted elsewhere
/// The networking module containing high-level wrappers of `TcpListener` and `TcpStream` (`PostOffice` and `PostBox` respectively) and data types used by both the server and client /// The networking module containing high-level wrappers of `TcpListener` and `TcpStream` (`PostOffice` and `PostBox` respectively) and data types used by both the server and client

View File

@ -1,10 +1,12 @@
use vek::*;
use super::ClientState; use super::ClientState;
use crate::comp; use crate::comp;
use vek::*;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ClientMsg { pub enum ClientMsg {
Register { player: comp::Player }, Register {
player: comp::Player,
},
Character(comp::Character), Character(comp::Character),
RequestState(ClientState), RequestState(ClientState),
Ping, Ping,

View File

@ -1,6 +1,6 @@
use std::marker::PhantomData;
use serde_derive::{Serialize, Deserialize};
use crate::comp; use crate::comp;
use serde_derive::{Deserialize, Serialize};
use std::marker::PhantomData;
// Automatically derive From<T> for Packet for each variant Packet::T(T) // Automatically derive From<T> for Packet for each variant Packet::T(T)
sphynx::sum_type! { sphynx::sum_type! {

View File

@ -1,11 +1,11 @@
pub mod client;
pub mod ecs_packet; pub mod ecs_packet;
pub mod server; pub mod server;
pub mod client;
// Reexports // Reexports
pub use self::server::{ServerMsg, RequestStateError};
pub use self::client::ClientMsg; pub use self::client::ClientMsg;
pub use self::ecs_packet::EcsPacket; pub use self::ecs_packet::EcsPacket;
pub use self::server::{RequestStateError, ServerMsg};
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum ClientState { pub enum ClientState {

View File

@ -1,9 +1,6 @@
use super::{ClientState, EcsPacket};
use crate::{comp, terrain::TerrainChunk};
use vek::*; use vek::*;
use crate::{
comp,
terrain::TerrainChunk,
};
use super::{EcsPacket, ClientState};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RequestStateError { pub enum RequestStateError {

View File

@ -7,11 +7,7 @@ pub use post2 as post;
// Reexports // Reexports
pub use self::{ pub use self::{
data::{ClientMsg, ServerMsg}, data::{ClientMsg, ServerMsg},
post::{ post::{Error as PostError, PostBox, PostOffice},
Error as PostError,
PostBox,
PostOffice,
},
}; };
pub trait PostSend = 'static + serde::Serialize + std::marker::Send + std::fmt::Debug; pub trait PostSend = 'static + serde::Serialize + std::marker::Send + std::fmt::Debug;

View File

@ -1,14 +1,17 @@
use serde::{de::DeserializeOwned, Serialize};
use std::{ use std::{
io::{self, Read, Write},
net::{TcpListener, TcpStream, SocketAddr, Shutdown},
time::{Instant, Duration},
marker::PhantomData,
sync::{mpsc, Arc, atomic::{AtomicBool, Ordering}},
thread,
collections::VecDeque, collections::VecDeque,
convert::TryFrom, convert::TryFrom,
io::{self, Read, Write},
marker::PhantomData,
net::{Shutdown, SocketAddr, TcpListener, TcpStream},
sync::{
atomic::{AtomicBool, Ordering},
mpsc, Arc,
},
thread,
time::{Duration, Instant},
}; };
use serde::{Serialize, de::DeserializeOwned};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Error { pub enum Error {
@ -73,11 +76,11 @@ impl<S: PostMsg, R: PostMsg> PostOffice<S, R> {
match self.listener.accept() { match self.listener.accept() {
Ok((stream, sock)) => new.push(PostBox::from_stream(stream).unwrap()), Ok((stream, sock)) => new.push(PostBox::from_stream(stream).unwrap()),
Err(e) if e.kind() == io::ErrorKind::WouldBlock => break, Err(e) if e.kind() == io::ErrorKind::WouldBlock => break,
Err(e) if e.kind() == io::ErrorKind::Interrupted => {}, Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => { Err(e) => {
self.error = Some(e.into()); self.error = Some(e.into());
break; break;
}, }
} }
} }
@ -136,7 +139,7 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
Err(e) => { Err(e) => {
self.error = Some(e); self.error = Some(e);
None None
}, }
} }
} }
@ -154,18 +157,23 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
Err(e) => { Err(e) => {
self.error = Some(e.into()); self.error = Some(e.into());
break; break;
}, }
Ok(Err(e)) => { Ok(Err(e)) => {
self.error = Some(e); self.error = Some(e);
break; break;
}, }
} }
} }
new.into_iter() new.into_iter()
} }
fn worker(mut stream: TcpStream, send_rx: mpsc::Receiver<S>, recv_tx: mpsc::Sender<Result<R, Error>>, running: Arc<AtomicBool>) { fn worker(
mut stream: TcpStream,
send_rx: mpsc::Receiver<S>,
recv_tx: mpsc::Sender<Result<R, Error>>,
running: Arc<AtomicBool>,
) {
let mut outgoing_chunks = VecDeque::new(); let mut outgoing_chunks = VecDeque::new();
let mut incoming_buf = Vec::new(); let mut incoming_buf = Vec::new();
@ -176,8 +184,8 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
Ok(Some(e)) | Err(e) => { Ok(Some(e)) | Err(e) => {
recv_tx.send(Err(e.into())).unwrap(); recv_tx.send(Err(e.into())).unwrap();
break 'work; break 'work;
}, }
Ok(None) => {}, Ok(None) => {}
} }
// Try getting messages from the send channel // Try getting messages from the send channel
@ -188,11 +196,7 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
let mut msg_bytes = bincode::serialize(&send_msg).unwrap(); let mut msg_bytes = bincode::serialize(&send_msg).unwrap();
// Assemble into packet // Assemble into packet
let mut packet_bytes = msg_bytes let mut packet_bytes = msg_bytes.len().to_le_bytes().as_ref().to_vec();
.len()
.to_le_bytes()
.as_ref()
.to_vec();
packet_bytes.append(&mut msg_bytes); packet_bytes.append(&mut msg_bytes);
// Split packet into chunks // Split packet into chunks
@ -200,13 +204,13 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
.chunks(4096) .chunks(4096)
.map(|chunk| chunk.to_vec()) .map(|chunk| chunk.to_vec())
.for_each(|chunk| outgoing_chunks.push_back(chunk)) .for_each(|chunk| outgoing_chunks.push_back(chunk))
}, }
Err(mpsc::TryRecvError::Empty) => break, Err(mpsc::TryRecvError::Empty) => break,
// Worker error // Worker error
Err(e) => { Err(e) => {
let _ = recv_tx.send(Err(e.into())); let _ = recv_tx.send(Err(e.into()));
break 'work; break 'work;
}, }
} }
} }
@ -218,17 +222,17 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
Ok(n) => { Ok(n) => {
outgoing_chunks.push_front(chunk.split_off(n)); outgoing_chunks.push_front(chunk.split_off(n));
break; break;
}, }
Err(e) if e.kind() == io::ErrorKind::WouldBlock => { Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
// Return chunk to the queue to try again later // Return chunk to the queue to try again later
outgoing_chunks.push_front(chunk); outgoing_chunks.push_front(chunk);
break; break;
}, }
// Worker error // Worker error
Err(e) => { Err(e) => {
recv_tx.send(Err(e.into())).unwrap(); recv_tx.send(Err(e.into())).unwrap();
break 'work; break 'work;
}, }
}, },
None => break, None => break,
} }
@ -241,12 +245,12 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
match stream.read(&mut buf) { match stream.read(&mut buf) {
Ok(n) => incoming_buf.extend_from_slice(&buf[0..n]), Ok(n) => incoming_buf.extend_from_slice(&buf[0..n]),
Err(e) if e.kind() == io::ErrorKind::WouldBlock => break, Err(e) if e.kind() == io::ErrorKind::WouldBlock => break,
Err(e) if e.kind() == io::ErrorKind::Interrupted => {}, Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
// Worker error // Worker error
Err(e) => { Err(e) => {
recv_tx.send(Err(e.into())).unwrap(); recv_tx.send(Err(e.into())).unwrap();
break 'work; break 'work;
}, }
} }
} }
@ -262,16 +266,14 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
} else if incoming_buf.len() >= len + 8 { } else if incoming_buf.len() >= len + 8 {
match bincode::deserialize(&incoming_buf[8..len + 8]) { match bincode::deserialize(&incoming_buf[8..len + 8]) {
Ok(msg) => recv_tx.send(Ok(msg)).unwrap(), Ok(msg) => recv_tx.send(Ok(msg)).unwrap(),
Err(err) => { Err(err) => recv_tx.send(Err(err.into())).unwrap(),
recv_tx.send(Err(err.into())).unwrap()
},
} }
incoming_buf = incoming_buf.split_off(len + 8); incoming_buf = incoming_buf.split_off(len + 8);
} else { } else {
break; break;
} }
}, }
None => break, None => break,
} }
} }
@ -295,7 +297,9 @@ impl<S: PostMsg, R: PostMsg> Drop for PostBox<S, R> {
mod tests { mod tests {
use super::*; use super::*;
fn create_postoffice<S: PostMsg, R: PostMsg>(id: u16) -> Result<(PostOffice<S, R>, SocketAddr), Error> { fn create_postoffice<S: PostMsg, R: PostMsg>(
id: u16,
) -> Result<(PostOffice<S, R>, SocketAddr), Error> {
let sock = ([0; 4], 12345 + id).into(); let sock = ([0; 4], 12345 + id).into();
Ok((PostOffice::bind(sock)?, sock)) Ok((PostOffice::bind(sock)?, sock))
} }
@ -353,9 +357,9 @@ mod tests {
} }
let mut recv_msgs = Vec::new(); let mut recv_msgs = Vec::new();
loop_for(Duration::from_millis(250), || server loop_for(Duration::from_millis(250), || {
.new_messages() server.new_messages().for_each(|msg| recv_msgs.push(msg))
.for_each(|msg| recv_msgs.push(msg))); });
assert_eq!(test_msgs, recv_msgs); assert_eq!(test_msgs, recv_msgs);
} }
@ -363,7 +367,9 @@ mod tests {
#[test] #[test]
fn send_recv_huge() { fn send_recv_huge() {
let (mut postoffice, sock) = create_postoffice::<(), Vec<i32>>(3).unwrap(); let (mut postoffice, sock) = create_postoffice::<(), Vec<i32>>(3).unwrap();
let test_msgs: Vec<Vec<i32>> = (0..5).map(|i| (0..100000).map(|j| i * 2 + j).collect()).collect(); let test_msgs: Vec<Vec<i32>> = (0..5)
.map(|i| (0..100000).map(|j| i * 2 + j).collect())
.collect();
let mut client = PostBox::<Vec<i32>, ()>::to(sock).unwrap(); let mut client = PostBox::<Vec<i32>, ()>::to(sock).unwrap();
loop_for(Duration::from_millis(250), || ()); loop_for(Duration::from_millis(250), || ());
@ -374,9 +380,9 @@ mod tests {
} }
let mut recv_msgs = Vec::new(); let mut recv_msgs = Vec::new();
loop_for(Duration::from_millis(3000), || server loop_for(Duration::from_millis(3000), || {
.new_messages() server.new_messages().for_each(|msg| recv_msgs.push(msg))
.for_each(|msg| recv_msgs.push(msg))); });
assert_eq!(test_msgs.len(), recv_msgs.len()); assert_eq!(test_msgs.len(), recv_msgs.len());
assert!(test_msgs == recv_msgs); assert!(test_msgs == recv_msgs);

View File

@ -1,8 +1,5 @@
use crate::vol::{ReadVol, Vox};
use vek::*; use vek::*;
use crate::vol::{
Vox,
ReadVol,
};
pub trait RayUntil<V: Vox> = FnMut(&V) -> bool; pub trait RayUntil<V: Vox> = FnMut(&V) -> bool;
@ -26,10 +23,7 @@ impl<'a, V: ReadVol, F: RayUntil<V::Vox>> Ray<'a, V, F> {
} }
pub fn until(self, f: F) -> Ray<'a, V, F> { pub fn until(self, f: F) -> Ray<'a, V, F> {
Ray { Ray { until: f, ..self }
until: f,
..self
}
} }
pub fn max_iter(mut self, max_iter: usize) -> Self { pub fn max_iter(mut self, max_iter: usize) -> Self {
@ -52,19 +46,14 @@ impl<'a, V: ReadVol, F: RayUntil<V::Vox>> Ray<'a, V, F> {
pos = self.from + dir * dist; pos = self.from + dir * dist;
ipos = pos.map(|e| e as i32); ipos = pos.map(|e| e as i32);
match self.vol match self.vol.get(ipos).map(|vox| (vox, (self.until)(vox))) {
.get(ipos)
.map(|vox| (vox, (self.until)(vox)))
{
Ok((vox, true)) => return (dist, Ok(Some(vox))), Ok((vox, true)) => return (dist, Ok(Some(vox))),
Ok((_, false)) => {}, Ok((_, false)) => {}
Err(err) => return (dist, Err(err)), Err(err) => return (dist, Err(err)),
} }
let deltas = ( let deltas =
dir.map(|e| if e < 0.0 { 0.0 } else { 1.0 }) - (dir.map(|e| if e < 0.0 { 0.0 } else { 1.0 }) - pos.map(|e| e.fract())) / dir;
pos.map(|e| e.fract())
) / dir;
dist += deltas.reduce(f32::min).max(PLANCK); dist += deltas.reduce(f32::min).max(PLANCK);
} }

View File

@ -1,34 +1,21 @@
// Reexports // Reexports
pub use sphynx::Uid; pub use sphynx::Uid;
use std::{ use crate::{
time::Duration, comp,
collections::HashSet, msg::EcsPacket,
sys,
terrain::{TerrainChunk, TerrainMap},
}; };
use shred::{Fetch, FetchMut}; use shred::{Fetch, FetchMut};
use specs::{ use specs::{
Builder,
Component,
DispatcherBuilder,
EntityBuilder as EcsEntityBuilder,
Entity as EcsEntity,
storage::{
Storage as EcsStorage,
MaskedStorage as EcsMaskedStorage,
},
saveload::{MarkedBuilder, MarkerAllocator}, saveload::{MarkedBuilder, MarkerAllocator},
storage::{MaskedStorage as EcsMaskedStorage, Storage as EcsStorage},
Builder, Component, DispatcherBuilder, Entity as EcsEntity, EntityBuilder as EcsEntityBuilder,
}; };
use sphynx; use sphynx;
use std::{collections::HashSet, time::Duration};
use vek::*; use vek::*;
use crate::{
comp,
sys,
terrain::{
TerrainMap,
TerrainChunk,
},
msg::EcsPacket,
};
/// How much faster should an in-game day be compared to a real day? /// How much faster should an in-game day be compared to a real day?
// TODO: Don't hard-code this // TODO: Don't hard-code this
@ -85,7 +72,11 @@ impl State {
/// Create a new `State` from an ECS state package /// Create a new `State` from an ECS state package
pub fn from_state_package(state_package: sphynx::StatePackage<EcsPacket>) -> Self { pub fn from_state_package(state_package: sphynx::StatePackage<EcsPacket>) -> Self {
Self { Self {
ecs: sphynx::World::from_state_package(specs::World::new(), Self::setup_sphynx_world, state_package), ecs: sphynx::World::from_state_package(
specs::World::new(),
Self::setup_sphynx_world,
state_package,
),
changes: Changes::default(), changes: Changes::default(),
} }
} }
@ -113,7 +104,8 @@ impl State {
/// Register a component with the state's ECS /// Register a component with the state's ECS
pub fn with_component<T: Component>(mut self) -> Self pub fn with_component<T: Component>(mut self) -> Self
where <T as Component>::Storage: Default where
<T as Component>::Storage: Default,
{ {
self.ecs.register::<T>(); self.ecs.register::<T>();
self self
@ -166,13 +158,13 @@ impl State {
/// Get a reference to this state's terrain. /// Get a reference to this state's terrain.
pub fn terrain(&self) -> Fetch<TerrainMap> { pub fn terrain(&self) -> Fetch<TerrainMap> {
self.ecs self.ecs.read_resource::<TerrainMap>()
.read_resource::<TerrainMap>()
} }
/// Insert the provided chunk into this state's terrain. /// Insert the provided chunk into this state's terrain.
pub fn insert_chunk(&mut self, key: Vec3<i32>, chunk: TerrainChunk) { pub fn insert_chunk(&mut self, key: Vec3<i32>, chunk: TerrainChunk) {
if self.ecs if self
.ecs
.write_resource::<TerrainMap>() .write_resource::<TerrainMap>()
.insert(key, chunk) .insert(key, chunk)
.is_some() .is_some()
@ -185,7 +177,8 @@ impl State {
/// Remove the chunk with the given key from this state's terrain, if it exists /// Remove the chunk with the given key from this state's terrain, if it exists
pub fn remove_chunk(&mut self, key: Vec3<i32>) { pub fn remove_chunk(&mut self, key: Vec3<i32>) {
if self.ecs if self
.ecs
.write_resource::<TerrainMap>() .write_resource::<TerrainMap>()
.remove(key) .remove(key)
.is_some() .is_some()

View File

@ -3,7 +3,7 @@ use specs::{Join, Read, ReadStorage, System, WriteStorage};
use vek::*; use vek::*;
// Crate // Crate
use crate::comp::{Agent, Control, phys::Pos}; use crate::comp::{phys::Pos, Agent, Control};
// Basic ECS AI agent system // Basic ECS AI agent system
pub struct Sys; pub struct Sys;
@ -22,12 +22,14 @@ impl<'a> System<'a> for Sys {
*bearing += Vec2::new( *bearing += Vec2::new(
rand::random::<f32>().fract() - 0.5, rand::random::<f32>().fract() - 0.5,
rand::random::<f32>().fract() - 0.5, rand::random::<f32>().fract() - 0.5,
) * 0.1 - *bearing * 0.01 - pos.0 * 0.0002; ) * 0.1
- *bearing * 0.01
- pos.0 * 0.0002;
if bearing.magnitude_squared() != 0.0 { if bearing.magnitude_squared() != 0.0 {
control.move_dir = bearing.normalized(); control.move_dir = bearing.normalized();
} }
}, }
} }
} }
} }

View File

@ -1,9 +1,12 @@
// Library // Library
use specs::{Join, Read, ReadStorage, System, WriteStorage, Entities}; use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
use vek::*; use vek::*;
// Crate // Crate
use crate::comp::{Control, Animation, AnimationHistory, phys::{Pos, Vel, Dir}}; use crate::comp::{
phys::{Dir, Pos, Vel},
Animation, AnimationHistory, Control,
};
// Basic ECS AI agent system // Basic ECS AI agent system
pub struct Sys; pub struct Sys;
@ -18,13 +21,14 @@ impl<'a> System<'a> for Sys {
); );
fn run(&mut self, (entities, mut vels, mut dirs, mut anims, controls): Self::SystemData) { fn run(&mut self, (entities, mut vels, mut dirs, mut anims, controls): Self::SystemData) {
for (entity, mut vel, mut dir, control) in (&entities, &mut vels, &mut dirs, &controls).join() { for (entity, mut vel, mut dir, control) in
(&entities, &mut vels, &mut dirs, &controls).join()
{
// TODO: Don't hard-code this // TODO: Don't hard-code this
// Apply physics to the player: acceleration and non-linear decceleration // Apply physics to the player: acceleration and non-linear decceleration
vel.0 += control.move_dir * 2.0 - vel.0.map(|e| e * e.abs() + e) * 0.03; vel.0 += control.move_dir * 2.0 - vel.0.map(|e| e * e.abs() + e) * 0.03;
let animation = let animation = if control.move_dir.magnitude() > 0.01 {
if control.move_dir.magnitude() > 0.01 {
dir.0 = vel.0.normalized() * Vec3::new(1.0, 1.0, 0.0); dir.0 = vel.0.normalized() * Vec3::new(1.0, 1.0, 0.0);
Animation::Run Animation::Run
} else { } else {
@ -33,10 +37,13 @@ impl<'a> System<'a> for Sys {
let last_animation = anims.get_mut(entity).map(|h| h.current); let last_animation = anims.get_mut(entity).map(|h| h.current);
anims.insert(entity, AnimationHistory { anims.insert(
entity,
AnimationHistory {
last: last_animation, last: last_animation,
current: animation, current: animation,
}); },
);
} }
} }
} }

View File

@ -1,11 +1,11 @@
use vek::*;
use specs::{Join, Read, ReadStorage, System, WriteStorage, ReadExpect};
use crate::{ use crate::{
comp::phys::{Pos, Vel}, comp::phys::{Pos, Vel},
state::DeltaTime, state::DeltaTime,
terrain::TerrainMap, terrain::TerrainMap,
vol::{Vox, ReadVol}, vol::{ReadVol, Vox},
}; };
use specs::{Join, Read, ReadExpect, ReadStorage, System, WriteStorage};
use vek::*;
// Basic ECS physics system // Basic ECS physics system
pub struct Sys; pub struct Sys;
@ -33,8 +33,8 @@ impl<'a> System<'a> for Sys {
while terrain while terrain
.get(pos.0.map(|e| e.floor() as i32)) .get(pos.0.map(|e| e.floor() as i32))
.map(|vox| !vox.is_empty()) .map(|vox| !vox.is_empty())
.unwrap_or(false) && .unwrap_or(false)
i < 80 && i < 80
{ {
pos.0.z += 0.005; pos.0.z += 0.005;
vel.0.z = 0.0; vel.0.z = 0.0;

View File

@ -1,4 +1,4 @@
use serde_derive::{Serialize, Deserialize}; use serde_derive::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum BiomeKind { pub enum BiomeKind {

View File

@ -1,5 +1,5 @@
use serde_derive::{Deserialize, Serialize};
use vek::*; use vek::*;
use serde_derive::{Serialize, Deserialize};
// Crate // Crate
use crate::vol::Vox; use crate::vol::Vox;

View File

@ -1,21 +1,15 @@
pub mod block;
pub mod biome; pub mod biome;
pub mod block;
// Reexports // Reexports
pub use self::{ pub use self::{biome::BiomeKind, block::Block};
block::Block,
biome::BiomeKind,
};
use vek::*;
use serde_derive::{Serialize, Deserialize};
use crate::{ use crate::{
vol::VolSize, vol::VolSize,
volumes::{ volumes::{chunk::Chunk, vol_map::VolMap},
vol_map::VolMap,
chunk::Chunk,
},
}; };
use serde_derive::{Deserialize, Serialize};
use vek::*;
// TerrainChunkSize // TerrainChunkSize
@ -23,7 +17,11 @@ use crate::{
pub struct TerrainChunkSize; pub struct TerrainChunkSize;
impl VolSize for TerrainChunkSize { impl VolSize for TerrainChunkSize {
const SIZE: Vec3<u32> = Vec3 { x: 32, y: 32, z: 32 }; const SIZE: Vec3<u32> = Vec3 {
x: 32,
y: 32,
z: 32,
};
} }
// TerrainChunkMeta // TerrainChunkMeta

View File

@ -1,5 +1,5 @@
use vek::*;
use crate::ray::{Ray, RayUntil}; use crate::ray::{Ray, RayUntil};
use vek::*;
/// A voxel /// A voxel
pub trait Vox { pub trait Vox {
@ -66,14 +66,18 @@ pub trait ReadVol: BaseVol {
fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Err>; fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Err>;
fn ray(&self, from: Vec3<f32>, to: Vec3<f32>) -> Ray<Self, fn(&Self::Vox) -> bool> fn ray(&self, from: Vec3<f32>, to: Vec3<f32>) -> Ray<Self, fn(&Self::Vox) -> bool>
where Self: Sized where
Self: Sized,
{ {
Ray::new(self, from, to, |vox| !vox.is_empty()) Ray::new(self, from, to, |vox| !vox.is_empty())
} }
} }
/// A volume that provides the ability to sample (i.e: clone a section of) its voxel data. /// A volume that provides the ability to sample (i.e: clone a section of) its voxel data.
pub trait SampleVol: BaseVol where Self::Vox: Clone { pub trait SampleVol: BaseVol
where
Self::Vox: Clone,
{
type Sample: BaseVol + ReadVol; type Sample: BaseVol + ReadVol;
/// Take a sample of the volume by cloning voxels within the provided range. /// Take a sample of the volume by cloning voxels within the provided range.
/// ///

View File

@ -2,18 +2,11 @@
use std::marker::PhantomData; use std::marker::PhantomData;
// Library // Library
use serde_derive::{Deserialize, Serialize};
use vek::*; use vek::*;
use serde_derive::{Serialize, Deserialize};
// Local // Local
use crate::vol::{ use crate::vol::{BaseVol, ReadVol, SizedVol, VolSize, Vox, WriteVol};
Vox,
BaseVol,
SizedVol,
ReadVol,
WriteVol,
VolSize,
};
#[derive(Debug)] #[derive(Debug)]
pub enum ChunkErr { pub enum ChunkErr {
@ -36,15 +29,13 @@ impl<V: Vox, S: VolSize, M> Chunk<V, S, M> {
// array. // array.
#[inline(always)] #[inline(always)]
fn idx_for(pos: Vec3<i32>) -> Option<usize> { fn idx_for(pos: Vec3<i32>) -> Option<usize> {
if if pos.map(|e| e >= 0).reduce_and()
pos.map(|e| e >= 0).reduce_and() && && pos.map2(S::SIZE, |e, lim| e < lim as i32).reduce_and()
pos.map2(S::SIZE, |e, lim| e < lim as i32).reduce_and()
{ {
Some(( Some(
pos.x * S::SIZE.y as i32 * S::SIZE.z as i32 + (pos.x * S::SIZE.y as i32 * S::SIZE.z as i32 + pos.y * S::SIZE.z as i32 + pos.z)
pos.y * S::SIZE.z as i32 + as usize,
pos.z )
) as usize)
} else { } else {
None None
} }
@ -58,7 +49,9 @@ impl<V: Vox, S: VolSize, M> BaseVol for Chunk<V, S, M> {
impl<V: Vox, S: VolSize, M> SizedVol for Chunk<V, S, M> { impl<V: Vox, S: VolSize, M> SizedVol for Chunk<V, S, M> {
#[inline(always)] #[inline(always)]
fn get_size(&self) -> Vec3<u32> { S::SIZE } fn get_size(&self) -> Vec3<u32> {
S::SIZE
}
} }
impl<V: Vox, S: VolSize, M> ReadVol for Chunk<V, S, M> { impl<V: Vox, S: VolSize, M> ReadVol for Chunk<V, S, M> {

View File

@ -2,13 +2,7 @@
use vek::*; use vek::*;
// Local // Local
use crate::vol::{ use crate::vol::{BaseVol, ReadVol, SizedVol, Vox, WriteVol};
Vox,
BaseVol,
SizedVol,
ReadVol,
WriteVol,
};
#[derive(Debug)] #[derive(Debug)]
pub enum DynaErr { pub enum DynaErr {
@ -30,15 +24,8 @@ impl<V: Vox, M> Dyna<V, M> {
// array. // array.
#[inline(always)] #[inline(always)]
fn idx_for(sz: Vec3<u32>, pos: Vec3<i32>) -> Option<usize> { fn idx_for(sz: Vec3<u32>, pos: Vec3<i32>) -> Option<usize> {
if if pos.map(|e| e >= 0).reduce_and() && pos.map2(sz, |e, lim| e < lim as i32).reduce_and() {
pos.map(|e| e >= 0).reduce_and() && Some((pos.x * sz.y as i32 * sz.z as i32 + pos.y * sz.z as i32 + pos.z) as usize)
pos.map2(sz, |e, lim| e < lim as i32).reduce_and()
{
Some((
pos.x * sz.y as i32 * sz.z as i32 +
pos.y * sz.z as i32 +
pos.z
) as usize)
} else { } else {
None None
} }
@ -52,7 +39,9 @@ impl<V: Vox, M> BaseVol for Dyna<V, M> {
impl<V: Vox, M> SizedVol for Dyna<V, M> { impl<V: Vox, M> SizedVol for Dyna<V, M> {
#[inline(always)] #[inline(always)]
fn get_size(&self) -> Vec3<u32> { self.sz } fn get_size(&self) -> Vec3<u32> {
self.sz
}
} }
impl<V: Vox, M> ReadVol for Dyna<V, M> { impl<V: Vox, M> ReadVol for Dyna<V, M> {

View File

@ -1,3 +1,3 @@
pub mod dyna;
pub mod chunk; pub mod chunk;
pub mod dyna;
pub mod vol_map; pub mod vol_map;

View File

@ -6,15 +6,7 @@ use vek::*;
// Crate // Crate
use crate::{ use crate::{
vol::{ vol::{BaseVol, ReadVol, SampleVol, SizedVol, VolSize, Vox, WriteVol},
Vox,
BaseVol,
SizedVol,
ReadVol,
SampleVol,
WriteVol,
VolSize,
},
volumes::{ volumes::{
chunk::{Chunk, ChunkErr}, chunk::{Chunk, ChunkErr},
dyna::{Dyna, DynaErr}, dyna::{Dyna, DynaErr},
@ -56,7 +48,8 @@ impl<V: Vox, S: VolSize, M> ReadVol for VolMap<V, S, M> {
#[inline(always)] #[inline(always)]
fn get(&self, pos: Vec3<i32>) -> Result<&V, VolMapErr> { fn get(&self, pos: Vec3<i32>) -> Result<&V, VolMapErr> {
let ck = Self::chunk_key(pos); let ck = Self::chunk_key(pos);
self.chunks.get(&ck) self.chunks
.get(&ck)
.ok_or(VolMapErr::NoSuchChunk) .ok_or(VolMapErr::NoSuchChunk)
.and_then(|chunk| { .and_then(|chunk| {
let co = Self::chunk_offs(pos); let co = Self::chunk_offs(pos);
@ -87,14 +80,16 @@ impl<V: Vox + Clone, S: VolSize, M> SampleVol for VolMap<V, S, M> {
} }
*/ */
let mut sample = Dyna::filled( let mut sample = Dyna::filled(range.size().map(|e| e as u32).into(), V::empty(), ());
range.size().map(|e| e as u32).into(),
V::empty(),
(),
);
for pos in sample.iter_positions() { for pos in sample.iter_positions() {
sample.set(pos, self.get(range.min + pos).map(|v| v.clone()).unwrap_or(V::empty())) sample
.set(
pos,
self.get(range.min + pos)
.map(|v| v.clone())
.unwrap_or(V::empty()),
)
.map_err(|err| VolMapErr::DynaErr(err))?; .map_err(|err| VolMapErr::DynaErr(err))?;
} }
@ -106,7 +101,8 @@ impl<V: Vox, S: VolSize, M> WriteVol for VolMap<V, S, M> {
#[inline(always)] #[inline(always)]
fn set(&mut self, pos: Vec3<i32>, vox: V) -> Result<(), VolMapErr> { fn set(&mut self, pos: Vec3<i32>, vox: V) -> Result<(), VolMapErr> {
let ck = Self::chunk_key(pos); let ck = Self::chunk_key(pos);
self.chunks.get_mut(&ck) self.chunks
.get_mut(&ck)
.ok_or(VolMapErr::NoSuchChunk) .ok_or(VolMapErr::NoSuchChunk)
.and_then(|chunk| { .and_then(|chunk| {
let co = Self::chunk_offs(pos); let co = Self::chunk_offs(pos);
@ -122,7 +118,9 @@ impl<V: Vox, S: VolSize, M> VolMap<V, S, M> {
} }
} }
pub fn chunk_size() -> Vec3<u32> { S::SIZE } pub fn chunk_size() -> Vec3<u32> {
S::SIZE
}
pub fn insert(&mut self, key: Vec3<i32>, chunk: Chunk<V, S, M>) -> Option<Chunk<V, S, M>> { pub fn insert(&mut self, key: Vec3<i32>, chunk: Chunk<V, S, M>) -> Option<Chunk<V, S, M>> {
self.chunks.insert(key, chunk) self.chunks.insert(key, chunk)

View File

@ -1,7 +1,7 @@
use std::time::Duration;
use log::info;
use server::{Input, Event, Server};
use common::clock::Clock; use common::clock::Clock;
use log::info;
use server::{Event, Input, Server};
use std::time::Duration;
const TPS: u64 = 30; const TPS: u64 = 30;
@ -15,11 +15,11 @@ fn main() {
let mut clock = Clock::new(); let mut clock = Clock::new();
// Create server // Create server
let mut server = Server::new() let mut server = Server::new().expect("Failed to create server instance");
.expect("Failed to create server instance");
loop { loop {
let events = server.tick(Input::default(), clock.get_last_delta()) let events = server
.tick(Input::default(), clock.get_last_delta())
.expect("Failed to tick server"); .expect("Failed to tick server");
for event in events { for event in events {

View File

@ -88,9 +88,14 @@ fn handle_jump(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
.read_component_cloned::<comp::phys::Pos>(entity) .read_component_cloned::<comp::phys::Pos>(entity)
{ {
Some(current_pos) => { Some(current_pos) => {
server.state.write_component(entity, comp::phys::Pos(current_pos.0 + Vec3::new(x, y, z))); server.state.write_component(
server.state.write_component(entity, comp::phys::ForceUpdate); entity,
}, comp::phys::Pos(current_pos.0 + Vec3::new(x, y, z)),
);
server
.state
.write_component(entity, comp::phys::ForceUpdate);
}
None => server.clients.notify( None => server.clients.notify(
entity, entity,
ServerMsg::Chat(String::from("Command 'jump' invalid in current state")), ServerMsg::Chat(String::from("Command 'jump' invalid in current state")),
@ -107,9 +112,13 @@ fn handle_goto(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
let (opt_x, opt_y, opt_z) = scan_fmt!(&args, action.arg_fmt, f32, f32, f32); let (opt_x, opt_y, opt_z) = scan_fmt!(&args, action.arg_fmt, f32, f32, f32);
match (opt_x, opt_y, opt_z) { match (opt_x, opt_y, opt_z) {
(Some(x), Some(y), Some(z)) => { (Some(x), Some(y), Some(z)) => {
server.state.write_component(entity, comp::phys::Pos(Vec3::new(x, y, z))); server
server.state.write_component(entity, comp::phys::ForceUpdate); .state
}, .write_component(entity, comp::phys::Pos(Vec3::new(x, y, z)));
server
.state
.write_component(entity, comp::phys::ForceUpdate);
}
_ => server _ => server
.clients .clients
.notify(entity, ServerMsg::Chat(String::from(action.help_string))), .notify(entity, ServerMsg::Chat(String::from(action.help_string))),
@ -144,8 +153,10 @@ fn handle_tp(server: &mut Server, entity: EcsEntity, args: String, action: &Chat
{ {
Some(pos) => { Some(pos) => {
server.state.write_component(entity, pos); server.state.write_component(entity, pos);
server.state.write_component(entity, comp::phys::ForceUpdate); server
}, .state
.write_component(entity, comp::phys::ForceUpdate);
}
None => server.clients.notify( None => server.clients.notify(
entity, entity,
ServerMsg::Chat(format!("Unable to teleport to player '{}'", alias)), ServerMsg::Chat(format!("Unable to teleport to player '{}'", alias)),

View File

@ -8,20 +8,10 @@ pub mod input;
// Reexports // Reexports
pub use crate::{error::Error, input::Input}; pub use crate::{error::Error, input::Input};
use std::{ use crate::{
collections::HashSet, client::{Client, Clients},
net::SocketAddr, cmd::CHAT_COMMANDS,
sync::mpsc,
time::Duration,
i32,
}; };
use specs::{
join::Join, saveload::MarkedBuilder, world::EntityBuilder as EcsEntityBuilder, Builder,
Entity as EcsEntity,
};
use threadpool::ThreadPool;
use vek::*;
use world::World;
use common::{ use common::{
comp, comp,
comp::character::Animation, comp::character::Animation,
@ -30,10 +20,14 @@ use common::{
state::{State, Uid}, state::{State, Uid},
terrain::TerrainChunk, terrain::TerrainChunk,
}; };
use crate::{ use specs::{
client::{Client, Clients}, join::Join, saveload::MarkedBuilder, world::EntityBuilder as EcsEntityBuilder, Builder,
cmd::CHAT_COMMANDS, Entity as EcsEntity,
}; };
use std::{collections::HashSet, i32, net::SocketAddr, sync::mpsc, time::Duration};
use threadpool::ThreadPool;
use vek::*;
use world::World;
const CLIENT_TIMEOUT: f64 = 20.0; // Seconds const CLIENT_TIMEOUT: f64 = 20.0; // Seconds
@ -193,15 +187,20 @@ impl Server {
&self.state.ecs().entities(), &self.state.ecs().entities(),
&self.state.ecs().read_storage::<comp::Player>(), &self.state.ecs().read_storage::<comp::Player>(),
&self.state.ecs().read_storage::<comp::phys::Pos>(), &self.state.ecs().read_storage::<comp::phys::Pos>(),
).join() { )
.join()
{
let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32)); let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32));
let dist = (chunk_pos - key).map(|e| e.abs()).reduce_max(); let dist = (chunk_pos - key).map(|e| e.abs()).reduce_max();
if dist < 4 { if dist < 4 {
self.clients.notify(entity, ServerMsg::TerrainChunkUpdate { self.clients.notify(
entity,
ServerMsg::TerrainChunkUpdate {
key, key,
chunk: Box::new(chunk.clone()), chunk: Box::new(chunk.clone()),
}); },
);
} }
} }
@ -218,7 +217,9 @@ impl Server {
for (_, pos) in ( for (_, pos) in (
&self.state.ecs().read_storage::<comp::Player>(), &self.state.ecs().read_storage::<comp::Player>(),
&self.state.ecs().read_storage::<comp::phys::Pos>(), &self.state.ecs().read_storage::<comp::phys::Pos>(),
).join() { )
.join()
{
let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32)); let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32));
let dist = (chunk_pos - key).map(|e| e.abs()).reduce_max(); let dist = (chunk_pos - key).map(|e| e.abs()).reduce_max();
min_dist = min_dist.min(dist); min_dist = min_dist.min(dist);
@ -297,44 +298,69 @@ impl Server {
ClientState::Connected => disconnect = true, // Default state ClientState::Connected => disconnect = true, // Default state
ClientState::Registered => match client.client_state { ClientState::Registered => match client.client_state {
// Use ClientMsg::Register instead // Use ClientMsg::Register instead
ClientState::Connected => client.error_state(RequestStateError::WrongMessage), ClientState::Connected => {
ClientState::Registered => client.error_state(RequestStateError::Already), client.error_state(RequestStateError::WrongMessage)
ClientState::Spectator | ClientState::Character }
=> client.allow_state(ClientState::Registered), ClientState::Registered => {
client.error_state(RequestStateError::Already)
}
ClientState::Spectator | ClientState::Character => {
client.allow_state(ClientState::Registered)
}
}, },
ClientState::Spectator => match requested_state { ClientState::Spectator => match requested_state {
// Become Registered first // Become Registered first
ClientState::Connected => client.error_state(RequestStateError::Impossible), ClientState::Connected => {
ClientState::Spectator => client.error_state(RequestStateError::Already), client.error_state(RequestStateError::Impossible)
ClientState::Registered | ClientState::Character }
=> client.allow_state(ClientState::Spectator), ClientState::Spectator => {
client.error_state(RequestStateError::Already)
}
ClientState::Registered | ClientState::Character => {
client.allow_state(ClientState::Spectator)
}
}, },
// Use ClientMsg::Character instead // Use ClientMsg::Character instead
ClientState::Character => client.error_state(RequestStateError::WrongMessage), ClientState::Character => {
client.error_state(RequestStateError::WrongMessage)
}
}, },
ClientMsg::Register { player } => match client.client_state { ClientMsg::Register { player } => match client.client_state {
ClientState::Connected => Self::initialize_player(state, entity, client, player), ClientState::Connected => {
Self::initialize_player(state, entity, client, player)
}
// Use RequestState instead (No need to send `player` again) // Use RequestState instead (No need to send `player` again)
_ => client.error_state(RequestStateError::Impossible), _ => client.error_state(RequestStateError::Impossible),
}, },
ClientMsg::Character(character) => match client.client_state { ClientMsg::Character(character) => match client.client_state {
// Become Registered first // Become Registered first
ClientState::Connected => client.error_state(RequestStateError::Impossible), ClientState::Connected => {
ClientState::Registered | ClientState::Spectator => client.error_state(RequestStateError::Impossible)
Self::create_player_character(state, entity, client, character), }
ClientState::Character => client.error_state(RequestStateError::Already), ClientState::Registered | ClientState::Spectator => {
Self::create_player_character(state, entity, client, character)
}
ClientState::Character => {
client.error_state(RequestStateError::Already)
}
}, },
ClientMsg::Chat(msg) => match client.client_state { ClientMsg::Chat(msg) => match client.client_state {
ClientState::Connected => client.error_state(RequestStateError::Impossible), ClientState::Connected => {
client.error_state(RequestStateError::Impossible)
}
ClientState::Registered ClientState::Registered
| ClientState::Spectator | ClientState::Spectator
| ClientState::Character => new_chat_msgs.push((entity, msg)), | ClientState::Character => new_chat_msgs.push((entity, msg)),
}, },
ClientMsg::PlayerAnimation(animation_history) => match client.client_state { ClientMsg::PlayerAnimation(animation_history) => {
ClientState::Character => state.write_component(entity, animation_history), match client.client_state {
ClientState::Character => {
state.write_component(entity, animation_history)
}
// Only characters can send animations // Only characters can send animations
_ => client.error_state(RequestStateError::Impossible), _ => client.error_state(RequestStateError::Impossible),
} }
}
ClientMsg::PlayerPhysics { pos, vel, dir } => match client.client_state { ClientMsg::PlayerPhysics { pos, vel, dir } => match client.client_state {
ClientState::Character => { ClientState::Character => {
state.write_component(entity, pos); state.write_component(entity, pos);
@ -350,10 +376,12 @@ impl Server {
} }
ClientState::Spectator | ClientState::Character => { ClientState::Spectator | ClientState::Character => {
match state.terrain().get_key(key) { match state.terrain().get_key(key) {
Some(chunk) => client.postbox.send_message(ServerMsg::TerrainChunkUpdate { Some(chunk) => {
client.postbox.send_message(ServerMsg::TerrainChunkUpdate {
key, key,
chunk: Box::new(chunk.clone()), chunk: Box::new(chunk.clone()),
}), })
}
None => requested_chunks.push(key), None => requested_chunks.push(key),
} }
} }
@ -458,7 +486,10 @@ impl Server {
&self.state.ecs().read_storage::<comp::phys::Pos>(), &self.state.ecs().read_storage::<comp::phys::Pos>(),
&self.state.ecs().read_storage::<comp::phys::Vel>(), &self.state.ecs().read_storage::<comp::phys::Vel>(),
&self.state.ecs().read_storage::<comp::phys::Dir>(), &self.state.ecs().read_storage::<comp::phys::Dir>(),
self.state.ecs().read_storage::<comp::phys::ForceUpdate>().maybe(), self.state
.ecs()
.read_storage::<comp::phys::ForceUpdate>()
.maybe(),
) )
.join() .join()
{ {
@ -508,7 +539,10 @@ impl Server {
} }
// Remove all force flags // Remove all force flags
self.state.ecs_mut().write_storage::<comp::phys::ForceUpdate>().clear(); self.state
.ecs_mut()
.write_storage::<comp::phys::ForceUpdate>()
.clear();
} }
pub fn generate_chunk(&mut self, key: Vec3<i32>) { pub fn generate_chunk(&mut self, key: Vec3<i32>) {

View File

@ -5,11 +5,7 @@ use std::f32::consts::PI;
use vek::*; use vek::*;
// Local // Local
use super::{ use super::{super::Animation, CharacterSkeleton, SCALE};
CharacterSkeleton,
super::Animation,
SCALE,
};
pub struct IdleAnimation; pub struct IdleAnimation;
@ -17,10 +13,7 @@ impl Animation for IdleAnimation {
type Skeleton = CharacterSkeleton; type Skeleton = CharacterSkeleton;
type Dependency = f64; type Dependency = f64;
fn update_skeleton( fn update_skeleton(skeleton: &Self::Skeleton, time: f64) -> Self::Skeleton {
skeleton: &Self::Skeleton,
time: f64,
) -> Self::Skeleton {
let mut next = (*skeleton).clone(); let mut next = (*skeleton).clone();
let wave = (time as f32 * 12.0).sin(); let wave = (time as f32 * 12.0).sin();
@ -47,11 +40,19 @@ impl Animation for IdleAnimation {
next.shorts.ori = Quaternion::rotation_y(0.0); next.shorts.ori = Quaternion::rotation_y(0.0);
next.shorts.scale = Vec3::one(); next.shorts.scale = Vec3::one();
next.l_hand.offset = Vec3::new(2.0 + waveultracos_slow * 0.3, 7.5, 12.5 + waveultra_slow * 1.1); next.l_hand.offset = Vec3::new(
2.0 + waveultracos_slow * 0.3,
7.5,
12.5 + waveultra_slow * 1.1,
);
next.l_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06); next.l_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06);
next.l_hand.scale = Vec3::one(); next.l_hand.scale = Vec3::one();
next.r_hand.offset = Vec3::new(2.0 + waveultracos_slow * 0.3 , - 7.5, 12.5 + waveultra_slow * 1.1); next.r_hand.offset = Vec3::new(
2.0 + waveultracos_slow * 0.3,
-7.5,
12.5 + waveultra_slow * 1.1,
);
next.r_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06); next.r_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06);
next.r_hand.scale = Vec3::one(); next.r_hand.scale = Vec3::one();

View File

@ -1,18 +1,15 @@
pub mod run;
pub mod idle; pub mod idle;
pub mod run;
// Reexports // Reexports
pub use self::run::RunAnimation;
pub use self::idle::IdleAnimation; pub use self::idle::IdleAnimation;
pub use self::run::RunAnimation;
// Crate // Crate
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
// Local // Local
use super::{ use super::{Bone, Skeleton};
Skeleton,
Bone,
};
const SCALE: f32 = 11.0; const SCALE: f32 = 11.0;
@ -47,7 +44,6 @@ impl CharacterSkeleton {
torso: Bone::default(), torso: Bone::default(),
l_shoulder: Bone::default(), l_shoulder: Bone::default(),
r_shoulder: Bone::default(), r_shoulder: Bone::default(),
} }
} }
} }
@ -75,7 +71,6 @@ impl Skeleton for CharacterSkeleton {
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
] ]
} }
@ -92,6 +87,5 @@ impl Skeleton for CharacterSkeleton {
self.torso.interpolate(&target.torso); self.torso.interpolate(&target.torso);
self.l_shoulder.interpolate(&target.l_shoulder); self.l_shoulder.interpolate(&target.l_shoulder);
self.r_shoulder.interpolate(&target.r_shoulder); self.r_shoulder.interpolate(&target.r_shoulder);
} }
} }

View File

@ -5,11 +5,7 @@ use std::f32::consts::PI;
use vek::*; use vek::*;
// Local // Local
use super::{ use super::{super::Animation, CharacterSkeleton, SCALE};
CharacterSkeleton,
super::Animation,
SCALE
};
pub struct RunAnimation; pub struct RunAnimation;
@ -17,10 +13,7 @@ impl Animation for RunAnimation {
type Skeleton = CharacterSkeleton; type Skeleton = CharacterSkeleton;
type Dependency = f64; type Dependency = f64;
fn update_skeleton( fn update_skeleton(skeleton: &Self::Skeleton, time: f64) -> Self::Skeleton {
skeleton: &Self::Skeleton,
time: f64,
) -> Self::Skeleton {
let mut next = (*skeleton).clone(); let mut next = (*skeleton).clone();
let wave = (time as f32 * 14.0).sin(); let wave = (time as f32 * 14.0).sin();
@ -79,8 +72,6 @@ impl Animation for RunAnimation {
next.r_shoulder.ori = Quaternion::rotation_y(0.0); next.r_shoulder.ori = Quaternion::rotation_y(0.0);
next.r_shoulder.scale = Vec3::one(); next.r_shoulder.scale = Vec3::one();
next next
} }
} }

View File

@ -23,7 +23,9 @@ impl Bone {
} }
pub fn compute_base_matrix(&self) -> Mat4<f32> { pub fn compute_base_matrix(&self) -> Mat4<f32> {
Mat4::<f32>::translation_3d(self.offset) * Mat4::scaling_3d(self.scale) * Mat4::from(self.ori) Mat4::<f32>::translation_3d(self.offset)
* Mat4::scaling_3d(self.scale)
* Mat4::from(self.ori)
} }
/// Change the current bone to be more like `target` /// Change the current bone to be more like `target`
@ -48,8 +50,5 @@ pub trait Animation {
type Dependency; type Dependency;
/// Returns a new skeleton that is generated by the animation /// Returns a new skeleton that is generated by the animation
fn update_skeleton( fn update_skeleton(skeleton: &Self::Skeleton, dependency: Self::Dependency) -> Self::Skeleton;
skeleton: &Self::Skeleton,
dependency: Self::Dependency,
) -> Self::Skeleton;
} }

View File

@ -85,7 +85,11 @@ impl Chat {
// Only show if it has the keyboard captured // Only show if it has the keyboard captured
// Chat input with rectangle as background // Chat input with rectangle as background
let keyboard_captured = ui_widgets.global_input().current.widget_capturing_keyboard.map_or(false, |id| id == self.ids.input); let keyboard_captured = ui_widgets
.global_input()
.current
.widget_capturing_keyboard
.map_or(false, |id| id == self.ids.input);
if keyboard_captured { if keyboard_captured {
let text_edit = TextEdit::new(&self.input) let text_edit = TextEdit::new(&self.input)
.w(460.0) .w(460.0)
@ -114,10 +118,12 @@ impl Chat {
// Message box // Message box
Rectangle::fill([470.0, 174.0]) Rectangle::fill([470.0, 174.0])
.rgba(0.0, 0.0, 0.0, 0.4) .rgba(0.0, 0.0, 0.0, 0.4)
.and(|r| if keyboard_captured { .and(|r| {
if keyboard_captured {
r.up_from(self.ids.input_bg, 0.0) r.up_from(self.ids.input_bg, 0.0)
} else { } else {
r.bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0) r.bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0)
}
}) })
.set(self.ids.message_box_bg, ui_widgets); .set(self.ids.message_box_bg, ui_widgets);
let (mut items, _) = List::flow_down(self.messages.len() + 1) let (mut items, _) = List::flow_down(self.messages.len() + 1)

View File

@ -176,7 +176,6 @@ pub(self) struct Imgs {
inv_slot: ImgId, inv_slot: ImgId,
// Buttons // Buttons
mmap_closed: ImgId, mmap_closed: ImgId,
mmap_closed_hover: ImgId, mmap_closed_hover: ImgId,
mmap_closed_press: ImgId, mmap_closed_press: ImgId,
@ -670,18 +669,29 @@ impl Hud {
Rectangle::fill_with([92.0 * 2.0, 82.0 * 2.0], color::TRANSPARENT) Rectangle::fill_with([92.0 * 2.0, 82.0 * 2.0], color::TRANSPARENT)
.mid_top_with_margin_on(self.ids.mmap_frame, 13.0 * 2.0 + 2.0) .mid_top_with_margin_on(self.ids.mmap_frame, 13.0 * 2.0 + 2.0)
.set(self.ids.mmap_frame_bg, ui_widgets); .set(self.ids.mmap_frame_bg, ui_widgets);
} } else {
else {
Image::new(self.imgs.mmap_frame_closed) Image::new(self.imgs.mmap_frame_closed)
.w_h(100.0 * 2.0, 11.0 * 2.0) .w_h(100.0 * 2.0, 11.0 * 2.0)
.top_right_with_margins_on(ui_widgets.window, 5.0, 5.0) .top_right_with_margins_on(ui_widgets.window, 5.0, 5.0)
.set(self.ids.mmap_frame, ui_widgets); .set(self.ids.mmap_frame, ui_widgets);
}; };
if Button::image(if self.mmap_open {self.imgs.mmap_open} else {self.imgs.mmap_closed}) if Button::image(if self.mmap_open {
self.imgs.mmap_open
} else {
self.imgs.mmap_closed
})
.w_h(100.0 * 0.2, 100.0 * 0.2) .w_h(100.0 * 0.2, 100.0 * 0.2)
.hover_image(if self.mmap_open {self.imgs.mmap_open_hover} else {self.imgs.mmap_closed_hover}) .hover_image(if self.mmap_open {
.press_image(if self.mmap_open {self.imgs.mmap_open_press} else {self.imgs.mmap_closed_press}) self.imgs.mmap_open_hover
} else {
self.imgs.mmap_closed_hover
})
.press_image(if self.mmap_open {
self.imgs.mmap_open_press
} else {
self.imgs.mmap_closed_press
})
.top_right_with_margins_on(self.ids.mmap_frame, 0.0, 0.0) .top_right_with_margins_on(self.ids.mmap_frame, 0.0, 0.0)
.set(self.ids.mmap_button, ui_widgets) .set(self.ids.mmap_button, ui_widgets)
.was_clicked() .was_clicked()
@ -1590,7 +1600,6 @@ impl Hud {
.w_h(412.0, 488.0) .w_h(412.0, 488.0)
.set(self.ids.map_frame_bl, ui_widgets); .set(self.ids.map_frame_bl, ui_widgets);
// Icon // Icon
Image::new(self.imgs.map_icon) Image::new(self.imgs.map_icon)
.w_h(224.0 / 3.0, 224.0 / 3.0) .w_h(224.0 / 3.0, 224.0 / 3.0)

View File

@ -10,22 +10,18 @@ pub mod mesh;
pub mod render; pub mod render;
pub mod scene; pub mod scene;
pub mod session; pub mod session;
pub mod ui;
pub mod window;
pub mod settings; pub mod settings;
pub mod singleplayer; pub mod singleplayer;
pub mod ui;
pub mod window;
// Reexports // Reexports
pub use crate::error::Error; pub use crate::error::Error;
use std::{mem, thread, panic, fs::File, str::FromStr}; use crate::{menu::main::MainMenuState, settings::Settings, window::Window};
use log; use log;
use simplelog::{CombinedLogger, TermLogger, WriteLogger, Config}; use simplelog::{CombinedLogger, Config, TermLogger, WriteLogger};
use crate::{ use std::{fs::File, mem, panic, str::FromStr, thread};
menu::main::MainMenuState,
window::Window,
settings::Settings,
};
/// The URL of the default public server that Voxygen will connect to /// The URL of the default public server that Voxygen will connect to
const DEFAULT_PUBLIC_SERVER: &'static str = "server.veloren.net"; const DEFAULT_PUBLIC_SERVER: &'static str = "server.veloren.net";
@ -82,7 +78,7 @@ fn main() {
let settings = Settings::default(); let settings = Settings::default();
settings.save_to_file(); settings.save_to_file();
settings settings
}, }
}; };
let window = Window::new(&settings).expect("Failed to create window"); let window = Window::new(&settings).expect("Failed to create window");
@ -93,8 +89,13 @@ fn main() {
.unwrap_or(log::LevelFilter::Warn); .unwrap_or(log::LevelFilter::Warn);
CombinedLogger::init(vec![ CombinedLogger::init(vec![
TermLogger::new(term_log_level, Config::default()).unwrap(), TermLogger::new(term_log_level, Config::default()).unwrap(),
WriteLogger::new(log::LevelFilter::Info, Config::default(), File::create(&settings.log.file).unwrap()), WriteLogger::new(
]).unwrap(); log::LevelFilter::Info,
Config::default(),
File::create(&settings.log.file).unwrap(),
),
])
.unwrap();
// Set up panic handler to relay swish panic messages to the user // Set up panic handler to relay swish panic messages to the user
let settings_clone = settings.clone(); let settings_clone = settings.clone();
@ -127,18 +128,13 @@ The information below is intended for developers and testers.
msgbox::create("Voxygen has panicked", &msg, msgbox::IconType::ERROR); msgbox::create("Voxygen has panicked", &msg, msgbox::IconType::ERROR);
})); }));
let mut global_state = GlobalState { let mut global_state = GlobalState { settings, window };
settings,
window,
};
// Set up the initial play state // Set up the initial play state
let mut states: Vec<Box<dyn PlayState>> = vec![Box::new(MainMenuState::new( let mut states: Vec<Box<dyn PlayState>> = vec![Box::new(MainMenuState::new(&mut global_state))];
&mut global_state, states
))]; .last()
states.last().map(|current_state| { .map(|current_state| log::info!("Started game with state '{}'", current_state.name()));
log::info!("Started game with state '{}'", current_state.name())
});
// What's going on here? // What's going on here?
// --------------------- // ---------------------
@ -148,7 +144,10 @@ The information below is intended for developers and testers.
// The code below manages the state transfer logic automatically so that we don't have to // The code below manages the state transfer logic automatically so that we don't have to
// re-engineer it for each menu we decide to add to the game. // re-engineer it for each menu we decide to add to the game.
let mut direction = Direction::Forwards; let mut direction = Direction::Forwards;
while let Some(state_result) = states.last_mut().map(|last| last.play(direction, &mut global_state)){ while let Some(state_result) = states
.last_mut()
.map(|last| last.play(direction, &mut global_state))
{
// Implement state transfer logic // Implement state transfer logic
match state_result { match state_result {
PlayStateResult::Shutdown => { PlayStateResult::Shutdown => {
@ -160,28 +159,32 @@ The information below is intended for developers and testers.
global_state.on_play_state_changed(); global_state.on_play_state_changed();
}); });
} }
}, }
PlayStateResult::Pop => { PlayStateResult::Pop => {
direction = Direction::Backwards; direction = Direction::Backwards;
states.pop().map(|old_state| { states.pop().map(|old_state| {
log::info!("Popped state '{}'", old_state.name()); log::info!("Popped state '{}'", old_state.name());
global_state.on_play_state_changed(); global_state.on_play_state_changed();
}); });
}, }
PlayStateResult::Push(new_state) => { PlayStateResult::Push(new_state) => {
direction = Direction::Forwards; direction = Direction::Forwards;
log::info!("Pushed state '{}'", new_state.name()); log::info!("Pushed state '{}'", new_state.name());
states.push(new_state); states.push(new_state);
global_state.on_play_state_changed(); global_state.on_play_state_changed();
}, }
PlayStateResult::Switch(mut new_state) => { PlayStateResult::Switch(mut new_state) => {
direction = Direction::Forwards; direction = Direction::Forwards;
states.last_mut().map(|old_state| { states.last_mut().map(|old_state| {
log::info!("Switching to state '{}' from state '{}'", new_state.name(), old_state.name()); log::info!(
"Switching to state '{}' from state '{}'",
new_state.name(),
old_state.name()
);
mem::swap(old_state, &mut new_state); mem::swap(old_state, &mut new_state);
global_state.on_play_state_changed(); global_state.on_play_state_changed();
}); });
}, }
} }
} }
} }

View File

@ -1,15 +1,12 @@
mod ui; mod ui;
use crate::{ use crate::{
window::{Event, Window},
session::SessionState, session::SessionState,
window::{Event, Window},
Direction, GlobalState, PlayState, PlayStateResult, Direction, GlobalState, PlayState, PlayStateResult,
}; };
use client::{self, Client}; use client::{self, Client};
use common::{ use common::{clock::Clock, msg::ClientMsg};
clock::Clock,
msg::ClientMsg,
};
use std::{cell::RefCell, rc::Rc, time::Duration}; use std::{cell::RefCell, rc::Rc, time::Duration};
use ui::CharSelectionUi; use ui::CharSelectionUi;
use vek::*; use vek::*;
@ -50,7 +47,7 @@ impl PlayState for CharSelectionState {
match event { match event {
Event::Close => { Event::Close => {
return PlayStateResult::Shutdown; return PlayStateResult::Shutdown;
}, }
// Pass events to ui // Pass events to ui
Event::Ui(event) => { Event::Ui(event) => {
self.char_selection_ui.handle_event(event); self.char_selection_ui.handle_event(event);
@ -63,23 +60,35 @@ impl PlayState for CharSelectionState {
global_state.window.renderer_mut().clear(BG_COLOR); global_state.window.renderer_mut().clear(BG_COLOR);
// Maintain the UI // Maintain the UI
for event in self.char_selection_ui.maintain(global_state.window.renderer_mut()) { for event in self
.char_selection_ui
.maintain(global_state.window.renderer_mut())
{
match event { match event {
ui::Event::Logout => { ui::Event::Logout => {
return PlayStateResult::Pop; return PlayStateResult::Pop;
}, }
ui::Event::Play => { ui::Event::Play => {
self.client.borrow_mut().postbox.send_message(ClientMsg::Character(self.char_selection_ui.character)); self.client
return PlayStateResult::Switch( Box::new(SessionState::new(&mut global_state.window, self.client.clone()))); .borrow_mut()
.postbox
.send_message(ClientMsg::Character(self.char_selection_ui.character));
return PlayStateResult::Switch(Box::new(SessionState::new(
&mut global_state.window,
self.client.clone(),
)));
} }
} }
} }
// Draw the UI to the screen // Draw the UI to the screen
self.char_selection_ui.render(global_state.window.renderer_mut()); self.char_selection_ui
.render(global_state.window.renderer_mut());
// Tick the client (currently only to keep the connection alive) // Tick the client (currently only to keep the connection alive)
self.client.borrow_mut().tick(client::Input::default(), clock.get_last_delta()) self.client
.borrow_mut()
.tick(client::Input::default(), clock.get_last_delta())
.expect("Failed to tick the client"); .expect("Failed to tick the client");
self.client.borrow_mut().cleanup(); self.client.borrow_mut().cleanup();

View File

@ -5,19 +5,8 @@ use crate::{
}; };
use common::{ use common::{
assets, assets,
comp::character::{Belt, Character, Chest, Foot, Gender, Hand, Head, Pants, Race, Weapon},
figure::Segment, figure::Segment,
comp::character::{
Character,
Race,
Gender,
Head,
Chest,
Belt,
Pants,
Hand,
Foot,
Weapon,
}
}; };
use conrod_core::{ use conrod_core::{
color, color,
@ -381,10 +370,12 @@ impl CharSelectionUi {
// Load fonts // Load fonts
let load_font = |filename, ui: &mut Ui| { let load_font = |filename, ui: &mut Ui| {
let fullpath: String = ["/voxygen/font", filename].concat(); let fullpath: String = ["/voxygen/font", filename].concat();
ui.new_font(conrod_core::text::Font::from_bytes( ui.new_font(
assets::load(fullpath.as_str()) conrod_core::text::Font::from_bytes(
.expect("Error loading file") assets::load(fullpath.as_str()).expect("Error loading file"),
).unwrap()) )
.unwrap(),
)
}; };
let font_opensans = load_font("/OpenSans-Regular.ttf", &mut ui); let font_opensans = load_font("/OpenSans-Regular.ttf", &mut ui);
let font_metamorph = load_font("/Metamorphous-Regular.ttf", &mut ui); let font_metamorph = load_font("/Metamorphous-Regular.ttf", &mut ui);

View File

@ -20,10 +20,7 @@ pub struct ClientInit {
rx: Receiver<Result<Client, Error>>, rx: Receiver<Result<Client, Error>>,
} }
impl ClientInit { impl ClientInit {
pub fn new( pub fn new(connection_args: (String, u16, bool), client_args: (comp::Player, u64)) -> Self {
connection_args: (String, u16, bool),
client_args: (comp::Player, u64),
) -> Self {
let (server_address, default_port, prefer_ipv6) = connection_args; let (server_address, default_port, prefer_ipv6) = connection_args;
let (player, view_distance) = client_args; let (player, view_distance) = client_args;

View File

@ -2,7 +2,6 @@ mod client_init;
mod start_singleplayer; mod start_singleplayer;
mod ui; mod ui;
use start_singleplayer::StartSingleplayerState;
use super::char_selection::CharSelectionState; use super::char_selection::CharSelectionState;
use crate::{ use crate::{
window::{Event, Window}, window::{Event, Window},
@ -10,6 +9,7 @@ use crate::{
}; };
use client_init::{ClientInit, Error as InitError}; use client_init::{ClientInit, Error as InitError};
use common::{clock::Clock, comp}; use common::{clock::Clock, comp};
use start_singleplayer::StartSingleplayerState;
use std::time::Duration; use std::time::Duration;
use ui::{Event as MainMenuEvent, MainMenuUi}; use ui::{Event as MainMenuEvent, MainMenuUi};
use vek::*; use vek::*;
@ -86,10 +86,7 @@ impl PlayState for MainMenuState {
} }
// Maintain the UI // Maintain the UI
for event in self for event in self.main_menu_ui.maintain(global_state) {
.main_menu_ui
.maintain(global_state)
{
match event { match event {
MainMenuEvent::LoginAttempt { MainMenuEvent::LoginAttempt {
username, username,
@ -104,15 +101,12 @@ impl PlayState for MainMenuState {
// Don't try to connect if there is already a connection in progress // Don't try to connect if there is already a connection in progress
client_init = client_init.or(Some(ClientInit::new( client_init = client_init.or(Some(ClientInit::new(
(server_address, DEFAULT_PORT, false), (server_address, DEFAULT_PORT, false),
( (comp::Player::new(username.clone()), 300),
comp::Player::new(username.clone()),
300,
),
))); )));
}, }
MainMenuEvent::StartSingleplayer => { MainMenuEvent::StartSingleplayer => {
return PlayStateResult::Push(Box::new(StartSingleplayerState::new())); return PlayStateResult::Push(Box::new(StartSingleplayerState::new()));
}, }
MainMenuEvent::Quit => return PlayStateResult::Shutdown, MainMenuEvent::Quit => return PlayStateResult::Shutdown,
} }
} }

View File

@ -1,10 +1,9 @@
use common::comp; use super::{client_init::ClientInit, DEFAULT_PORT};
use super::{DEFAULT_PORT, client_init::ClientInit};
use crate::{ use crate::{
menu::char_selection::CharSelectionState, menu::char_selection::CharSelectionState, singleplayer::Singleplayer, Direction, GlobalState,
singleplayer::Singleplayer, PlayState, PlayStateResult,
Direction, GlobalState, PlayState, PlayStateResult,
}; };
use common::comp;
pub struct StartSingleplayerState { pub struct StartSingleplayerState {
singleplayer: Singleplayer, singleplayer: Singleplayer,
@ -28,10 +27,7 @@ impl PlayState for StartSingleplayerState {
let client_init = ClientInit::new( let client_init = ClientInit::new(
(server_address.clone(), DEFAULT_PORT, false), (server_address.clone(), DEFAULT_PORT, false),
( (comp::Player::new(username.clone()), 300),
comp::Player::new(username.clone()),
300,
),
); );
// Client creation // Client creation
@ -40,7 +36,7 @@ impl PlayState for StartSingleplayerState {
Some(Ok(client)) => break client, Some(Ok(client)) => break client,
// Should always work // Should always work
Some(Err(err)) => unreachable!(), Some(Err(err)) => unreachable!(),
_ => {}, _ => {}
} }
}; };
@ -55,7 +51,7 @@ impl PlayState for StartSingleplayerState {
&mut global_state.window, &mut global_state.window,
std::rc::Rc::new(std::cell::RefCell::new(client)), std::rc::Rc::new(std::cell::RefCell::new(client)),
))) )))
}, }
Direction::Backwards => PlayStateResult::Pop, Direction::Backwards => PlayStateResult::Pop,
} }
} }

View File

@ -1,6 +1,6 @@
mod vol;
pub mod segment; pub mod segment;
pub mod terrain; pub mod terrain;
mod vol;
// Crate // Crate
use crate::render::{self, Mesh}; use crate::render::{self, Mesh};

View File

@ -1,14 +1,8 @@
// Library // Library
use gfx::{ use gfx::{self, traits::FactoryExt};
self,
traits::FactoryExt,
};
// Local // Local
use super::{ use super::{gfx_backend, RenderError};
RenderError,
gfx_backend,
};
/// A handle to a series of constants sitting on the GPU. This is used to hold information used in /// A handle to a series of constants sitting on the GPU. This is used to hold information used in
/// the rendering process that does not change throughout a single render pass. /// the rendering process that does not change throughout a single render pass.
@ -31,7 +25,8 @@ impl<T: Copy + gfx::traits::Pod> Consts<T> {
encoder: &mut gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>, encoder: &mut gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
vals: &[T], vals: &[T],
) -> Result<(), RenderError> { ) -> Result<(), RenderError> {
encoder.update_buffer(&self.buf, vals, 0) encoder
.update_buffer(&self.buf, vals, 0)
.map_err(|err| RenderError::UpdateError(err)) .map_err(|err| RenderError::UpdateError(err))
} }
} }

View File

@ -75,11 +75,7 @@ pub struct Tri<P: Pipeline> {
} }
impl<P: Pipeline> Tri<P> { impl<P: Pipeline> Tri<P> {
pub fn new( pub fn new(a: P::Vertex, b: P::Vertex, c: P::Vertex) -> Self {
a: P::Vertex,
b: P::Vertex,
c: P::Vertex,
) -> Self {
Self { a, b, c } Self { a, b, c }
} }
} }
@ -93,12 +89,7 @@ pub struct Quad<P: Pipeline> {
} }
impl<P: Pipeline> Quad<P> { impl<P: Pipeline> Quad<P> {
pub fn new( pub fn new(a: P::Vertex, b: P::Vertex, c: P::Vertex, d: P::Vertex) -> Self {
a: P::Vertex,
b: P::Vertex,
c: P::Vertex,
d: P::Vertex,
) -> Self {
Self { a, b, c, d } Self { a, b, c, d }
} }
} }

View File

@ -9,33 +9,19 @@ mod util;
// Reexports // Reexports
pub use self::{ pub use self::{
consts::Consts, consts::Consts,
mesh::{Mesh, Tri, Quad}, mesh::{Mesh, Quad, Tri},
model::Model, model::Model,
texture::Texture,
renderer::{Renderer, TgtColorFmt, TgtDepthFmt},
pipelines::{ pipelines::{
Globals, figure::{BoneData as FigureBoneData, FigurePipeline, Locals as FigureLocals},
figure::{ skybox::{create_mesh as create_skybox_mesh, Locals as SkyboxLocals, SkyboxPipeline},
FigurePipeline, terrain::{Locals as TerrainLocals, TerrainPipeline},
Locals as FigureLocals,
BoneData as FigureBoneData,
},
skybox::{
create_mesh as create_skybox_mesh,
SkyboxPipeline,
Locals as SkyboxLocals,
},
terrain::{
TerrainPipeline,
Locals as TerrainLocals,
},
ui::{ ui::{
create_quad as create_ui_quad, create_quad as create_ui_quad, create_tri as create_ui_tri, Mode as UiMode, UiPipeline,
create_tri as create_ui_tri,
Mode as UiMode,
UiPipeline,
}, },
Globals,
}, },
renderer::{Renderer, TgtColorFmt, TgtDepthFmt},
texture::Texture,
}; };
#[cfg(feature = "gl")] #[cfg(feature = "gl")]
@ -64,8 +50,5 @@ pub enum RenderError {
/// - `SkyboxPipeline` /// - `SkyboxPipeline`
/// - `FigurePipeline` /// - `FigurePipeline`
pub trait Pipeline { pub trait Pipeline {
type Vertex: type Vertex: Clone + gfx::traits::Pod + gfx::pso::buffer::Structure<gfx::format::Format>;
Clone +
gfx::traits::Pod +
gfx::pso::buffer::Structure<gfx::format::Format>;
} }

View File

@ -1,15 +1,8 @@
// Library // Library
use gfx::{ use gfx::{self, traits::FactoryExt};
self,
traits::FactoryExt,
};
// Local // Local
use super::{ use super::{gfx_backend, mesh::Mesh, Pipeline};
mesh::Mesh,
Pipeline,
gfx_backend,
};
/// Represents a mesh that has been sent to the GPU. /// Represents a mesh that has been sent to the GPU.
pub struct Model<P: Pipeline> { pub struct Model<P: Pipeline> {
@ -18,10 +11,7 @@ pub struct Model<P: Pipeline> {
} }
impl<P: Pipeline> Model<P> { impl<P: Pipeline> Model<P> {
pub fn new( pub fn new(factory: &mut gfx_backend::Factory, mesh: &Mesh<P>) -> Self {
factory: &mut gfx_backend::Factory,
mesh: &Mesh<P>,
) -> Self {
Self { Self {
vbuf: factory.create_vertex_buffer(mesh.vertices()), vbuf: factory.create_vertex_buffer(mesh.vertices()),
slice: gfx::Slice { slice: gfx::Slice {

View File

@ -1,25 +1,20 @@
// Library // Library
use gfx::{ use gfx::{
self, self,
gfx_constant_struct_meta,
// Macros // Macros
gfx_defines, gfx_defines,
gfx_vertex_struct_meta,
gfx_constant_struct_meta,
gfx_impl_struct_meta, gfx_impl_struct_meta,
gfx_pipeline, gfx_pipeline,
gfx_pipeline_inner, gfx_pipeline_inner,
gfx_vertex_struct_meta,
}; };
use vek::*; use vek::*;
// Local // Local
use super::{ use super::{
super::{util::arr_to_mat, Pipeline, TgtColorFmt, TgtDepthFmt},
Globals, Globals,
super::{
Pipeline,
TgtColorFmt,
TgtDepthFmt,
util::arr_to_mat,
},
}; };
gfx_defines! { gfx_defines! {

View File

@ -6,9 +6,9 @@ pub mod ui;
// Library // Library
use gfx::{ use gfx::{
self, self,
gfx_constant_struct_meta,
// Macros // Macros
gfx_defines, gfx_defines,
gfx_constant_struct_meta,
gfx_impl_struct_meta, gfx_impl_struct_meta,
}; };
use vek::*; use vek::*;

View File

@ -1,25 +1,19 @@
// Library // Library
use gfx::{ use gfx::{
self, self,
gfx_constant_struct_meta,
// Macros // Macros
gfx_defines, gfx_defines,
gfx_vertex_struct_meta,
gfx_constant_struct_meta,
gfx_impl_struct_meta, gfx_impl_struct_meta,
gfx_pipeline, gfx_pipeline,
gfx_pipeline_inner, gfx_pipeline_inner,
gfx_vertex_struct_meta,
}; };
// Local // Local
use super::{ use super::{
super::{Mesh, Pipeline, Quad, TgtColorFmt, TgtDepthFmt},
Globals, Globals,
super::{
Pipeline,
TgtColorFmt,
TgtDepthFmt,
Mesh,
Quad,
},
}; };
gfx_defines! { gfx_defines! {

View File

@ -1,24 +1,20 @@
// Library // Library
use gfx::{ use gfx::{
self, self,
gfx_constant_struct_meta,
// Macros // Macros
gfx_defines, gfx_defines,
gfx_vertex_struct_meta,
gfx_constant_struct_meta,
gfx_impl_struct_meta, gfx_impl_struct_meta,
gfx_pipeline, gfx_pipeline,
gfx_pipeline_inner, gfx_pipeline_inner,
gfx_vertex_struct_meta,
}; };
use vek::*; use vek::*;
// Local // Local
use super::{ use super::{
super::{Pipeline, TgtColorFmt, TgtDepthFmt},
Globals, Globals,
super::{
Pipeline,
TgtColorFmt,
TgtDepthFmt,
},
}; };
gfx_defines! { gfx_defines! {

View File

@ -1,20 +1,14 @@
use super::super::{Pipeline, Quad, TgtColorFmt, TgtDepthFmt, Tri};
use gfx::{ use gfx::{
self, self,
// Macros // Macros
gfx_defines, gfx_defines,
gfx_vertex_struct_meta,
gfx_impl_struct_meta, gfx_impl_struct_meta,
gfx_pipeline, gfx_pipeline,
gfx_pipeline_inner, gfx_pipeline_inner,
gfx_vertex_struct_meta,
}; };
use vek::*; use vek::*;
use super::super::{
Pipeline,
TgtColorFmt,
TgtDepthFmt,
Quad,
Tri,
};
gfx_defines! { gfx_defines! {
vertex Vertex { vertex Vertex {
@ -65,20 +59,20 @@ impl Mode {
} }
} }
pub fn create_quad(rect: Aabr<f32>, uv_rect: Aabr<f32>, color: Rgba<f32>, mode: Mode) -> Quad<UiPipeline> { pub fn create_quad(
rect: Aabr<f32>,
uv_rect: Aabr<f32>,
color: Rgba<f32>,
mode: Mode,
) -> Quad<UiPipeline> {
let mode_val = mode.value(); let mode_val = mode.value();
let v = |pos, uv| { let v = |pos, uv| Vertex {
Vertex {
pos, pos,
uv, uv,
color: color.into_array(), color: color.into_array(),
mode: mode_val, mode: mode_val,
}
}; };
let aabr_to_lbrt = |aabr: Aabr<f32>| ( let aabr_to_lbrt = |aabr: Aabr<f32>| (aabr.min.x, aabr.min.y, aabr.max.x, aabr.max.y);
aabr.min.x, aabr.min.y,
aabr.max.x, aabr.max.y,
);
let (l, b, r, t) = aabr_to_lbrt(rect); let (l, b, r, t) = aabr_to_lbrt(rect);
let (uv_l, uv_b, uv_r, uv_t) = aabr_to_lbrt(uv_rect); let (uv_l, uv_b, uv_r, uv_t) = aabr_to_lbrt(uv_rect);
@ -90,15 +84,18 @@ pub fn create_quad(rect: Aabr<f32>, uv_rect: Aabr<f32>, color: Rgba<f32>, mode:
) )
} }
pub fn create_tri(tri: [[f32; 2]; 3], uv_tri: [[f32; 2]; 3], color: Rgba<f32>, mode: Mode) -> Tri<UiPipeline> { pub fn create_tri(
tri: [[f32; 2]; 3],
uv_tri: [[f32; 2]; 3],
color: Rgba<f32>,
mode: Mode,
) -> Tri<UiPipeline> {
let mode_val = mode.value(); let mode_val = mode.value();
let v = |pos, uv| { let v = |pos, uv| Vertex {
Vertex {
pos, pos,
uv, uv,
color: color.into_array(), color: color.into_array(),
mode: mode_val, mode: mode_val,
}
}; };
Tri::new( Tri::new(
v([tri[0][0], tri[0][1]], [uv_tri[0][0], uv_tri[0][1]]), v([tri[0][0], tri[0][1]], [uv_tri[0][0], uv_tri[0][1]]),

View File

@ -1,25 +1,18 @@
use vek::*; use super::{
consts::Consts,
gfx_backend,
mesh::Mesh,
model::Model,
pipelines::{figure, skybox, terrain, ui, Globals},
texture::Texture,
Pipeline, RenderError,
};
use gfx::{ use gfx::{
self, self,
traits::{Device, FactoryExt}, traits::{Device, FactoryExt},
}; };
use image; use image;
use super::{ use vek::*;
consts::Consts,
mesh::Mesh,
model::Model,
texture::Texture,
Pipeline,
RenderError,
gfx_backend,
pipelines::{
Globals,
figure,
skybox,
terrain,
ui,
},
};
/// Represents the format of the window's color target. /// Represents the format of the window's color target.
pub type TgtColorFmt = gfx::format::Rgba8; pub type TgtColorFmt = gfx::format::Rgba8;
@ -149,37 +142,30 @@ impl Renderer {
pub fn update_consts<T: Copy + gfx::traits::Pod>( pub fn update_consts<T: Copy + gfx::traits::Pod>(
&mut self, &mut self,
consts: &mut Consts<T>, consts: &mut Consts<T>,
vals: &[T] vals: &[T],
) -> Result<(), RenderError> { ) -> Result<(), RenderError> {
consts.update(&mut self.encoder, vals) consts.update(&mut self.encoder, vals)
} }
/// Create a new model from the provided mesh. /// Create a new model from the provided mesh.
pub fn create_model<P: Pipeline>(&mut self, mesh: &Mesh<P>) -> Result<Model<P>, RenderError> { pub fn create_model<P: Pipeline>(&mut self, mesh: &Mesh<P>) -> Result<Model<P>, RenderError> {
Ok(Model::new( Ok(Model::new(&mut self.factory, mesh))
&mut self.factory,
mesh,
))
} }
/// Create a new texture from the provided image. /// Create a new texture from the provided image.
pub fn create_texture<P: Pipeline>(&mut self, image: &image::DynamicImage) -> Result<Texture<P>, RenderError> { pub fn create_texture<P: Pipeline>(
Texture::new( &mut self,
&mut self.factory, image: &image::DynamicImage,
image, ) -> Result<Texture<P>, RenderError> {
) Texture::new(&mut self.factory, image)
} }
/// Create a new dynamic texture (gfx::memory::Usage::Dynamic) with the specified dimensions /// Create a new dynamic texture (gfx::memory::Usage::Dynamic) with the specified dimensions
pub fn create_dynamic_texture<P: Pipeline>( pub fn create_dynamic_texture<P: Pipeline>(
&mut self, &mut self,
dims: Vec2<u16> dims: Vec2<u16>,
) -> Result<Texture<P>, RenderError> { ) -> Result<Texture<P>, RenderError> {
Texture::new_dynamic( Texture::new_dynamic(&mut self.factory, dims.x, dims.y)
&mut self.factory,
dims.x,
dims.y,
)
} }
/// Update a texture with the provided offset, size, and data /// Update a texture with the provided offset, size, and data
@ -188,14 +174,9 @@ impl Renderer {
texture: &Texture<P>, texture: &Texture<P>,
offset: [u16; 2], offset: [u16; 2],
size: [u16; 2], size: [u16; 2],
data: &[[u8; 4]] data: &[[u8; 4]],
) -> Result<(), RenderError> { ) -> Result<(), RenderError> {
texture.update( texture.update(&mut self.encoder, offset, size, data)
&mut self.encoder,
offset,
size,
data,
)
} }
/// Queue the rendering of the provided skybox model in the upcoming frame. /// Queue the rendering of the provided skybox model in the upcoming frame.
@ -273,7 +254,12 @@ impl Renderer {
&self.ui_pipeline.pso, &self.ui_pipeline.pso,
&ui::pipe::Data { &ui::pipe::Data {
vbuf: model.vbuf.clone(), vbuf: model.vbuf.clone(),
scissor: gfx::Rect { x: min.x, y: min.y, w: max.x - min.x, h: max.y - min.y }, scissor: gfx::Rect {
x: min.x,
y: min.y,
w: max.x - min.x,
h: max.y - min.y,
},
tex: (tex.srv.clone(), tex.sampler.clone()), tex: (tex.srv.clone(), tex.sampler.clone()),
tgt_color: self.tgt_color_view.clone(), tgt_color: self.tgt_color_view.clone(),
tgt_depth: self.tgt_depth_view.clone(), tgt_depth: self.tgt_depth_view.clone(),
@ -298,7 +284,8 @@ fn create_pipeline<'a, P: gfx::pso::PipelineInit>(
.map_err(|err| RenderError::PipelineError(gfx::PipelineStateError::Program(err)))?; .map_err(|err| RenderError::PipelineError(gfx::PipelineStateError::Program(err)))?;
Ok(GfxPipeline { Ok(GfxPipeline {
pso: factory.create_pipeline_from_program( pso: factory
.create_pipeline_from_program(
&program, &program,
gfx::Primitive::TriangleList, gfx::Primitive::TriangleList,
gfx::state::Rasterizer { gfx::state::Rasterizer {
@ -311,13 +298,16 @@ fn create_pipeline<'a, P: gfx::pso::PipelineInit>(
pipe, pipe,
) )
// Do some funky things to work around an oddity in gfx's error ownership rules // Do some funky things to work around an oddity in gfx's error ownership rules
.map_err(|err| RenderError::PipelineError(match err { .map_err(|err| {
gfx::PipelineStateError::Program(err) => RenderError::PipelineError(match err {
gfx::PipelineStateError::Program(err), gfx::PipelineStateError::Program(err) => gfx::PipelineStateError::Program(err),
gfx::PipelineStateError::DescriptorInit(err) => gfx::PipelineStateError::DescriptorInit(err) => {
gfx::PipelineStateError::DescriptorInit(err.into()), gfx::PipelineStateError::DescriptorInit(err.into())
gfx::PipelineStateError::DeviceCreate(err) => }
gfx::PipelineStateError::DeviceCreate(err), gfx::PipelineStateError::DeviceCreate(err) => {
}))?, gfx::PipelineStateError::DeviceCreate(err)
}
})
})?,
}) })
} }

View File

@ -2,29 +2,25 @@
use std::marker::PhantomData; use std::marker::PhantomData;
// Library // Library
use gfx::{ use gfx::{self, traits::Factory};
self, use image::{DynamicImage, GenericImageView};
traits::Factory,
};
use image::{
DynamicImage,
GenericImageView,
};
use vek::Vec2; use vek::Vec2;
// Local // Local
use super::{ use super::{gfx_backend, Pipeline, RenderError};
RenderError,
Pipeline,
gfx_backend,
};
type ShaderFormat = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb); type ShaderFormat = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb);
/// Represents an image that has been uploaded to the GPU. /// Represents an image that has been uploaded to the GPU.
pub struct Texture<P: Pipeline> { pub struct Texture<P: Pipeline> {
pub tex: gfx::handle::Texture<gfx_backend::Resources, <ShaderFormat as gfx::format::Formatted>::Surface>, pub tex: gfx::handle::Texture<
pub srv: gfx::handle::ShaderResourceView<gfx_backend::Resources, <ShaderFormat as gfx::format::Formatted>::View>, gfx_backend::Resources,
<ShaderFormat as gfx::format::Formatted>::Surface,
>,
pub srv: gfx::handle::ShaderResourceView<
gfx_backend::Resources,
<ShaderFormat as gfx::format::Formatted>::View,
>,
pub sampler: gfx::handle::Sampler<gfx_backend::Resources>, pub sampler: gfx::handle::Sampler<gfx_backend::Resources>,
_phantom: PhantomData<P>, _phantom: PhantomData<P>,
} }
@ -34,7 +30,8 @@ impl<P: Pipeline> Texture<P> {
factory: &mut gfx_backend::Factory, factory: &mut gfx_backend::Factory,
image: &DynamicImage, image: &DynamicImage,
) -> Result<Self, RenderError> { ) -> Result<Self, RenderError> {
let (tex, srv) = factory.create_texture_immutable_u8::<ShaderFormat>( let (tex, srv) = factory
.create_texture_immutable_u8::<ShaderFormat>(
gfx::texture::Kind::D2( gfx::texture::Kind::D2(
image.width() as u16, image.width() as u16,
image.height() as u16, image.height() as u16,
@ -73,8 +70,12 @@ impl<P: Pipeline> Texture<P> {
) )
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?; .map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
let srv = let srv = factory
factory.view_texture_as_shader_resource::<ShaderFormat>(&tex, (0, 0), gfx::format::Swizzle::new()) .view_texture_as_shader_resource::<ShaderFormat>(
&tex,
(0, 0),
gfx::format::Swizzle::new(),
)
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Resource(err)))?; .map_err(|err| RenderError::CombinedError(gfx::CombinedError::Resource(err)))?;
Ok(Self { Ok(Self {
@ -107,7 +108,9 @@ impl<P: Pipeline> Texture<P> {
mipmap: 0, mipmap: 0,
}; };
encoder encoder
.update_texture::<<ShaderFormat as gfx::format::Formatted>::Surface, ShaderFormat>(&self.tex, None, info, data) .update_texture::<<ShaderFormat as gfx::format::Formatted>::Surface, ShaderFormat>(
&self.tex, None, info, data,
)
.map_err(|err| RenderError::TexUpdateError(err)) .map_err(|err| RenderError::TexUpdateError(err))
} }
/// Get dimensions of the represented image /// Get dimensions of the represented image

View File

@ -38,12 +38,7 @@ impl Camera {
* Mat4::rotation_3d(PI / 2.0, -Vec4::unit_x()) * Mat4::rotation_3d(PI / 2.0, -Vec4::unit_x())
* Mat4::translation_3d(-self.focus); * Mat4::translation_3d(-self.focus);
let proj_mat = Mat4::perspective_rh_no( let proj_mat = Mat4::perspective_rh_no(self.fov, self.aspect, NEAR_PLANE, FAR_PLANE);
self.fov,
self.aspect,
NEAR_PLANE,
FAR_PLANE,
);
// TODO: Make this more efficient // TODO: Make this more efficient
let cam_pos = Vec3::from(view_mat.inverted() * Vec4::unit_w()); let cam_pos = Vec3::from(view_mat.inverted() * Vec4::unit_w());
@ -56,9 +51,7 @@ impl Camera {
// Wrap camera yaw // Wrap camera yaw
self.ori.x = (self.ori.x + delta.x) % (2.0 * PI); self.ori.x = (self.ori.x + delta.x) % (2.0 * PI);
// Clamp camera pitch to the vertical limits // Clamp camera pitch to the vertical limits
self.ori.y = (self.ori.y + delta.y) self.ori.y = (self.ori.y + delta.y).min(PI / 2.0).max(-PI / 2.0);
.min(PI / 2.0)
.max(-PI / 2.0);
// Wrap camera roll // Wrap camera roll
self.ori.z = (self.ori.z + delta.z) % (2.0 * PI); self.ori.z = (self.ori.z + delta.z) % (2.0 * PI);
} }
@ -70,15 +63,25 @@ impl Camera {
} }
/// Get the focus position of the camera. /// Get the focus position of the camera.
pub fn get_focus_pos(&self) -> Vec3<f32> { self.focus } pub fn get_focus_pos(&self) -> Vec3<f32> {
self.focus
}
/// Set the focus position of the camera. /// Set the focus position of the camera.
pub fn set_focus_pos(&mut self, focus: Vec3<f32>) { self.focus = focus; } pub fn set_focus_pos(&mut self, focus: Vec3<f32>) {
self.focus = focus;
}
/// Get the aspect ratio of the camera. /// Get the aspect ratio of the camera.
pub fn get_aspect_ratio(&self) -> f32 { self.aspect } pub fn get_aspect_ratio(&self) -> f32 {
self.aspect
}
/// Set the aspect ratio of the camera. /// Set the aspect ratio of the camera.
pub fn set_aspect_ratio(&mut self, aspect: f32) { self.aspect = aspect; } pub fn set_aspect_ratio(&mut self, aspect: f32) {
self.aspect = aspect;
}
/// Get the orientation of the camera /// Get the orientation of the camera
pub fn get_orientation(&self) -> Vec3<f32> { self.ori } pub fn get_orientation(&self) -> Vec3<f32> {
self.ori
}
} }

View File

@ -1,51 +1,27 @@
use std::{ use crate::{
collections::HashMap, anim::{
f32, character::{CharacterSkeleton, IdleAnimation, RunAnimation},
Animation, Skeleton,
},
mesh::Meshable,
render::{
Consts, FigureBoneData, FigureLocals, FigurePipeline, Globals, Mesh, Model, Renderer,
},
Error,
}; };
use specs::{Entity as EcsEntity, Component, VecStorage, Join};
use vek::*;
use client::Client; use client::Client;
use common::{ use common::{
assets,
comp::{ comp::{
self, self,
character::{ character::{Belt, Character, Chest, Foot, Hand, Head, Pants, Weapon},
Character,
Head,
Chest,
Belt,
Pants,
Hand,
Foot,
Weapon,
}
}, },
figure::Segment, figure::Segment,
msg, msg,
assets,
};
use crate::{
Error,
render::{
Consts,
Globals,
Mesh,
Model,
Renderer,
FigurePipeline,
FigureBoneData,
FigureLocals,
},
anim::{
Animation,
Skeleton,
character::{
CharacterSkeleton,
RunAnimation,
IdleAnimation,
},
},
mesh::Meshable,
}; };
use specs::{Component, Entity as EcsEntity, Join, VecStorage};
use std::{collections::HashMap, f32};
use vek::*;
pub struct FigureCache { pub struct FigureCache {
models: HashMap<Character, (Model<FigurePipeline>, u64)>, models: HashMap<Character, (Model<FigurePipeline>, u64)>,
@ -64,14 +40,17 @@ impl FigureCache {
models: &'a mut HashMap<Character, (Model<FigurePipeline>, u64)>, models: &'a mut HashMap<Character, (Model<FigurePipeline>, u64)>,
renderer: &mut Renderer, renderer: &mut Renderer,
tick: u64, tick: u64,
character: Character) character: Character,
-> &'a (Model<FigurePipeline>, u64) { ) -> &'a (Model<FigurePipeline>, u64) {
match models.get_mut(&character) { match models.get_mut(&character) {
Some((model, last_used)) => { Some((model, last_used)) => {
*last_used = tick; *last_used = tick;
} }
None => { None => {
models.insert(character, ({ models.insert(
character,
(
{
let bone_meshes = [ let bone_meshes = [
Some(Self::load_head(character.head)), Some(Self::load_head(character.head)),
Some(Self::load_chest(character.chest)), Some(Self::load_chest(character.chest)),
@ -91,18 +70,22 @@ impl FigureCache {
None, None,
]; ];
let mut mesh = Mesh::new(); let mut mesh = Mesh::new();
bone_meshes bone_meshes
.iter() .iter()
.enumerate() .enumerate()
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm))) .filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm)))
.for_each(|(i, bone_mesh)| { .for_each(|(i, bone_mesh)| {
mesh.push_mesh_map(bone_mesh, |vert| vert.with_bone_idx(i as u8)) mesh.push_mesh_map(bone_mesh, |vert| {
vert.with_bone_idx(i as u8)
})
}); });
renderer.create_model(&mesh).unwrap() renderer.create_model(&mesh).unwrap()
}, tick)); },
tick,
),
);
} }
} }
@ -111,76 +94,106 @@ impl FigureCache {
pub fn clean(&mut self, tick: u64) { pub fn clean(&mut self, tick: u64) {
// TODO: Don't hard-code this // TODO: Don't hard-code this
self.models.retain(|_, (_, last_used)| *last_used + 60 > tick); self.models
.retain(|_, (_, last_used)| *last_used + 60 > tick);
} }
fn load_mesh(filename: &'static str, position: Vec3<f32>) -> Mesh<FigurePipeline> { fn load_mesh(filename: &'static str, position: Vec3<f32>) -> Mesh<FigurePipeline> {
let fullpath: String = ["/voxygen/voxel/", filename].concat(); let fullpath: String = ["/voxygen/voxel/", filename].concat();
Segment::from(dot_vox::load_bytes( Segment::from(
dot_vox::load_bytes(
assets::load(fullpath.as_str()) assets::load(fullpath.as_str())
.expect("Error loading file") .expect("Error loading file")
.as_slice(), .as_slice(),
).unwrap()) )
.unwrap(),
)
.generate_mesh(position) .generate_mesh(position)
} }
fn load_head(head: Head) -> Mesh<FigurePipeline> { fn load_head(head: Head) -> Mesh<FigurePipeline> {
Self::load_mesh(match head { Self::load_mesh(
match head {
Head::DefaultHead => "head.vox", Head::DefaultHead => "head.vox",
}, Vec3::new(-5.5, -7.0, -6.0)) },
Vec3::new(-5.5, -7.0, -6.0),
)
} }
fn load_chest(chest: Chest) -> Mesh<FigurePipeline> { fn load_chest(chest: Chest) -> Mesh<FigurePipeline> {
Self::load_mesh(match chest { Self::load_mesh(
match chest {
Chest::DefaultChest => "chest.vox", Chest::DefaultChest => "chest.vox",
}, Vec3::new(-2.5, -6.0, 0.0)) },
Vec3::new(-2.5, -6.0, 0.0),
)
} }
fn load_belt(belt: Belt) -> Mesh<FigurePipeline> { fn load_belt(belt: Belt) -> Mesh<FigurePipeline> {
Self::load_mesh(match belt { Self::load_mesh(
match belt {
Belt::DefaultBelt => "belt.vox", Belt::DefaultBelt => "belt.vox",
}, Vec3::new(-2.5, -5.0, 0.0)) },
Vec3::new(-2.5, -5.0, 0.0),
)
} }
fn load_pants(pants: Pants) -> Mesh<FigurePipeline> { fn load_pants(pants: Pants) -> Mesh<FigurePipeline> {
Self::load_mesh(match pants { Self::load_mesh(
match pants {
Pants::DefaultPants => "pants.vox", Pants::DefaultPants => "pants.vox",
}, Vec3::new(-2.5, -5.0, 0.0)) },
Vec3::new(-2.5, -5.0, 0.0),
)
} }
fn load_left_hand(hand: Hand) -> Mesh<FigurePipeline> { fn load_left_hand(hand: Hand) -> Mesh<FigurePipeline> {
Self::load_mesh(match hand { Self::load_mesh(
match hand {
Hand::DefaultHand => "hand.vox", Hand::DefaultHand => "hand.vox",
}, Vec3::new(0.0, -2.0, -7.0)) },
Vec3::new(0.0, -2.0, -7.0),
)
} }
fn load_right_hand(hand: Hand) -> Mesh<FigurePipeline> { fn load_right_hand(hand: Hand) -> Mesh<FigurePipeline> {
Self::load_mesh(match hand { Self::load_mesh(
match hand {
Hand::DefaultHand => "hand.vox", Hand::DefaultHand => "hand.vox",
}, Vec3::new(0.0, -2.0, -7.0)) },
Vec3::new(0.0, -2.0, -7.0),
)
} }
fn load_left_foot(foot: Foot) -> Mesh<FigurePipeline> { fn load_left_foot(foot: Foot) -> Mesh<FigurePipeline> {
Self::load_mesh(match foot { Self::load_mesh(
match foot {
Foot::DefaultFoot => "foot.vox", Foot::DefaultFoot => "foot.vox",
}, Vec3::new(-3.5, -2.5, -8.0)) },
Vec3::new(-3.5, -2.5, -8.0),
)
} }
fn load_right_foot(foot: Foot) -> Mesh<FigurePipeline> { fn load_right_foot(foot: Foot) -> Mesh<FigurePipeline> {
Self::load_mesh(match foot { Self::load_mesh(
match foot {
Foot::DefaultFoot => "foot.vox", Foot::DefaultFoot => "foot.vox",
}, Vec3::new(-3.5, -2.5, -8.0)) },
Vec3::new(-3.5, -2.5, -8.0),
)
} }
fn load_weapon(weapon: Weapon) -> Mesh<FigurePipeline> { fn load_weapon(weapon: Weapon) -> Mesh<FigurePipeline> {
Self::load_mesh(match weapon { Self::load_mesh(
match weapon {
Weapon::Sword => "sword.vox", Weapon::Sword => "sword.vox",
// TODO actually match against other weapons and set the right model // TODO actually match against other weapons and set the right model
_ => "sword.vox", _ => "sword.vox",
}, Vec3::new(0.0, 0.0, -4.0)) },
Vec3::new(0.0, 0.0, -4.0),
)
} }
pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) { pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) {
let time = client.state().get_time(); let time = client.state().get_time();
let ecs = client.state_mut().ecs_mut(); let ecs = client.state_mut().ecs_mut();
@ -190,14 +203,21 @@ impl FigureCache {
&ecs.read_storage::<comp::phys::Dir>(), &ecs.read_storage::<comp::phys::Dir>(),
&ecs.read_storage::<comp::Character>(), &ecs.read_storage::<comp::Character>(),
&ecs.read_storage::<comp::AnimationHistory>(), &ecs.read_storage::<comp::AnimationHistory>(),
).join() { )
let state = self.states .join()
{
let state = self
.states
.entry(entity) .entry(entity)
.or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new())); .or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new()));
let target_skeleton = match animation_history.current { let target_skeleton = match animation_history.current {
comp::character::Animation::Idle => IdleAnimation::update_skeleton(&mut state.skeleton, time), comp::character::Animation::Idle => {
comp::character::Animation::Run => RunAnimation::update_skeleton(&mut state.skeleton, time), IdleAnimation::update_skeleton(&mut state.skeleton, time)
}
comp::character::Animation::Run => {
RunAnimation::update_skeleton(&mut state.skeleton, time)
}
}; };
state.skeleton.interpolate(&target_skeleton); state.skeleton.interpolate(&target_skeleton);
@ -205,26 +225,25 @@ impl FigureCache {
state.update(renderer, pos.0, dir.0); state.update(renderer, pos.0, dir.0);
} }
self.states.retain(|entity, _| ecs.entities().is_alive(*entity)); self.states
.retain(|entity, _| ecs.entities().is_alive(*entity));
} }
pub fn render(&mut self, renderer: &mut Renderer, client: &mut Client, globals: &Consts<Globals>) { pub fn render(
&mut self,
renderer: &mut Renderer,
client: &mut Client,
globals: &Consts<Globals>,
) {
let tick = client.get_tick(); let tick = client.get_tick();
let ecs = client.state().ecs(); let ecs = client.state().ecs();
let models = &mut self.models; let models = &mut self.models;
for (entity, &character) in ( for (entity, &character) in (&ecs.entities(), &ecs.read_storage::<comp::Character>()).join()
&ecs.entities(), {
&ecs.read_storage::<comp::Character>(),
).join() {
let model = Self::get_or_create_model(models, renderer, tick, character); let model = Self::get_or_create_model(models, renderer, tick, character);
let state = self.states.get(&entity).unwrap(); let state = self.states.get(&entity).unwrap();
renderer.render_figure( renderer.render_figure(&model.0, globals, &state.locals, &state.bone_consts);
&model.0,
globals,
&state.locals,
&state.bone_consts,
);
} }
} }
} }
@ -238,21 +257,24 @@ pub struct FigureState<S: Skeleton> {
impl<S: Skeleton> FigureState<S> { impl<S: Skeleton> FigureState<S> {
pub fn new(renderer: &mut Renderer, skeleton: S) -> Self { pub fn new(renderer: &mut Renderer, skeleton: S) -> Self {
Self { Self {
bone_consts: renderer.create_consts(&skeleton.compute_matrices()).unwrap(), bone_consts: renderer
.create_consts(&skeleton.compute_matrices())
.unwrap(),
locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(), locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(),
skeleton, skeleton,
} }
} }
fn update(&mut self, renderer: &mut Renderer, pos: Vec3<f32>, dir: Vec3<f32>) { fn update(&mut self, renderer: &mut Renderer, pos: Vec3<f32>, dir: Vec3<f32>) {
let mat = let mat = Mat4::<f32>::identity()
Mat4::<f32>::identity() * * Mat4::translation_3d(pos)
Mat4::translation_3d(pos) * * Mat4::rotation_z(-dir.x.atan2(dir.y) + f32::consts::PI / 2.0);
Mat4::rotation_z(-dir.x.atan2(dir.y) + f32::consts::PI / 2.0);
let locals = FigureLocals::new(mat); let locals = FigureLocals::new(mat);
renderer.update_consts(&mut self.locals, &[locals]).unwrap(); renderer.update_consts(&mut self.locals, &[locals]).unwrap();
renderer.update_consts(&mut self.bone_consts, &self.skeleton.compute_matrices()).unwrap(); renderer
.update_consts(&mut self.bone_consts, &self.skeleton.compute_matrices())
.unwrap();
} }
} }

View File

@ -2,35 +2,23 @@ pub mod camera;
pub mod figure; pub mod figure;
pub mod terrain; pub mod terrain;
use vek::*; use self::{camera::Camera, figure::FigureCache, terrain::Terrain};
use dot_vox;
use common::{
comp,
figure::Segment,
};
use client::Client;
use crate::{ use crate::{
anim::{
character::{CharacterSkeleton, RunAnimation},
Animation,
},
mesh::Meshable,
render::{ render::{
Consts, create_skybox_mesh, Consts, FigureLocals, Globals, Model, Renderer, SkyboxLocals,
Globals,
Model,
Renderer,
SkyboxPipeline, SkyboxPipeline,
SkyboxLocals,
FigureLocals,
create_skybox_mesh,
}, },
window::Event, window::Event,
mesh::Meshable, anim::{
Animation,
character::{CharacterSkeleton, RunAnimation},
},
};
use self::{
camera::Camera,
figure::FigureCache,
terrain::Terrain,
}; };
use client::Client;
use common::{comp, figure::Segment};
use dot_vox;
use vek::*;
// TODO: Don't hard-code this // TODO: Don't hard-code this
const CURSOR_PAN_SCALE: f32 = 0.005; const CURSOR_PAN_SCALE: f32 = 0.005;
@ -56,18 +44,12 @@ impl Scene {
let resolution = renderer.get_resolution().map(|e| e as f32); let resolution = renderer.get_resolution().map(|e| e as f32);
Self { Self {
globals: renderer globals: renderer.create_consts(&[Globals::default()]).unwrap(),
.create_consts(&[Globals::default()])
.unwrap(),
camera: Camera::new(resolution.x / resolution.y), camera: Camera::new(resolution.x / resolution.y),
skybox: Skybox { skybox: Skybox {
model: renderer model: renderer.create_model(&create_skybox_mesh()).unwrap(),
.create_model(&create_skybox_mesh()) locals: renderer.create_consts(&[SkyboxLocals::default()]).unwrap(),
.unwrap(),
locals: renderer
.create_consts(&[SkyboxLocals::default()])
.unwrap(),
}, },
terrain: Terrain::new(), terrain: Terrain::new(),
figure_cache: FigureCache::new(), figure_cache: FigureCache::new(),
@ -75,10 +57,14 @@ impl Scene {
} }
/// Get a reference to the scene's camera. /// Get a reference to the scene's camera.
pub fn camera(&self) -> &Camera { &self.camera } pub fn camera(&self) -> &Camera {
&self.camera
}
/// Get a mutable reference to the scene's camera. /// Get a mutable reference to the scene's camera.
pub fn camera_mut(&mut self) -> &mut Camera { &mut self.camera } pub fn camera_mut(&mut self) -> &mut Camera {
&mut self.camera
}
/// Handle an incoming user input event (i.e: cursor moved, key pressed, window closed, etc.). /// Handle an incoming user input event (i.e: cursor moved, key pressed, window closed, etc.).
/// ///
@ -89,17 +75,17 @@ impl Scene {
Event::Resize(dims) => { Event::Resize(dims) => {
self.camera.set_aspect_ratio(dims.x as f32 / dims.y as f32); self.camera.set_aspect_ratio(dims.x as f32 / dims.y as f32);
true true
}, }
// Panning the cursor makes the camera rotate // Panning the cursor makes the camera rotate
Event::CursorPan(delta) => { Event::CursorPan(delta) => {
self.camera.rotate_by(Vec3::from(delta) * CURSOR_PAN_SCALE); self.camera.rotate_by(Vec3::from(delta) * CURSOR_PAN_SCALE);
true true
}, }
// Zoom the camera when a zoom event occurs // Zoom the camera when a zoom event occurs
Event::Zoom(delta) => { Event::Zoom(delta) => {
self.camera.zoom_by(delta * 0.3); self.camera.zoom_by(delta * 0.3);
true true
}, }
// All other events are unhandled // All other events are unhandled
_ => false, _ => false,
} }
@ -123,7 +109,10 @@ impl Scene {
let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents(); let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents();
// Update global constants // Update global constants
renderer.update_consts(&mut self.globals, &[Globals::new( renderer
.update_consts(
&mut self.globals,
&[Globals::new(
view_mat, view_mat,
proj_mat, proj_mat,
cam_pos, cam_pos,
@ -131,7 +120,8 @@ impl Scene {
10.0, 10.0,
client.state().get_time_of_day(), client.state().get_time_of_day(),
client.state().get_time(), client.state().get_time(),
)]) )],
)
.expect("Failed to update global constants"); .expect("Failed to update global constants");
// Maintain the terrain // Maintain the terrain
@ -147,11 +137,7 @@ impl Scene {
/// Render the scene using the provided `Renderer` /// Render the scene using the provided `Renderer`
pub fn render(&mut self, renderer: &mut Renderer, client: &mut Client) { pub fn render(&mut self, renderer: &mut Renderer, client: &mut Client) {
// Render the skybox first (it appears over everything else so must be rendered first) // Render the skybox first (it appears over everything else so must be rendered first)
renderer.render_skybox( renderer.render_skybox(&self.skybox.model, &self.globals, &self.skybox.locals);
&self.skybox.model,
&self.globals,
&self.skybox.locals,
);
// Render terrain and figures // Render terrain and figures
self.terrain.render(renderer, &self.globals); self.terrain.render(renderer, &self.globals);

View File

@ -10,24 +10,12 @@ use vek::*;
// Project // Project
use client::Client; use client::Client;
use common::{ use common::{terrain::TerrainMap, vol::SampleVol, volumes::vol_map::VolMapErr};
terrain::TerrainMap,
volumes::vol_map::VolMapErr,
vol::SampleVol,
};
// Crate // Crate
use crate::{ use crate::{
render::{
Consts,
Globals,
Mesh,
Model,
Renderer,
TerrainPipeline,
TerrainLocals,
},
mesh::Meshable, mesh::Meshable,
render::{Consts, Globals, Mesh, Model, Renderer, TerrainLocals, TerrainPipeline},
}; };
struct TerrainChunk { struct TerrainChunk {
@ -92,7 +80,11 @@ impl Terrain {
let current_tick = client.get_tick(); let current_tick = client.get_tick();
// Add any recently created or changed chunks to the list of chunks to be meshed // Add any recently created or changed chunks to the list of chunks to be meshed
for pos in client.state().changes().new_chunks.iter() for pos in client
.state()
.changes()
.new_chunks
.iter()
.chain(client.state().changes().changed_chunks.iter()) .chain(client.state().changes().changed_chunks.iter())
{ {
// TODO: ANOTHER PROBLEM HERE! // TODO: ANOTHER PROBLEM HERE!
@ -139,8 +131,12 @@ impl Terrain {
// ambient occlusion and edge elision, we also need to borders of the chunk's // ambient occlusion and edge elision, we also need to borders of the chunk's
// neighbours too (hence the `- 1` and `+ 1`). // neighbours too (hence the `- 1` and `+ 1`).
let aabb = Aabb { let aabb = Aabb {
min: todo.pos.map2(TerrainMap::chunk_size(), |e, sz| e * sz as i32 - 1), min: todo
max: todo.pos.map2(TerrainMap::chunk_size(), |e, sz| (e + 1) * sz as i32 + 1), .pos
.map2(TerrainMap::chunk_size(), |e, sz| e * sz as i32 - 1),
max: todo
.pos
.map2(TerrainMap::chunk_size(), |e, sz| (e + 1) * sz as i32 + 1),
}; };
// Copy out the chunk data we need to perform the meshing. We do this by taking a // Copy out the chunk data we need to perform the meshing. We do this by taking a
@ -173,27 +169,35 @@ impl Terrain {
// It's the mesh we want, insert the newly finished model into the terrain model // It's the mesh we want, insert the newly finished model into the terrain model
// data structure (convert the mesh to a model first of course) // data structure (convert the mesh to a model first of course)
Some(todo) if response.started_tick == todo.started_tick => { Some(todo) if response.started_tick == todo.started_tick => {
self.chunks.insert(response.pos, TerrainChunk { self.chunks.insert(
model: renderer.create_model(&response.mesh).expect("Failed to upload chunk mesh to the GPU"), response.pos,
locals: renderer.create_consts(&[TerrainLocals { TerrainChunk {
model_offs: response.pos.map2(TerrainMap::chunk_size(), |e, sz| e as f32 * sz as f32).into_array(), model: renderer
}]).expect("Failed to upload chunk locals to the GPU"), .create_model(&response.mesh)
}); .expect("Failed to upload chunk mesh to the GPU"),
locals: renderer
.create_consts(&[TerrainLocals {
model_offs: response
.pos
.map2(TerrainMap::chunk_size(), |e, sz| {
e as f32 * sz as f32
})
.into_array(),
}])
.expect("Failed to upload chunk locals to the GPU"),
}, },
);
}
// Chunk must have been removed, or it was spawned on an old tick. Drop the mesh // Chunk must have been removed, or it was spawned on an old tick. Drop the mesh
// since it's either out of date or no longer needed // since it's either out of date or no longer needed
_ => {}, _ => {}
} }
} }
} }
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) { pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
for (_, chunk) in &self.chunks { for (_, chunk) in &self.chunks {
renderer.render_terrain_chunk( renderer.render_terrain_chunk(&chunk.model, globals, &chunk.locals);
&chunk.model,
globals,
&chunk.locals,
);
} }
} }
} }

View File

@ -1,22 +1,15 @@
use std::{cell::RefCell, rc::Rc, time::Duration};
use vek::*;
use common::clock::Clock;
use client::{
self,
Client,
};
use crate::{ use crate::{
Direction, hud::{Event as HudEvent, Hud},
Error,
PlayState,
PlayStateResult,
GlobalState,
key_state::KeyState, key_state::KeyState,
window::{Event, Key, Window},
render::Renderer, render::Renderer,
scene::Scene, scene::Scene,
hud::{Hud, Event as HudEvent}, window::{Event, Key, Window},
Direction, Error, GlobalState, PlayState, PlayStateResult,
}; };
use client::{self, Client};
use common::clock::Clock;
use std::{cell::RefCell, rc::Rc, time::Duration};
use vek::*;
const FPS: u64 = 60; const FPS: u64 = 60;
@ -27,7 +20,6 @@ pub struct SessionState {
hud: Hud, hud: Hud,
} }
/// Represents an active game session (i.e: one that is being played) /// Represents an active game session (i.e: one that is being played)
impl SessionState { impl SessionState {
/// Create a new `SessionState` /// Create a new `SessionState`
@ -43,7 +35,6 @@ impl SessionState {
} }
} }
// The background colour // The background colour
const BG_COLOR: Rgba<f32> = Rgba { const BG_COLOR: Rgba<f32> = Rgba {
r: 0.0, r: 0.0,
@ -64,7 +55,11 @@ impl SessionState {
let dir_vec = self.key_state.dir_vec(); let dir_vec = self.key_state.dir_vec();
let move_dir = unit_vecs.0 * dir_vec[0] + unit_vecs.1 * dir_vec[1]; let move_dir = unit_vecs.0 * dir_vec[0] + unit_vecs.1 * dir_vec[1];
for event in self.client.borrow_mut().tick(client::Input { move_dir }, dt)? { for event in self
.client
.borrow_mut()
.tick(client::Input { move_dir }, dt)?
{
match event { match event {
client::Event::Chat(msg) => { client::Event::Chat(msg) => {
self.hud.new_message(msg); self.hud.new_message(msg);
@ -123,7 +118,6 @@ impl PlayState for SessionState {
loop { loop {
// Handle window events // Handle window events
for event in global_state.window.fetch_events() { for event in global_state.window.fetch_events() {
// Pass all events to the ui first // Pass all events to the ui first
if self.hud.handle_event(event.clone(), global_state) { if self.hud.handle_event(event.clone(), global_state) {
continue; continue;
@ -131,7 +125,7 @@ impl PlayState for SessionState {
let _handled = match event { let _handled = match event {
Event::Close => { Event::Close => {
return PlayStateResult::Shutdown; return PlayStateResult::Shutdown;
}, }
// Toggle cursor grabbing // Toggle cursor grabbing
Event::KeyDown(Key::ToggleCursor) => { Event::KeyDown(Key::ToggleCursor) => {
global_state global_state
@ -161,18 +155,24 @@ impl PlayState for SessionState {
.expect("Failed to tick the scene"); .expect("Failed to tick the scene");
// Maintain the scene // Maintain the scene
self.scene.maintain(global_state.window.renderer_mut(), &mut self.client.borrow_mut()); self.scene.maintain(
global_state.window.renderer_mut(),
&mut self.client.borrow_mut(),
);
// Maintain the UI // Maintain the UI
for event in self.hud.maintain(global_state.window.renderer_mut(), clock.get_tps()) { for event in self
.hud
.maintain(global_state.window.renderer_mut(), clock.get_tps())
{
match event { match event {
HudEvent::SendMessage(msg) => { HudEvent::SendMessage(msg) => {
// TODO: Handle result // TODO: Handle result
self.client.borrow_mut().send_chat(msg); self.client.borrow_mut().send_chat(msg);
}, }
HudEvent::Logout => return PlayStateResult::Pop, HudEvent::Logout => return PlayStateResult::Pop,
HudEvent::Quit => { HudEvent::Quit => {
return PlayStateResult::Shutdown; return PlayStateResult::Shutdown;
}, }
} }
} }

View File

@ -1,14 +1,9 @@
use std::time::Duration;
use log::info;
use server::{Input, Event, Server};
use common::clock::Clock; use common::clock::Clock;
use std::{ use log::info;
thread, use server::{Event, Input, Server};
thread::JoinHandle use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
}; use std::time::Duration;
use std::sync::mpsc::{ use std::{thread, thread::JoinHandle};
channel, Receiver, Sender, TryRecvError,
};
const TPS: u64 = 30; const TPS: u64 = 30;
@ -49,11 +44,11 @@ fn run_server(rec: Receiver<Msg>) {
let mut clock = Clock::new(); let mut clock = Clock::new();
// Create server // Create server
let mut server = Server::new() let mut server = Server::new().expect("Failed to create server instance");
.expect("Failed to create server instance");
loop { loop {
let events = server.tick(Input::default(), clock.get_last_delta()) let events = server
.tick(Input::default(), clock.get_last_delta())
.expect("Failed to tick server"); .expect("Failed to tick server");
for event in events { for event in events {

View File

@ -1,46 +1,30 @@
mod widgets;
mod graphic; mod graphic;
mod util; mod util;
mod widgets;
pub use widgets::toggle_button::ToggleButton;
pub use graphic::Graphic; pub use graphic::Graphic;
pub(self) use util::{srgb_to_linear, linear_to_srgb}; pub(self) use util::{linear_to_srgb, srgb_to_linear};
pub use widgets::toggle_button::ToggleButton;
use graphic::{
GraphicCache,
Id as GraphicId,
};
use conrod_core::{
Ui as CrUi,
UiBuilder,
UiCell,
text::{
Font,
GlyphCache,
font::Id as FontId,
},
image::{Map, Id as ImgId},
widget::{Id as WidgId, id::Generator},
render::Primitive,
event::Input,
input::{touch::Touch, Widget, Motion, Button},
};
use vek::*;
use crate::{ use crate::{
Error,
render::{ render::{
RenderError, create_ui_quad, create_ui_tri, Mesh, Model, RenderError, Renderer, Texture, UiMode,
Renderer,
Model,
Mesh,
Texture,
UiPipeline, UiPipeline,
UiMode,
create_ui_quad,
create_ui_tri,
}, },
window::Window, window::Window,
Error,
}; };
use conrod_core::{
event::Input,
image::{Id as ImgId, Map},
input::{touch::Touch, Button, Motion, Widget},
render::Primitive,
text::{font::Id as FontId, Font, GlyphCache},
widget::{id::Generator, Id as WidgId},
Ui as CrUi, UiBuilder, UiCell,
};
use graphic::{GraphicCache, Id as GraphicId};
use vek::*;
#[derive(Debug)] #[derive(Debug)]
pub enum UiError { pub enum UiError {
@ -66,19 +50,23 @@ impl Event {
winit::Window::get_hidpi_factor(&self.0) as _ winit::Window::get_hidpi_factor(&self.0) as _
} }
} }
convert_event!(event, &WindowRef(window.window())).map(|input| { convert_event!(event, &WindowRef(window.window())).map(|input| Self(input))
Self(input)
})
} }
pub fn is_keyboard_or_mouse(&self) -> bool { pub fn is_keyboard_or_mouse(&self) -> bool {
match self.0 { match self.0 {
Input::Press(_) | Input::Release(_) | Input::Motion(_) | Input::Touch(_) | Input::Text(_) => true, Input::Press(_)
| Input::Release(_)
| Input::Motion(_)
| Input::Touch(_)
| Input::Text(_) => true,
_ => false, _ => false,
} }
} }
pub fn is_keyboard(&self) -> bool { pub fn is_keyboard(&self) -> bool {
match self.0 { match self.0 {
Input::Press(Button::Keyboard(_)) | Input::Release(Button::Keyboard(_)) | Input::Text(_) => true, Input::Press(Button::Keyboard(_))
| Input::Release(Button::Keyboard(_))
| Input::Text(_) => true,
_ => false, _ => false,
} }
} }
@ -113,11 +101,21 @@ impl Cache {
graphic_cache_tex: renderer.create_dynamic_texture(graphic_cache_dims)?, graphic_cache_tex: renderer.create_dynamic_texture(graphic_cache_dims)?,
}) })
} }
pub fn glyph_cache_tex(&self) -> &Texture<UiPipeline> { &self.glyph_cache_tex } pub fn glyph_cache_tex(&self) -> &Texture<UiPipeline> {
pub fn glyph_cache_mut_and_tex(&mut self) -> (&mut GlyphCache<'static>, &Texture<UiPipeline>) { (&mut self.glyph_cache, &self.glyph_cache_tex) } &self.glyph_cache_tex
pub fn graphic_cache_tex(&self) -> &Texture<UiPipeline> { &self.graphic_cache_tex } }
pub fn graphic_cache_mut_and_tex(&mut self) -> (&mut GraphicCache, &Texture<UiPipeline>) { (&mut self.graphic_cache, &self.graphic_cache_tex) } pub fn glyph_cache_mut_and_tex(&mut self) -> (&mut GlyphCache<'static>, &Texture<UiPipeline>) {
pub fn new_graphic(&mut self, graphic: Graphic) -> GraphicId { self.graphic_cache.new_graphic(graphic) } (&mut self.glyph_cache, &self.glyph_cache_tex)
}
pub fn graphic_cache_tex(&self) -> &Texture<UiPipeline> {
&self.graphic_cache_tex
}
pub fn graphic_cache_mut_and_tex(&mut self) -> (&mut GraphicCache, &Texture<UiPipeline>) {
(&mut self.graphic_cache, &self.graphic_cache_tex)
}
pub fn new_graphic(&mut self, graphic: Graphic) -> GraphicId {
self.graphic_cache.new_graphic(graphic)
}
pub fn clear_graphic_cache(&mut self, renderer: &mut Renderer, new_size: Vec2<u16>) { pub fn clear_graphic_cache(&mut self, renderer: &mut Renderer, new_size: Vec2<u16>) {
self.graphic_cache.clear_cache(new_size); self.graphic_cache.clear_cache(new_size);
self.graphic_cache_tex = renderer.create_dynamic_texture(new_size).unwrap(); self.graphic_cache_tex = renderer.create_dynamic_texture(new_size).unwrap();
@ -190,7 +188,9 @@ impl Scale {
match self.mode { match self.mode {
ScaleMode::Absolute(scale) => scale / self.dpi_factor, ScaleMode::Absolute(scale) => scale / self.dpi_factor,
ScaleMode::DpiFactor => 1.0, ScaleMode::DpiFactor => 1.0,
ScaleMode::RelativeToWindow(dims) => (self.window_dims.x / dims.x).min(self.window_dims.y / dims.y), ScaleMode::RelativeToWindow(dims) => {
(self.window_dims.x / dims.x).min(self.window_dims.y / dims.y)
}
} }
} }
// Calculate factor to transform between physical coordinates and our scaled coordinates // Calculate factor to transform between physical coordinates and our scaled coordinates
@ -277,20 +277,22 @@ impl Ui {
// Get whether a widget besides the window is capturing the mouse // Get whether a widget besides the window is capturing the mouse
pub fn no_widget_capturing_mouse(&self) -> bool { pub fn no_widget_capturing_mouse(&self) -> bool {
self.ui.global_input().current.widget_capturing_mouse.filter(|id| id != &self.ui.window ).is_none() self.ui
.global_input()
.current
.widget_capturing_mouse
.filter(|id| id != &self.ui.window)
.is_none()
} }
pub fn handle_event(&mut self, event: Event) { pub fn handle_event(&mut self, event: Event) {
match event.0 { match event.0 {
Input::Resize(w, h) => self.window_resized = Some(Vec2::new(w, h)), Input::Resize(w, h) => self.window_resized = Some(Vec2::new(w, h)),
Input::Touch(touch) => self.ui.handle_event( Input::Touch(touch) => self.ui.handle_event(Input::Touch(Touch {
Input::Touch(Touch {
xy: self.scale.scale_point(touch.xy.into()).into_array(), xy: self.scale.scale_point(touch.xy.into()).into_array(),
..touch ..touch
}) })),
), Input::Motion(motion) => self.ui.handle_event(Input::Motion(match motion {
Input::Motion(motion) => self.ui.handle_event(
Input::Motion( match motion {
Motion::MouseCursor { x, y } => { Motion::MouseCursor { x, y } => {
let (x, y) = self.scale.scale_point(Vec2::new(x, y)).into_tuple(); let (x, y) = self.scale.scale_point(Vec2::new(x, y)).into_tuple();
Motion::MouseCursor { x, y } Motion::MouseCursor { x, y }
@ -304,8 +306,7 @@ impl Ui {
Motion::Scroll { x, y } Motion::Scroll { x, y }
} }
_ => motion, _ => motion,
}) })),
),
_ => self.ui.handle_event(event.0), _ => self.ui.handle_event(event.0),
} }
} }
@ -338,7 +339,8 @@ impl Ui {
macro_rules! switch_to_plain_state { macro_rules! switch_to_plain_state {
() => { () => {
if let State::Image = current_state { if let State::Image = current_state {
self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap())); self.draw_commands
.push(DrawCommand::image(renderer.create_model(&mesh).unwrap()));
mesh.clear(); mesh.clear();
current_state = State::Plain; current_state = State::Plain;
} }
@ -348,7 +350,12 @@ impl Ui {
let p_scale_factor = self.scale.scale_factor_physical(); let p_scale_factor = self.scale.scale_factor_physical();
while let Some(prim) = primitives.next() { while let Some(prim) = primitives.next() {
let Primitive {kind, scizzor, id: _id, rect} = prim; let Primitive {
kind,
scizzor,
id: _id,
rect,
} = prim;
// Check for a change in the scizzor // Check for a change in the scizzor
let new_scizzor = { let new_scizzor = {
@ -366,17 +373,15 @@ impl Ui {
max: Vec2 { max: Vec2 {
x: ((min_x + w) * p_scale_factor) as u16, x: ((min_x + w) * p_scale_factor) as u16,
y: ((min_y + h) * p_scale_factor) as u16, y: ((min_y + h) * p_scale_factor) as u16,
} },
} }
.intersection(window_scizzor) .intersection(window_scizzor)
}; };
if new_scizzor != current_scizzor { if new_scizzor != current_scizzor {
// Finish the current command // Finish the current command
self.draw_commands.push(match current_state { self.draw_commands.push(match current_state {
State::Plain => State::Plain => DrawCommand::plain(renderer.create_model(&mesh).unwrap()),
DrawCommand::plain(renderer.create_model(&mesh).unwrap()), State::Image => DrawCommand::image(renderer.create_model(&mesh).unwrap()),
State::Image =>
DrawCommand::image(renderer.create_model(&mesh).unwrap()),
}); });
mesh.clear(); mesh.clear();
@ -398,8 +403,15 @@ impl Ui {
use conrod_core::render::PrimitiveKind; use conrod_core::render::PrimitiveKind;
match kind { match kind {
PrimitiveKind::Image { image_id, color, source_rect } => { PrimitiveKind::Image {
let graphic_id = self.image_map.get(&image_id).expect("Image does not exist in image map"); image_id,
color,
source_rect,
} => {
let graphic_id = self
.image_map
.get(&image_id)
.expect("Image does not exist in image map");
let (graphic_cache, cache_tex) = self.cache.graphic_cache_mut_and_tex(); let (graphic_cache, cache_tex) = self.cache.graphic_cache_mut_and_tex();
match graphic_cache.get_graphic(*graphic_id) { match graphic_cache.get_graphic(*graphic_id) {
@ -409,13 +421,15 @@ impl Ui {
// Switch to the `Image` state for this image if we're not in it already. // Switch to the `Image` state for this image if we're not in it already.
if let State::Plain = current_state { if let State::Plain = current_state {
self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap())); self.draw_commands
.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap()));
mesh.clear(); mesh.clear();
current_state = State::Image; current_state = State::Image;
} }
let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa().into()); let color = srgb_to_linear(
color.unwrap_or(conrod_core::color::WHITE).to_fsa().into(),
);
let resolution = Vec2::new( let resolution = Vec2::new(
(rect.w() * p_scale_factor) as u16, (rect.w() * p_scale_factor) as u16,
@ -439,17 +453,29 @@ impl Ui {
max: Vec2::new(uv_r, uv_t), max: Vec2::new(uv_r, uv_t),
} }
}; };
let (cache_w, cache_h) = cache_tex.get_dimensions().map(|e| e as f32).into_tuple(); let (cache_w, cache_h) =
cache_tex.get_dimensions().map(|e| e as f32).into_tuple();
// Cache graphic at particular resolution // Cache graphic at particular resolution
let uv_aabr = match graphic_cache.cache_res(*graphic_id, resolution, source_aabr, |aabr, data| { let uv_aabr = match graphic_cache.cache_res(
*graphic_id,
resolution,
source_aabr,
|aabr, data| {
let offset = aabr.min.into_array(); let offset = aabr.min.into_array();
let size = aabr.size().into_array(); let size = aabr.size().into_array();
renderer.update_texture(cache_tex, offset, size, &data); renderer.update_texture(cache_tex, offset, size, &data);
}) { },
) {
Some(aabr) => Aabr { Some(aabr) => Aabr {
min: Vec2::new(aabr.min.x as f32 / cache_w, aabr.max.y as f32 / cache_h), min: Vec2::new(
max: Vec2::new(aabr.max.x as f32 / cache_w, aabr.min.y as f32 / cache_h), aabr.min.x as f32 / cache_w,
aabr.max.y as f32 / cache_h,
),
max: Vec2::new(
aabr.max.x as f32 / cache_w,
aabr.min.y as f32 / cache_h,
),
}, },
None => continue, None => continue,
}; };
@ -460,12 +486,16 @@ impl Ui {
color, color,
UiMode::Image, UiMode::Image,
)); ));
} }
PrimitiveKind::Text { color, text, font_id } => { PrimitiveKind::Text {
color,
text,
font_id,
} => {
switch_to_plain_state!(); switch_to_plain_state!();
// Get screen width and height // Get screen width and height
let (screen_w, screen_h) = renderer.get_resolution().map(|e| e as f32).into_tuple(); let (screen_w, screen_h) =
renderer.get_resolution().map(|e| e as f32).into_tuple();
// Calculate dpi factor // Calculate dpi factor
let dpi_factor = screen_w / ui.win_w as f32; let dpi_factor = screen_w / ui.win_w as f32;
@ -476,19 +506,26 @@ impl Ui {
glyph_cache.queue_glyph(font_id.index(), glyph.clone()); glyph_cache.queue_glyph(font_id.index(), glyph.clone());
} }
glyph_cache.cache_queued(|rect, data| { glyph_cache
.cache_queued(|rect, data| {
let offset = [rect.min.x as u16, rect.min.y as u16]; let offset = [rect.min.x as u16, rect.min.y as u16];
let size = [rect.width() as u16, rect.height() as u16]; let size = [rect.width() as u16, rect.height() as u16];
let new_data = data.iter().map(|x| [255, 255, 255, *x]).collect::<Vec<[u8; 4]>>(); let new_data = data
.iter()
.map(|x| [255, 255, 255, *x])
.collect::<Vec<[u8; 4]>>();
renderer.update_texture(cache_tex, offset, size, &new_data); renderer.update_texture(cache_tex, offset, size, &new_data);
}).unwrap(); })
.unwrap();
let color = srgb_to_linear(color.to_fsa().into()); let color = srgb_to_linear(color.to_fsa().into());
for g in positioned_glyphs { for g in positioned_glyphs {
if let Ok(Some((uv_rect, screen_rect))) = glyph_cache.rect_for(font_id.index(), g) { if let Ok(Some((uv_rect, screen_rect))) =
glyph_cache.rect_for(font_id.index(), g)
{
let uv = Aabr { let uv = Aabr {
min: Vec2::new(uv_rect.min.x, uv_rect.max.y), min: Vec2::new(uv_rect.min.x, uv_rect.max.y),
max: Vec2::new(uv_rect.max.x, uv_rect.min.y), max: Vec2::new(uv_rect.max.x, uv_rect.min.y),
@ -503,12 +540,7 @@ impl Ui {
(screen_rect.min.y as f32 / screen_h - 0.5) * -2.0, (screen_rect.min.y as f32 / screen_h - 0.5) * -2.0,
), ),
}; };
mesh.push_quad(create_ui_quad( mesh.push_quad(create_ui_quad(rect, uv, color, UiMode::Text));
rect,
uv,
color,
UiMode::Text,
));
} }
} }
} }
@ -545,16 +577,13 @@ impl Ui {
let p2 = Vec2::new(vx(tri[1][0]), vy(tri[1][1])); let p2 = Vec2::new(vx(tri[1][0]), vy(tri[1][1]));
let p3 = Vec2::new(vx(tri[2][0]), vy(tri[2][1])); let p3 = Vec2::new(vx(tri[2][0]), vy(tri[2][1]));
// If triangle is clockwise reverse it // If triangle is clockwise reverse it
let (v1, v2): (Vec3<f32>, Vec3<f32>) = ((p2 - p1).into(), (p3 - p1).into()); let (v1, v2): (Vec3<f32>, Vec3<f32>) =
let triangle = if v1.cross(v2).z > 0.0 {[ ((p2 - p1).into(), (p3 - p1).into());
p1.into_array(), let triangle = if v1.cross(v2).z > 0.0 {
p2.into_array(), [p1.into_array(), p2.into_array(), p3.into_array()]
p3.into_array(), } else {
]} else {[ [p2.into_array(), p1.into_array(), p3.into_array()]
p2.into_array(), };
p1.into_array(),
p3.into_array(),
]};
mesh.push_tri(create_ui_tri( mesh.push_tri(create_ui_tri(
triangle, triangle,
[[0.0; 2]; 3], [[0.0; 2]; 3],
@ -562,10 +591,8 @@ impl Ui {
UiMode::Geometry, UiMode::Geometry,
)); ));
} }
} }
_ => {} _ => {} // TODO: Add this
// TODO: Add this
//PrimitiveKind::TrianglesMultiColor {..} => {println!("primitive kind multicolor with id {:?}", id);} //PrimitiveKind::TrianglesMultiColor {..} => {println!("primitive kind multicolor with id {:?}", id);}
// Other uneeded for now // Other uneeded for now
//PrimitiveKind::Other {..} => {println!("primitive kind other with id {:?}", id);} //PrimitiveKind::Other {..} => {println!("primitive kind other with id {:?}", id);}
@ -573,10 +600,8 @@ impl Ui {
} }
// Enter the final command // Enter the final command
self.draw_commands.push(match current_state { self.draw_commands.push(match current_state {
State::Plain => State::Plain => DrawCommand::plain(renderer.create_model(&mesh).unwrap()),
DrawCommand::plain(renderer.create_model(&mesh).unwrap()), State::Image => DrawCommand::image(renderer.create_model(&mesh).unwrap()),
State::Image =>
DrawCommand::image(renderer.create_model(&mesh).unwrap()),
}); });
// Handle window resizing // Handle window resizing
@ -584,7 +609,8 @@ impl Ui {
self.scale.window_resized(new_dims, renderer); self.scale.window_resized(new_dims, renderer);
let (w, h) = self.scale.scaled_window_size().into_tuple(); let (w, h) = self.scale.scaled_window_size().into_tuple();
self.ui.handle_event(Input::Resize(w, h)); self.ui.handle_event(Input::Resize(w, h));
self.cache.clear_graphic_cache(renderer, renderer.get_resolution().map(|e| e * 4)); self.cache
.clear_graphic_cache(renderer, renderer.get_resolution().map(|e| e * 4));
// TODO: probably need to resize glyph cache, see conrod's gfx backend for reference // TODO: probably need to resize glyph cache, see conrod's gfx backend for reference
} }
} }
@ -599,12 +625,8 @@ impl Ui {
} }
DrawCommand::Draw { kind, model } => { DrawCommand::Draw { kind, model } => {
let tex = match kind { let tex = match kind {
DrawKind::Image => { DrawKind::Image => self.cache.graphic_cache_tex(),
self.cache.graphic_cache_tex() DrawKind::Plain => self.cache.glyph_cache_tex(),
}
DrawKind::Plain => {
self.cache.glyph_cache_tex()
}
}; };
renderer.render_ui_element(&model, &tex, scissor); renderer.render_ui_element(&model, &tex, scissor);
} }
@ -617,6 +639,9 @@ fn default_scissor(renderer: &mut Renderer) -> Aabr<u16> {
let (screen_w, screen_h) = renderer.get_resolution().map(|e| e as u16).into_tuple(); let (screen_w, screen_h) = renderer.get_resolution().map(|e| e as u16).into_tuple();
Aabr { Aabr {
min: Vec2 { x: 0, y: 0 }, min: Vec2 { x: 0, y: 0 },
max: Vec2 { x: screen_w, y: screen_h } max: Vec2 {
x: screen_w,
y: screen_h,
},
} }
} }

View File

@ -1,13 +1,7 @@
use conrod_core::{ use conrod_core::{
widget::{self, button},
image, image,
WidgetCommon, widget::{self, button},
Widget, widget_ids, Color, Positionable, Rect, Sizeable, Widget, WidgetCommon,
Sizeable,
Color,
Rect,
Positionable,
widget_ids,
}; };
#[derive(Clone, WidgetCommon)] #[derive(Clone, WidgetCommon)]
@ -88,7 +82,9 @@ impl Widget for ToggleButton {
type Event = bool; type Event = bool;
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State { fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
State { ids: Ids::new(id_gen) } State {
ids: Ids::new(id_gen),
}
} }
fn style(&self) -> Self::Style { fn style(&self) -> Self::Style {
@ -96,8 +92,19 @@ impl Widget for ToggleButton {
} }
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event { fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
let widget::UpdateArgs{ id, state, ui, rect, .. } = args; let widget::UpdateArgs {
let ToggleButton { mut value, f_image, t_image, .. } = self; id,
state,
ui,
rect,
..
} = args;
let ToggleButton {
mut value,
f_image,
t_image,
..
} = self;
// Check if button was clicked // Check if button was clicked
// (can't use .set().was_clicked() because we are changing the image and this is after setting the widget which causes flickering as it takes a frame to change after the mouse button is lifted) // (can't use .set().was_clicked() because we are changing the image and this is after setting the widget which causes flickering as it takes a frame to change after the mouse button is lifted)
if ui.widget_input(state.ids.button).clicks().left().count() % 2 == 1 { if ui.widget_input(state.ids.button).clicks().left().count() % 2 == 1 {

View File

@ -1,6 +1,7 @@
use crate::{ use crate::{
render::{Renderer, TgtColorFmt, TgtDepthFmt}, render::{Renderer, TgtColorFmt, TgtDepthFmt},
ui, Error, settings::Settings, settings::Settings,
ui, Error,
}; };
use std::collections::HashMap; use std::collections::HashMap;
use vek::*; use vek::*;

View File

@ -1,15 +1,11 @@
// Library // Library
use vek::*;
use noise::{NoiseFn, Perlin}; use noise::{NoiseFn, Perlin};
use vek::*;
// Project // Project
use common::{ use common::{
vol::{Vox, SizedVol, WriteVol}, terrain::{Block, TerrainChunk, TerrainChunkMeta},
terrain::{ vol::{SizedVol, Vox, WriteVol},
Block,
TerrainChunk,
TerrainChunkMeta,
},
}; };
#[derive(Debug)] #[derive(Debug)]
@ -47,12 +43,14 @@ impl World {
let small_freq = 1.0 / 32.0; let small_freq = 1.0 / 32.0;
let small_ampl = 6.0; let small_ampl = 6.0;
let offs = 32.0; let offs = 32.0;
let height = let height = perlin_nz.get(Vec2::from(wposf * freq).into_array()) * ampl
perlin_nz.get(Vec2::from(wposf * freq).into_array()) * ampl
+ perlin_nz.get(Vec2::from(wposf * small_freq).into_array()) * small_ampl + perlin_nz.get(Vec2::from(wposf * small_freq).into_array()) * small_ampl
+ offs; + offs;
chunk.set(lpos, if wposf.z < height - 4.0 { chunk
.set(
lpos,
if wposf.z < height - 4.0 {
stone stone
} else if wposf.z < height - 1.0 { } else if wposf.z < height - 1.0 {
dirt dirt
@ -60,7 +58,9 @@ impl World {
grass grass
} else { } else {
air air
}).unwrap(); },
)
.unwrap();
} }
chunk chunk