mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added networked entity updates, player entity allocation
Former-commit-id: b81d6e38a74f846d64c092d1422dc402f369100c
This commit is contained in:
parent
bb93f29522
commit
a8b0039898
@ -19,8 +19,13 @@ fn main() {
|
||||
.expect("Failed to create client instance");
|
||||
|
||||
loop {
|
||||
let events = client.tick(Input::default(), clock.get_last_delta())
|
||||
.expect("Failed to tick client");
|
||||
let events = match client.tick(Input::default(), clock.get_last_delta()) {
|
||||
Ok(events) => events,
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
break;
|
||||
},
|
||||
};
|
||||
|
||||
for event in events {
|
||||
match event {
|
||||
|
@ -14,9 +14,12 @@ use std::{
|
||||
};
|
||||
use vek::*;
|
||||
use threadpool;
|
||||
use specs::Builder;
|
||||
use specs::{
|
||||
Builder,
|
||||
saveload::MarkerAllocator,
|
||||
};
|
||||
use common::{
|
||||
comp,
|
||||
comp::{self, Uid},
|
||||
state::State,
|
||||
terrain::TerrainChunk,
|
||||
net::PostBox,
|
||||
@ -36,7 +39,7 @@ pub struct Client {
|
||||
|
||||
tick: u64,
|
||||
state: State,
|
||||
player: Option<EcsEntity>,
|
||||
player: Option<Uid>,
|
||||
|
||||
// Testing
|
||||
world: World,
|
||||
@ -80,7 +83,6 @@ impl Client {
|
||||
// TODO: Get rid of this
|
||||
pub fn with_test_state(mut self) -> Self {
|
||||
self.chunk = Some(self.world.generate_chunk(Vec3::zero()));
|
||||
self.player = Some(self.state.new_test_player());
|
||||
self
|
||||
}
|
||||
|
||||
@ -99,15 +101,32 @@ impl Client {
|
||||
pub fn state_mut(&mut self) -> &mut State { &mut self.state }
|
||||
|
||||
/// Get an entity from its UID, creating it if it does not exists
|
||||
pub fn get_or_create_entity(&mut self, uid: u64) -> EcsEntity {
|
||||
self.state.ecs_world_mut().create_entity()
|
||||
.with(comp::Uid(uid))
|
||||
.build()
|
||||
pub fn get_or_create_entity(&mut self, uid: Uid) -> EcsEntity {
|
||||
// Find the ECS entity from its UID
|
||||
let ecs_entity = self.state().ecs_world()
|
||||
.read_resource::<comp::UidAllocator>()
|
||||
.retrieve_entity_internal(uid.into());
|
||||
|
||||
// Return the entity or create it
|
||||
if let Some(ecs_entity) = ecs_entity {
|
||||
ecs_entity
|
||||
} else {
|
||||
let ecs_entity = self.state.ecs_world_mut().create_entity()
|
||||
.build();
|
||||
|
||||
// Allocate it the specific UID given
|
||||
self.state
|
||||
.ecs_world_mut()
|
||||
.write_resource::<comp::UidAllocator>()
|
||||
.allocate(ecs_entity, Some(uid.into()));
|
||||
|
||||
ecs_entity
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the player entity
|
||||
#[allow(dead_code)]
|
||||
pub fn player(&self) -> Option<EcsEntity> {
|
||||
pub fn player(&self) -> Option<Uid> {
|
||||
self.player
|
||||
}
|
||||
|
||||
@ -145,12 +164,12 @@ impl Client {
|
||||
frontend_events.append(&mut self.handle_new_messages()?);
|
||||
|
||||
// Step 3
|
||||
if let Some(p) = self.player {
|
||||
if let Some(ecs_entity) = self.player.and_then(|uid| self.state().get_entity(uid)) {
|
||||
// TODO: remove this
|
||||
const PLAYER_VELOCITY: f32 = 100.0;
|
||||
|
||||
// TODO: Set acceleration instead
|
||||
self.state.write_component(p, comp::phys::Vel(Vec3::from(input.move_dir * PLAYER_VELOCITY)));
|
||||
self.state.write_component(ecs_entity, comp::phys::Vel(Vec3::from(input.move_dir * PLAYER_VELOCITY)));
|
||||
}
|
||||
|
||||
// Tick the client's LocalState (step 3)
|
||||
@ -182,12 +201,16 @@ impl Client {
|
||||
match msg {
|
||||
ServerMsg::Shutdown => return Err(Error::ServerShutdown),
|
||||
ServerMsg::Chat(msg) => frontend_events.push(Event::Chat(msg)),
|
||||
ServerMsg::SetPlayerEntity(uid) => self.player = Some(uid),
|
||||
ServerMsg::EntityPhysics { uid, pos, vel, dir } => {
|
||||
let ecs_entity = self.get_or_create_entity(uid);
|
||||
self.state.write_component(ecs_entity, pos);
|
||||
self.state.write_component(ecs_entity, vel);
|
||||
self.state.write_component(ecs_entity, dir);
|
||||
},
|
||||
ServerMsg::EntityDeleted(uid) => {
|
||||
self.state.delete_entity(uid);
|
||||
},
|
||||
}
|
||||
}
|
||||
} else if let Some(err) = self.postbox.status() {
|
||||
|
@ -6,7 +6,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
specs = { version = "0.14", features = ["serde"] }
|
||||
shred = "0.7"
|
||||
shred = { version = "0.7", features = ["nightly"] }
|
||||
vek = { version = "0.9", features = ["serde"] }
|
||||
dot_vox = "1.0"
|
||||
threadpool = "1.7"
|
||||
|
@ -8,8 +8,10 @@ use specs::World as EcsWorld;
|
||||
|
||||
pub fn register_local_components(ecs_world: &mut EcsWorld) {
|
||||
ecs_world.register::<Uid>();
|
||||
ecs_world.add_resource(UidAllocator::new());
|
||||
|
||||
ecs_world.register::<phys::Pos>();
|
||||
ecs_world.register::<phys::Vel>();
|
||||
ecs_world.register::<phys::Dir>();
|
||||
ecs_world.register::<phys::UpdateKind>();
|
||||
}
|
||||
|
@ -28,3 +28,14 @@ pub struct Dir(pub Vec3<f32>);
|
||||
impl Component for Dir {
|
||||
type Storage = VecStorage<Self>;
|
||||
}
|
||||
|
||||
// UpdateKind
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum UpdateKind {
|
||||
Passive,
|
||||
Force,
|
||||
}
|
||||
|
||||
impl Component for UpdateKind {
|
||||
type Storage = VecStorage<Self>;
|
||||
}
|
||||
|
@ -1,13 +1,18 @@
|
||||
use crate::comp::phys;
|
||||
use crate::comp::{
|
||||
Uid,
|
||||
phys,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ServerMsg {
|
||||
Shutdown,
|
||||
Chat(String),
|
||||
SetPlayerEntity(Uid),
|
||||
EntityPhysics {
|
||||
uid: u64,
|
||||
uid: Uid,
|
||||
pos: phys::Pos,
|
||||
vel: phys::Vel,
|
||||
dir: phys::Dir,
|
||||
},
|
||||
EntityDeleted(Uid),
|
||||
}
|
||||
|
@ -90,6 +90,14 @@ impl State {
|
||||
self
|
||||
}
|
||||
|
||||
/// Get an entity from its UID, if it exists
|
||||
pub fn get_entity(&self, uid: comp::Uid) -> Option<EcsEntity> {
|
||||
// Find the ECS entity from its UID
|
||||
self.ecs_world
|
||||
.read_resource::<comp::UidAllocator>()
|
||||
.retrieve_entity_internal(uid.into())
|
||||
}
|
||||
|
||||
/// Delete an entity from the state's ECS, if it exists
|
||||
pub fn delete_entity(&mut self, uid: comp::Uid) {
|
||||
// Find the ECS entity from its UID
|
||||
@ -103,16 +111,6 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Get rid of this
|
||||
pub fn new_test_player(&mut self) -> EcsEntity {
|
||||
self.ecs_world
|
||||
.create_entity()
|
||||
.with(comp::phys::Pos(Vec3::default()))
|
||||
.with(comp::phys::Vel(Vec3::default()))
|
||||
.with(comp::phys::Dir(Vec3::default()))
|
||||
.build()
|
||||
}
|
||||
|
||||
/// Write a component attributed to a particular entity
|
||||
pub fn write_component<C: Component>(&mut self, entity: EcsEntity, comp: C) {
|
||||
let _ = self.ecs_world.write_storage().insert(entity, comp);
|
||||
|
@ -3,7 +3,7 @@ use log::info;
|
||||
use server::{Input, Event, Server};
|
||||
use common::clock::Clock;
|
||||
|
||||
const FPS: u64 = 60;
|
||||
const TPS: u64 = 20;
|
||||
|
||||
fn main() {
|
||||
// Init logging
|
||||
@ -24,9 +24,9 @@ fn main() {
|
||||
|
||||
for event in events {
|
||||
match event {
|
||||
Event::ClientConnected { uid } => println!("Client {} connected!", uid),
|
||||
Event::ClientDisconnected { uid } => println!("Client {} disconnected!", uid),
|
||||
Event::Chat { uid, msg } => println!("[Client {}] {}", uid, msg),
|
||||
Event::ClientConnected { uid } => info!("Client {} connected!", uid),
|
||||
Event::ClientDisconnected { uid } => info!("Client {} disconnected!", uid),
|
||||
Event::Chat { uid, msg } => info!("[Client {}] {}", uid, msg),
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,6 +34,6 @@ fn main() {
|
||||
server.cleanup();
|
||||
|
||||
// Wait for the next tick
|
||||
clock.tick(Duration::from_millis(1000 / FPS));
|
||||
clock.tick(Duration::from_millis(1000 / TPS));
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ impl Clients {
|
||||
for client in &mut self.clients {
|
||||
// Consume any errors, deal with them later
|
||||
let _ = client.postbox.send(msg.clone());
|
||||
println!("Sending message...");
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +43,6 @@ impl Clients {
|
||||
if client.uid != uid {
|
||||
// Consume any errors, deal with them later
|
||||
let _ = client.postbox.send(msg.clone());
|
||||
println!("Sending message...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,12 +61,8 @@ impl Server {
|
||||
/// Create a new `Server`.
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
let mut state = State::new();
|
||||
|
||||
state.ecs_world_mut().add_resource(comp::UidAllocator::new());
|
||||
|
||||
Ok(Self {
|
||||
state,
|
||||
state: State::new(),
|
||||
world: World::new(),
|
||||
|
||||
postoffice: PostOffice::new(SocketAddr::from(([0; 4], 59003)))?,
|
||||
@ -93,6 +89,9 @@ impl Server {
|
||||
.with(comp::phys::Pos(Vec3::zero()))
|
||||
.with(comp::phys::Vel(Vec3::zero()))
|
||||
.with(comp::phys::Dir(Vec3::unit_y()))
|
||||
// When the player is first created, force a physics notification to everyone
|
||||
// including themselves.
|
||||
.with(comp::phys::UpdateKind::Force)
|
||||
}
|
||||
|
||||
/// Get a reference to the server's world.
|
||||
@ -154,19 +153,21 @@ impl Server {
|
||||
fn handle_new_connections(&mut self) -> Result<Vec<Event>, Error> {
|
||||
let mut frontend_events = Vec::new();
|
||||
|
||||
for postbox in self.postoffice.new_connections() {
|
||||
for mut postbox in self.postoffice.new_connections() {
|
||||
let ecs_entity = self.build_player().build();
|
||||
let uid = self.state.read_component(ecs_entity).unwrap();
|
||||
|
||||
frontend_events.push(Event::ClientConnected {
|
||||
uid,
|
||||
});
|
||||
let _ = postbox.send(ServerMsg::SetPlayerEntity(uid));
|
||||
|
||||
self.clients.add(Client {
|
||||
uid,
|
||||
postbox,
|
||||
last_ping: self.state.get_time(),
|
||||
});
|
||||
|
||||
frontend_events.push(Event::ClientConnected {
|
||||
uid,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(frontend_events)
|
||||
@ -178,6 +179,7 @@ impl Server {
|
||||
|
||||
let state = &mut self.state;
|
||||
let mut new_chat_msgs = Vec::new();
|
||||
let mut disconnected_clients = Vec::new();
|
||||
|
||||
self.clients.remove_if(|client| {
|
||||
let mut disconnected = false;
|
||||
@ -202,10 +204,7 @@ impl Server {
|
||||
}
|
||||
|
||||
if disconnected {
|
||||
state.delete_entity(client.uid);
|
||||
frontend_events.push(Event::ClientDisconnected {
|
||||
uid: client.uid,
|
||||
});
|
||||
disconnected_clients.push(client.uid);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@ -222,23 +221,45 @@ impl Server {
|
||||
});
|
||||
}
|
||||
|
||||
// Handle client disconnects
|
||||
for uid in disconnected_clients {
|
||||
self.clients.notify_all(ServerMsg::EntityDeleted(uid));
|
||||
|
||||
frontend_events.push(Event::ClientDisconnected {
|
||||
uid,
|
||||
});
|
||||
|
||||
state.delete_entity(uid);
|
||||
}
|
||||
|
||||
Ok(frontend_events)
|
||||
}
|
||||
|
||||
/// Sync client states with the most up to date information
|
||||
fn sync_clients(&mut self) {
|
||||
for (&uid, &pos, &vel, &dir) in (
|
||||
for (&uid, &pos, &vel, &dir, update_kind) in (
|
||||
&self.state.ecs_world().read_storage::<comp::Uid>(),
|
||||
&self.state.ecs_world().read_storage::<comp::phys::Pos>(),
|
||||
&self.state.ecs_world().read_storage::<comp::phys::Vel>(),
|
||||
&self.state.ecs_world().read_storage::<comp::phys::Dir>(),
|
||||
&mut self.state.ecs_world().write_storage::<comp::phys::UpdateKind>(),
|
||||
).join() {
|
||||
self.clients.notify_all_except(uid, ServerMsg::EntityPhysics {
|
||||
uid: uid.into(),
|
||||
let msg = ServerMsg::EntityPhysics {
|
||||
uid,
|
||||
pos,
|
||||
vel,
|
||||
dir,
|
||||
});
|
||||
};
|
||||
|
||||
// Sometimes we need to force updated (i.e: teleporting players). This involves sending
|
||||
// everyone, including the player themselves, of their new physics information.
|
||||
match update_kind {
|
||||
comp::phys::UpdateKind::Force => self.clients.notify_all(msg),
|
||||
comp::phys::UpdateKind::Passive => self.clients.notify_all_except(uid, msg),
|
||||
}
|
||||
|
||||
// Now that the update has occured, default to a passive update
|
||||
*update_kind = comp::phys::UpdateKind::Passive;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,10 @@ use super::{
|
||||
pub struct CharacterSkeleton {
|
||||
head: Bone,
|
||||
chest: Bone,
|
||||
bl_foot: Bone,
|
||||
br_foot: Bone,
|
||||
r_hand: Bone,
|
||||
belt: Bone,
|
||||
shorts: Bone,
|
||||
l_hand: Bone,
|
||||
r_hand: Bone,
|
||||
l_foot: Bone,
|
||||
r_foot: Bone,
|
||||
back: Bone,
|
||||
@ -29,10 +29,10 @@ impl CharacterSkeleton {
|
||||
Self {
|
||||
head: Bone::default(),
|
||||
chest: Bone::default(),
|
||||
br_foot: Bone::default(),
|
||||
bl_foot: Bone::default(),
|
||||
r_hand: Bone::default(),
|
||||
belt: Bone::default(),
|
||||
shorts: Bone::default(),
|
||||
l_hand: Bone::default(),
|
||||
r_hand: Bone::default(),
|
||||
l_foot: Bone::default(),
|
||||
r_foot: Bone::default(),
|
||||
back: Bone::default(),
|
||||
@ -47,10 +47,10 @@ impl Skeleton for CharacterSkeleton {
|
||||
[
|
||||
FigureBoneData::new(self.head.compute_base_matrix()),
|
||||
FigureBoneData::new(chest_mat),
|
||||
FigureBoneData::new(self.bl_foot.compute_base_matrix()),
|
||||
FigureBoneData::new(self.br_foot.compute_base_matrix()),
|
||||
FigureBoneData::new(self.r_hand.compute_base_matrix()),
|
||||
FigureBoneData::new(self.belt.compute_base_matrix()),
|
||||
FigureBoneData::new(self.shorts.compute_base_matrix()),
|
||||
FigureBoneData::new(self.l_hand.compute_base_matrix()),
|
||||
FigureBoneData::new(self.r_hand.compute_base_matrix()),
|
||||
FigureBoneData::new(self.l_foot.compute_base_matrix()),
|
||||
FigureBoneData::new(self.r_foot.compute_base_matrix()),
|
||||
FigureBoneData::new(chest_mat * self.back.compute_base_matrix()),
|
||||
|
@ -21,34 +21,30 @@ impl Animation for RunAnimation {
|
||||
time: f64,
|
||||
) {
|
||||
let wave = (time as f32 * 12.0).sin();
|
||||
let wavecos = (time as f32 * 12.0).cos();
|
||||
let wave_slow = (time as f32 * 6.0 + PI).sin();
|
||||
let wavecos_slow = (time as f32 * 6.0 + PI).cos();
|
||||
let wave_dip = (wave_slow.abs() - 0.5).abs();
|
||||
|
||||
skeleton.head.offset = Vec3::new(0.0, 0.0, 0.0);
|
||||
skeleton.head.ori = Quaternion::rotation_x(0.0);
|
||||
skeleton.head.offset = Vec3::unit_z() * 13.0;
|
||||
skeleton.head.ori = Quaternion::rotation_z(wave * 0.3);
|
||||
|
||||
skeleton.chest.offset = Vec3::new(0.0, 0.0, 0.0);
|
||||
skeleton.chest.ori = Quaternion::rotation_x(0.0);
|
||||
skeleton.chest.offset = Vec3::unit_z() * 9.0;
|
||||
skeleton.chest.ori = Quaternion::rotation_z(wave * 0.3);
|
||||
|
||||
//skeleton.br_foot.offset = Vec3::new(0.0, wavecos_slow * 1.0, wave_slow * 2.0 + wave_dip * 1.0);
|
||||
//skeleton.br_foot.ori = Quaternion::rotation_x(0.0 + wave_slow * 10.1);
|
||||
skeleton.belt.offset = Vec3::unit_z() * 7.0;
|
||||
skeleton.belt.ori = Quaternion::rotation_z(wave * 0.2);
|
||||
|
||||
skeleton.bl_foot.offset = Vec3::new(0.0, 0.0, 0.0);
|
||||
skeleton.bl_foot.ori = Quaternion::rotation_x(wave_slow * 2.0);
|
||||
//skeleton.bl_foot.offset = Vec3::new(0.0, wavecos_slow * 1.0, wave_slow * 2.0 + wave_dip * 1.0);
|
||||
//skeleton.bl_foot.ori = Quaternion::rotation_x(0.5 + wave_slow * 0.1);
|
||||
skeleton.shorts.offset = Vec3::unit_z() * 4.0;
|
||||
skeleton.shorts.ori = Quaternion::rotation_z(wave * 0.1);
|
||||
|
||||
//skeleton.r_hand.offset = Vec3::new(0.0, wavecos_slow * 1.0, wave_slow * 2.0 + wave_dip * 1.0);
|
||||
//skeleton.r_hand.ori = Quaternion::rotation_x(0.5 + wave_slow * 0.1);
|
||||
|
||||
skeleton.l_hand.offset = Vec3::new(0.0, 0.0, 0.0);
|
||||
skeleton.l_hand.ori = Quaternion::rotation_x(wave_slow * 2.0);
|
||||
|
||||
//skeleton.l_hand.offset = Vec3::new(0.0, wavecos_slow * 1.0, wave_slow * 2.0 + wave_dip * 1.0);
|
||||
//skeleton.l_hand.ori = Quaternion::rotation_x(0.5 + wave_slow * 0.1);
|
||||
skeleton.l_hand.offset = Vec3::new(-6.0 - wave_dip * 6.0, wave * 5.0, 11.0 - wave_dip * 6.0);
|
||||
skeleton.r_hand.offset = Vec3::new(6.0 + wave_dip * 6.0, -wave * 5.0, 11.0 - wave_dip * 6.0);
|
||||
|
||||
skeleton.l_foot.offset = Vec3::new(-3.5, 1.0 - wave * 8.0, 3.5 - wave_dip * 4.0);
|
||||
skeleton.l_foot.ori = Quaternion::rotation_x(-wave + 1.0);
|
||||
skeleton.r_foot.offset = Vec3::new(3.5, 1.0 + wave * 8.0, 3.5 - wave_dip * 4.0);
|
||||
skeleton.r_foot.ori = Quaternion::rotation_x(wave + 1.0);
|
||||
|
||||
skeleton.back.offset = Vec3::new(-9.0, 5.0, 18.0);
|
||||
skeleton.back.ori = Quaternion::rotation_y(2.5);
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,13 @@ pub mod camera;
|
||||
pub mod figure;
|
||||
pub mod terrain;
|
||||
|
||||
// Library
|
||||
use vek::*;
|
||||
use dot_vox;
|
||||
|
||||
// Project
|
||||
use common::figure::Segment;
|
||||
use common::{
|
||||
comp,
|
||||
figure::Segment,
|
||||
};
|
||||
use client::Client;
|
||||
|
||||
// Crate
|
||||
use crate::{
|
||||
render::{
|
||||
Consts,
|
||||
@ -29,8 +27,6 @@ use crate::{
|
||||
character::{CharacterSkeleton, RunAnimation},
|
||||
},
|
||||
};
|
||||
|
||||
// Local
|
||||
use self::{
|
||||
camera::Camera,
|
||||
figure::Figure,
|
||||
@ -82,15 +78,15 @@ impl Scene {
|
||||
test_figure: Figure::new(
|
||||
renderer,
|
||||
[
|
||||
Some(load_segment("dragonhead.vox").generate_mesh(Vec3::new(2.0, -12.0, 2.0))),
|
||||
Some(load_segment("dragon_body.vox").generate_mesh(Vec3::new(0.0, 0.0, 0.0))),
|
||||
Some(load_segment("dragon_lfoot.vox").generate_mesh(Vec3::new(0.0, 10.0, -4.0))),
|
||||
Some(load_segment("dragon_rfoot.vox").generate_mesh(Vec3::new(0.0, 10.0, -4.0))),
|
||||
Some(load_segment("dragon_rfoot.vox").generate_mesh(Vec3::new(0.0, -10.0, -4.0))),
|
||||
Some(load_segment("dragon_lfoot.vox").generate_mesh(Vec3::new(0.0, 0.0, 0.0))),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.0, -5.5, -1.0))),
|
||||
Some(load_segment("chest.vox").generate_mesh(Vec3::new(-6.0, -3.0, 0.0))),
|
||||
Some(load_segment("belt.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))),
|
||||
Some(load_segment("pants.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))),
|
||||
Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))),
|
||||
Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))),
|
||||
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))),
|
||||
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))),
|
||||
Some(load_segment("sword.vox").generate_mesh(Vec3::new(-6.5, -1.0, 0.0))),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@ -138,6 +134,22 @@ impl Scene {
|
||||
|
||||
/// Maintain data such as GPU constant buffers, models, etc. To be called once per tick.
|
||||
pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client) {
|
||||
// Get player position
|
||||
let player_pos = match client.player().and_then(|uid| client.state().get_entity(uid)) {
|
||||
Some(ecs_entity) => {
|
||||
client
|
||||
.state()
|
||||
.ecs_world()
|
||||
.read_storage::<comp::phys::Pos>()
|
||||
.get(ecs_entity)
|
||||
.expect("There was no position component on the player entity!")
|
||||
.0
|
||||
}
|
||||
None => Vec3::default(),
|
||||
};
|
||||
// Alter camera position to match player
|
||||
self.camera.set_focus_pos(player_pos);
|
||||
|
||||
// Compute camera matrices
|
||||
let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents();
|
||||
|
||||
@ -161,7 +173,11 @@ impl Scene {
|
||||
&mut self.test_figure.skeleton,
|
||||
client.state().get_time(),
|
||||
);
|
||||
self.test_figure.update_locals(renderer, FigureLocals::default()).unwrap();
|
||||
|
||||
// Calculate player model matrix
|
||||
let model_mat = Mat4::<f32>::translation_3d(player_pos);
|
||||
|
||||
self.test_figure.update_locals(renderer, FigureLocals::new(model_mat)).unwrap();
|
||||
self.test_figure.update_skeleton(renderer).unwrap();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user