Various bug fixes for entity handling. TODO: Smite this system from orbit, it sucks
This commit is contained in:
parent
347244c65c
commit
e36a0f4579
|
@ -84,6 +84,7 @@ pub trait System {
|
|||
struct EntityState {
|
||||
last_components: BSet,
|
||||
components: BSet,
|
||||
removed: bool,
|
||||
}
|
||||
|
||||
/// Stores and manages a collection of entities.
|
||||
|
@ -99,7 +100,6 @@ pub struct Manager {
|
|||
render_systems: Vec<Box<System + Send>>,
|
||||
|
||||
changed_entity_components: HashSet<Entity, BuildHasherDefault<FNVHash>>,
|
||||
removed_entities: HashSet<Entity, BuildHasherDefault<FNVHash>>,
|
||||
}
|
||||
|
||||
impl Manager {
|
||||
|
@ -110,6 +110,7 @@ impl Manager {
|
|||
entities: vec![(Some(EntityState {
|
||||
last_components: BSet::new(0),
|
||||
components: BSet::new(0),
|
||||
removed: false,
|
||||
}), 0)], // Has the world entity pre-defined
|
||||
free_entities: vec![],
|
||||
components: vec![],
|
||||
|
@ -119,7 +120,6 @@ impl Manager {
|
|||
render_systems: vec![],
|
||||
|
||||
changed_entity_components: HashSet::with_hasher(BuildHasherDefault::default()),
|
||||
removed_entities: HashSet::with_hasher(BuildHasherDefault::default()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@ impl Manager {
|
|||
}
|
||||
}
|
||||
|
||||
if self.removed_entities.remove(&entity) {
|
||||
if state.removed {
|
||||
self.free_entities.push(entity.id);
|
||||
self.entities[entity.id].0 = None;
|
||||
} else {
|
||||
|
@ -195,7 +195,7 @@ impl Manager {
|
|||
// Skip the world entity.
|
||||
for (i, &(ref set, gen)) in self.entities[1..].iter().enumerate() {
|
||||
if let Some(set) = set.as_ref() {
|
||||
if set.components.includes_set(&filter.bits) {
|
||||
if !set.removed && set.components.includes_set(&filter.bits) {
|
||||
ret.push(Entity {
|
||||
id: i + 1,
|
||||
generation: gen,
|
||||
|
@ -213,6 +213,7 @@ impl Manager {
|
|||
entity.0 = Some(EntityState {
|
||||
last_components: BSet::new(self.num_components),
|
||||
components: BSet::new(self.num_components),
|
||||
removed: false,
|
||||
});
|
||||
entity.1 += 1;
|
||||
return Entity {
|
||||
|
@ -225,6 +226,7 @@ impl Manager {
|
|||
Some(EntityState {
|
||||
last_components: BSet::new(self.num_components),
|
||||
components: BSet::new(self.num_components),
|
||||
removed: false,
|
||||
}),
|
||||
0
|
||||
));
|
||||
|
@ -238,10 +240,21 @@ impl Manager {
|
|||
pub fn remove_entity(&mut self, e: Entity) {
|
||||
if let Some(set) = self.entities[e.id].0.as_mut() {
|
||||
set.components = BSet::new(self.components.len());
|
||||
self.removed_entities.insert(e);
|
||||
set.removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Deallocates all entities/components excluding the world entity
|
||||
pub fn remove_all_entities(&mut self) {
|
||||
for e in &mut self.entities[1..] {
|
||||
if let Some(set) = e.0.as_mut() {
|
||||
set.components = BSet::new(self.components.len());
|
||||
set.removed = true;
|
||||
}
|
||||
}
|
||||
self.process_entity_changes();
|
||||
}
|
||||
|
||||
/// Returns whether an entity reference is valid.
|
||||
pub fn is_entity_valid(&self, e: Entity) -> bool {
|
||||
match self.entities.get(e.id) {
|
||||
|
|
|
@ -114,6 +114,14 @@ impl <T> ::std::ops::Deref for Proxy<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl <T> ::std::ops::DerefMut for Proxy<T> {
|
||||
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
self.inner.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl <T> Proxy<T> {
|
||||
|
||||
pub fn new() -> Proxy<T> {
|
||||
|
|
|
@ -27,7 +27,7 @@ pub fn add_systems(m: &mut ecs::Manager) {
|
|||
|
||||
pub fn create_local(m: &mut ecs::Manager) -> ecs::Entity {
|
||||
let entity = m.create_entity();
|
||||
m.add_component_direct(entity, Position::new(0.5, 13.2, 0.5));
|
||||
m.add_component_direct(entity, Position::new(0.0, 0.0, 0.0));
|
||||
m.add_component_direct(entity, Rotation::new(0.0, 0.0));
|
||||
m.add_component_direct(entity, Velocity::new(0.0, 0.0, 0.0));
|
||||
m.add_component_direct(entity, Gamemode::Survival);
|
||||
|
|
31
src/main.rs
31
src/main.rs
|
@ -109,10 +109,10 @@ impl Game {
|
|||
|
||||
pub fn tick(&mut self, delta: f64) {
|
||||
if !self.server.is_connected() {
|
||||
let rotation = self.server.entities.get_component_mut(self.server.player, self.server.rotation).unwrap();
|
||||
rotation.yaw += 0.005 * delta;
|
||||
if rotation.yaw > ::std::f64::consts::PI * 2.0 {
|
||||
rotation.yaw = 0.0;
|
||||
self.renderer.camera.pos = cgmath::Point3::new(0.5, 13.2, 0.5);
|
||||
self.renderer.camera.yaw += 0.005 * delta;
|
||||
if self.renderer.camera.yaw > ::std::f64::consts::PI * 2.0 {
|
||||
self.renderer.camera.yaw = 0.0;
|
||||
}
|
||||
}
|
||||
let mut clear_reply = false;
|
||||
|
@ -123,6 +123,7 @@ impl Game {
|
|||
Ok(val) => {
|
||||
self.screen_sys.pop_screen();
|
||||
self.focused = true;
|
||||
self.server.remove(&mut self.renderer);
|
||||
self.server = val;
|
||||
},
|
||||
Err(err) => {
|
||||
|
@ -270,16 +271,18 @@ fn handle_window_event(window: &sdl2::video::Window,
|
|||
if !mouse.relative_mouse_mode() {
|
||||
mouse.set_relative_mouse_mode(true);
|
||||
}
|
||||
let s = 2000.0 + 0.01;
|
||||
let (rx, ry) = (xrel as f64 / s, yrel as f64 / s);
|
||||
let rotation = game.server.entities.get_component_mut(game.server.player, game.server.rotation).unwrap();
|
||||
rotation.yaw -= rx;
|
||||
rotation.pitch -= ry;
|
||||
if rotation.pitch < (PI/2.0) + 0.01 {
|
||||
rotation.pitch = (PI/2.0) + 0.01;
|
||||
}
|
||||
if rotation.pitch > (PI/2.0)*3.0 - 0.01 {
|
||||
rotation.pitch = (PI/2.0)*3.0 - 0.01;
|
||||
if let Some(player) = game.server.player {
|
||||
let s = 2000.0 + 0.01;
|
||||
let (rx, ry) = (xrel as f64 / s, yrel as f64 / s);
|
||||
let rotation = game.server.entities.get_component_mut(player, game.server.rotation).unwrap();
|
||||
rotation.yaw -= rx;
|
||||
rotation.pitch -= ry;
|
||||
if rotation.pitch < (PI/2.0) + 0.01 {
|
||||
rotation.pitch = (PI/2.0) + 0.01;
|
||||
}
|
||||
if rotation.pitch > (PI/2.0)*3.0 - 0.01 {
|
||||
rotation.pitch = (PI/2.0)*3.0 - 0.01;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ui_container.hover_at(game, x as f64, y as f64, width as f64, height as f64);
|
||||
|
|
197
src/server.rs
197
src/server.rs
|
@ -60,11 +60,12 @@ pub struct Server {
|
|||
pub rotation: ecs::Key<entity::Rotation>,
|
||||
//
|
||||
|
||||
pub player: ecs::Entity,
|
||||
pub player: Option<ecs::Entity>,
|
||||
entity_map: HashMap<i32, ecs::Entity, BuildHasherDefault<FNVHash>>,
|
||||
|
||||
pressed_keys: HashMap<Keycode, bool, BuildHasherDefault<FNVHash>>,
|
||||
tick_timer: f64,
|
||||
entity_tick_timer: f64,
|
||||
}
|
||||
|
||||
macro_rules! handle_packet {
|
||||
|
@ -177,7 +178,6 @@ impl Server {
|
|||
}
|
||||
}
|
||||
}
|
||||
*server.entities.get_component_mut(server.player, server.gamemode).unwrap() = Gamemode::Spectator;
|
||||
server
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,6 @@ impl Server {
|
|||
let mut entities = ecs::Manager::new();
|
||||
entity::add_systems(&mut entities);
|
||||
|
||||
let player = entity::player::create_local(&mut entities);
|
||||
let world_entity = entities.get_world();
|
||||
let world_proxy = entities.get_key();
|
||||
entities.add_component(world_entity, world_proxy, entity::Proxy::new());
|
||||
|
@ -226,10 +225,11 @@ impl Server {
|
|||
//
|
||||
|
||||
entities: entities,
|
||||
player: player,
|
||||
player: None,
|
||||
entity_map: HashMap::with_hasher(BuildHasherDefault::default()),
|
||||
|
||||
tick_timer: 0.0,
|
||||
entity_tick_timer: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,6 +244,40 @@ impl Server {
|
|||
self.world.flag_dirty_all();
|
||||
}
|
||||
|
||||
self.entity_tick(renderer, delta);
|
||||
|
||||
self.tick_timer += delta;
|
||||
while self.tick_timer >= 3.0 && self.is_connected() {
|
||||
self.minecraft_tick();
|
||||
self.tick_timer -= 3.0;
|
||||
}
|
||||
|
||||
self.update_time(renderer, delta);
|
||||
|
||||
// Copy to camera
|
||||
if let Some(player) = self.player {
|
||||
let position = self.entities.get_component(player, self.position).unwrap();
|
||||
let rotation = self.entities.get_component(player, self.rotation).unwrap();
|
||||
renderer.camera.pos = cgmath::Point::from_vec(position.position + cgmath::Vector3::new(0.0, 1.62, 0.0));
|
||||
renderer.camera.yaw = rotation.yaw;
|
||||
renderer.camera.pitch = rotation.pitch;
|
||||
}
|
||||
}
|
||||
|
||||
fn entity_tick(&mut self, renderer: &mut render::Renderer, delta: f64) {
|
||||
let world_entity = self.entities.get_world();
|
||||
// Borrow the world and renderer
|
||||
self.entities.get_component_mut(world_entity, self.world_proxy)
|
||||
.unwrap()
|
||||
.give(&mut self.world);
|
||||
self.entities.get_component_mut(world_entity, self.renderer_proxy)
|
||||
.unwrap()
|
||||
.give(renderer);
|
||||
// Update the game's state for entities to read
|
||||
self.entities.get_component_mut(world_entity, self.game_info)
|
||||
.unwrap().delta = delta;
|
||||
|
||||
// Packets modify entities so need to handled here
|
||||
if let Some(rx) = self.read_queue.take() {
|
||||
while let Ok(pck) = rx.try_recv() {
|
||||
match pck {
|
||||
|
@ -265,25 +299,24 @@ impl Server {
|
|||
self.read_queue = Some(rx);
|
||||
}
|
||||
|
||||
self.tick_timer += delta;
|
||||
while self.tick_timer >= 3.0 && self.is_connected() {
|
||||
self.minecraft_tick();
|
||||
self.tick_timer -= 3.0;
|
||||
self.entity_tick_timer += delta;
|
||||
while self.entity_tick_timer >= 3.0 && self.is_connected() {
|
||||
self.entities.tick();
|
||||
self.entity_tick_timer -= 3.0;
|
||||
}
|
||||
|
||||
self.render_tick(renderer, delta);
|
||||
self.entities.render_tick();
|
||||
|
||||
self.update_time(renderer, delta);
|
||||
|
||||
// Copy to camera
|
||||
let position = self.entities.get_component(self.player, self.position).unwrap();
|
||||
let rotation = self.entities.get_component(self.player, self.rotation).unwrap();
|
||||
renderer.camera.pos = cgmath::Point::from_vec(position.position + cgmath::Vector3::new(0.0, 1.62, 0.0));
|
||||
renderer.camera.yaw = rotation.yaw;
|
||||
renderer.camera.pitch = rotation.pitch;
|
||||
// Return what we borrowed
|
||||
self.entities.get_component_mut(world_entity, self.world_proxy)
|
||||
.unwrap()
|
||||
.take(&mut self.world);
|
||||
self.entities.get_component_mut(world_entity, self.renderer_proxy)
|
||||
.unwrap()
|
||||
.take(renderer);
|
||||
}
|
||||
|
||||
fn render_tick(&mut self, renderer: &mut render::Renderer, delta: f64) {
|
||||
pub fn remove(&mut self, renderer: &mut render::Renderer) {
|
||||
let world_entity = self.entities.get_world();
|
||||
// Borrow the world and renderer
|
||||
self.entities.get_component_mut(world_entity, self.world_proxy)
|
||||
|
@ -292,12 +325,10 @@ impl Server {
|
|||
self.entities.get_component_mut(world_entity, self.renderer_proxy)
|
||||
.unwrap()
|
||||
.give(renderer);
|
||||
// Update the game's state for entities to read
|
||||
self.entities.get_component_mut(world_entity, self.game_info)
|
||||
.unwrap().delta = delta;
|
||||
|
||||
self.entities.render_tick();
|
||||
self.entities.remove_all_entities();
|
||||
|
||||
// Return what we borrowed
|
||||
self.entities.get_component_mut(world_entity, self.world_proxy)
|
||||
.unwrap()
|
||||
.take(&mut self.world);
|
||||
|
@ -348,47 +379,42 @@ impl Server {
|
|||
}
|
||||
|
||||
pub fn minecraft_tick(&mut self) {
|
||||
let world_entity = self.entities.get_world();
|
||||
self.entities.get_component_mut(world_entity, self.world_proxy)
|
||||
.unwrap()
|
||||
.give(&mut self.world);
|
||||
self.entities.tick();
|
||||
self.entities.get_component_mut(world_entity, self.world_proxy)
|
||||
.unwrap()
|
||||
.take(&mut self.world);
|
||||
if let Some(player) = self.player {
|
||||
let movement = self.entities.get_component_mut(player, self.player_movement).unwrap();
|
||||
let on_ground = self.entities.get_component(player, self.gravity).map_or(false, |v| v.on_ground);
|
||||
let position = self.entities.get_component(player, self.position).unwrap();
|
||||
let rotation = self.entities.get_component(player, self.rotation).unwrap();
|
||||
|
||||
let movement = self.entities.get_component_mut(self.player, self.player_movement).unwrap();
|
||||
let on_ground = self.entities.get_component(self.player, self.gravity).map_or(false, |v| v.on_ground);
|
||||
let position = self.entities.get_component(self.player, self.position).unwrap();
|
||||
let rotation = self.entities.get_component(self.player, self.rotation).unwrap();
|
||||
// Force the server to know when touched the ground
|
||||
// otherwise if it happens between ticks the server
|
||||
// will think we are flying.
|
||||
let on_ground = if movement.did_touch_ground {
|
||||
movement.did_touch_ground = false;
|
||||
true
|
||||
} else {
|
||||
on_ground
|
||||
};
|
||||
|
||||
// Force the server to know when touched the ground
|
||||
// otherwise if it happens between ticks the server
|
||||
// will think we are flying.
|
||||
let on_ground = if movement.did_touch_ground {
|
||||
movement.did_touch_ground = false;
|
||||
true
|
||||
} else {
|
||||
on_ground
|
||||
};
|
||||
|
||||
// Sync our position to the server
|
||||
// Use the smaller packets when possible
|
||||
let packet = packet::play::serverbound::PlayerPositionLook {
|
||||
x: position.position.x,
|
||||
y: position.position.y,
|
||||
z: position.position.z,
|
||||
yaw: rotation.yaw as f32,
|
||||
pitch: rotation.pitch as f32,
|
||||
on_ground: on_ground,
|
||||
};
|
||||
self.write_packet(packet);
|
||||
// Sync our position to the server
|
||||
// Use the smaller packets when possible
|
||||
let packet = packet::play::serverbound::PlayerPositionLook {
|
||||
x: position.position.x,
|
||||
y: position.position.y,
|
||||
z: position.position.z,
|
||||
yaw: rotation.yaw as f32,
|
||||
pitch: rotation.pitch as f32,
|
||||
on_ground: on_ground,
|
||||
};
|
||||
self.write_packet(packet);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn key_press(&mut self, down: bool, key: Keycode) {
|
||||
self.pressed_keys.insert(key, down);
|
||||
if let Some(movement) = self.entities.get_component_mut(self.player, self.player_movement) {
|
||||
movement.pressed_keys.insert(key, down);
|
||||
if let Some(player) = self.player {
|
||||
if let Some(movement) = self.entities.get_component_mut(player, self.player_movement) {
|
||||
movement.pressed_keys.insert(key, down);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,19 +434,24 @@ impl Server {
|
|||
|
||||
fn on_game_join(&mut self, join: packet::play::clientbound::JoinGame) {
|
||||
let gamemode = Gamemode::from_int((join.gamemode & 0x7) as i32);
|
||||
*self.entities.get_component_mut(self.player, self.gamemode).unwrap() = gamemode;
|
||||
let player = entity::player::create_local(&mut self.entities);
|
||||
*self.entities.get_component_mut(player, self.gamemode).unwrap() = gamemode;
|
||||
// TODO: Temp
|
||||
self.entities.get_component_mut(self.player, self.player_movement).unwrap().flying = gamemode.can_fly();
|
||||
self.entities.get_component_mut(player, self.player_movement).unwrap().flying = gamemode.can_fly();
|
||||
|
||||
self.entity_map.insert(join.entity_id, self.player);
|
||||
self.entity_map.insert(join.entity_id, player);
|
||||
self.player = Some(player);
|
||||
}
|
||||
|
||||
fn on_respawn(&mut self, respawn: packet::play::clientbound::Respawn) {
|
||||
self.world = world::World::new();
|
||||
let gamemode = Gamemode::from_int((respawn.gamemode & 0x7) as i32);
|
||||
*self.entities.get_component_mut(self.player, self.gamemode).unwrap() = gamemode;
|
||||
// TODO: Temp
|
||||
self.entities.get_component_mut(self.player, self.player_movement).unwrap().flying = gamemode.can_fly();
|
||||
|
||||
if let Some(player) = self.player {
|
||||
*self.entities.get_component_mut(player, self.gamemode).unwrap() = gamemode;
|
||||
// TODO: Temp
|
||||
self.entities.get_component_mut(player, self.player_movement).unwrap().flying = gamemode.can_fly();
|
||||
}
|
||||
}
|
||||
|
||||
fn on_time_update(&mut self, time_update: packet::play::clientbound::TimeUpdate) {
|
||||
|
@ -437,32 +468,38 @@ impl Server {
|
|||
fn on_game_state_change(&mut self, game_state: packet::play::clientbound::ChangeGameState) {
|
||||
match game_state.reason {
|
||||
3 => {
|
||||
let gamemode = Gamemode::from_int(game_state.value as i32);
|
||||
*self.entities.get_component_mut(self.player, self.gamemode).unwrap() = gamemode;
|
||||
// TODO: Temp
|
||||
self.entities.get_component_mut(self.player, self.player_movement).unwrap().flying = gamemode.can_fly();
|
||||
if let Some(player) = self.player {
|
||||
let gamemode = Gamemode::from_int(game_state.value as i32);
|
||||
*self.entities.get_component_mut(player, self.gamemode).unwrap() = gamemode;
|
||||
// TODO: Temp
|
||||
self.entities.get_component_mut(player, self.player_movement).unwrap().flying = gamemode.can_fly();
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn on_teleport(&mut self, teleport: packet::play::clientbound::TeleportPlayer) {
|
||||
let position = self.entities.get_component_mut(self.player, self.position).unwrap();
|
||||
let rotation = self.entities.get_component_mut(self.player, self.rotation).unwrap();
|
||||
if let Some(player) = self.player {
|
||||
let position = self.entities.get_component_mut(player, self.position).unwrap();
|
||||
let rotation = self.entities.get_component_mut(player, self.rotation).unwrap();
|
||||
|
||||
position.position.x = calculate_relative_teleport(TeleportFlag::RelX, teleport.flags, position.position.x, teleport.x);
|
||||
position.position.y = calculate_relative_teleport(TeleportFlag::RelY, teleport.flags, position.position.y, teleport.y);
|
||||
position.position.z = calculate_relative_teleport(TeleportFlag::RelZ, teleport.flags, position.position.z, teleport.z);
|
||||
rotation.yaw = calculate_relative_teleport(TeleportFlag::RelYaw, teleport.flags, rotation.yaw, teleport.yaw as f64);
|
||||
rotation.pitch = calculate_relative_teleport(TeleportFlag::RelPitch, teleport.flags, rotation.pitch, teleport.pitch as f64);
|
||||
position.position.x = calculate_relative_teleport(TeleportFlag::RelX, teleport.flags, position.position.x, teleport.x);
|
||||
position.position.y = calculate_relative_teleport(TeleportFlag::RelY, teleport.flags, position.position.y, teleport.y);
|
||||
position.position.z = calculate_relative_teleport(TeleportFlag::RelZ, teleport.flags, position.position.z, teleport.z);
|
||||
rotation.yaw = calculate_relative_teleport(TeleportFlag::RelYaw, teleport.flags, rotation.yaw, teleport.yaw as f64);
|
||||
rotation.pitch = calculate_relative_teleport(TeleportFlag::RelPitch, teleport.flags, rotation.pitch, teleport.pitch as f64);
|
||||
|
||||
self.write_packet(packet::play::serverbound::TeleportConfirm {
|
||||
teleport_id: teleport.teleport_id,
|
||||
});
|
||||
self.write_packet(packet::play::serverbound::TeleportConfirm {
|
||||
teleport_id: teleport.teleport_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn on_chunk_data(&mut self, chunk_data: packet::play::clientbound::ChunkData) {
|
||||
self.world.load_chunk(
|
||||
let world_entity = self.entities.get_world();
|
||||
let world = self.entities.get_component_mut(world_entity, self.world_proxy).unwrap();
|
||||
world.load_chunk(
|
||||
chunk_data.chunk_x,
|
||||
chunk_data.chunk_z,
|
||||
chunk_data.new,
|
||||
|
@ -472,7 +509,9 @@ impl Server {
|
|||
}
|
||||
|
||||
fn on_chunk_unload(&mut self, chunk_unload: packet::play::clientbound::ChunkUnload) {
|
||||
self.world.unload_chunk(chunk_unload.x, chunk_unload.z);
|
||||
let world_entity = self.entities.get_world();
|
||||
let world = self.entities.get_component_mut(world_entity, self.world_proxy).unwrap();
|
||||
world.unload_chunk(chunk_unload.x, chunk_unload.z);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue