mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Adapting various things to the new interface, fixing compilation errors,
and progressing on half done things. Also, added a few TODO comments.
This commit is contained in:
parent
4094887997
commit
f11baed9fa
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
common/src/uid.rs
|
|
||||||
# Rust
|
# Rust
|
||||||
target
|
target
|
||||||
|
|
||||||
|
@ -2221,6 +2221,7 @@ impl Client {
|
|||||||
if let Some(presence) = self.presence {
|
if let Some(presence) = self.presence {
|
||||||
self.presence = Some(match presence {
|
self.presence = Some(match presence {
|
||||||
PresenceKind::Spectator => PresenceKind::Spectator,
|
PresenceKind::Spectator => PresenceKind::Spectator,
|
||||||
|
PresenceKind::LoadingCharacter(_) => PresenceKind::Possessor,
|
||||||
PresenceKind::Character(_) => PresenceKind::Possessor,
|
PresenceKind::Character(_) => PresenceKind::Possessor,
|
||||||
PresenceKind::Possessor => PresenceKind::Possessor,
|
PresenceKind::Possessor => PresenceKind::Possessor,
|
||||||
});
|
});
|
||||||
@ -2748,12 +2749,12 @@ impl Client {
|
|||||||
|
|
||||||
// Recreate client entity with Uid
|
// Recreate client entity with Uid
|
||||||
let entity_builder = self.state.ecs_mut().create_entity();
|
let entity_builder = self.state.ecs_mut().create_entity();
|
||||||
let uid = entity_builder
|
entity_builder
|
||||||
.world
|
.world
|
||||||
.write_resource::<IdMaps>()
|
.write_resource::<IdMaps>()
|
||||||
.allocate(entity_builder.entity, Some(client_uid));
|
.add_entity(client_uid, entity_builder.entity);
|
||||||
|
|
||||||
let entity = entity_builder.with(uid).build();
|
let entity = entity_builder.with(client_uid).build();
|
||||||
self.state.ecs().write_resource::<PlayerEntity>().0 = Some(entity);
|
self.state.ecs().write_resource::<PlayerEntity>().0 = Some(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,10 +66,12 @@ impl WorldSyncExt for specs::World {
|
|||||||
|
|
||||||
/// This method should be used from the client-side when processing network
|
/// This method should be used from the client-side when processing network
|
||||||
/// messages that delete entities.
|
/// messages that delete entities.
|
||||||
// TODO: rename method
|
// TODO: rename method, document called from client only
|
||||||
fn delete_entity_and_clear_from_id_maps(&mut self, uid: Uid) {
|
fn delete_entity_and_clear_from_id_maps(&mut self, uid: Uid) {
|
||||||
// Clear from uid allocator
|
// Clear from uid allocator
|
||||||
let maybe_entity = self.write_resource::<IdMaps>().remove_entity_(uid);
|
let maybe_entity = self
|
||||||
|
.write_resource::<IdMaps>()
|
||||||
|
.remove_entity(None, uid, None, None);
|
||||||
if let Some(entity) = maybe_entity {
|
if let Some(entity) = maybe_entity {
|
||||||
if let Err(e) = self.delete_entity(entity) {
|
if let Err(e) = self.delete_entity(entity) {
|
||||||
error!(?e, "Failed to delete entity");
|
error!(?e, "Failed to delete entity");
|
||||||
@ -142,19 +144,24 @@ impl WorldSyncExt for specs::World {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Private utilities
|
// Private utilities
|
||||||
|
//
|
||||||
|
// Only used on the client.
|
||||||
fn create_entity_with_uid(specs_world: &mut specs::World, entity_uid: u64) -> specs::Entity {
|
fn create_entity_with_uid(specs_world: &mut specs::World, entity_uid: u64) -> specs::Entity {
|
||||||
let entity_uid = Uid::from(entity_uid);
|
let entity_uid = Uid::from(entity_uid);
|
||||||
let existing_entity = specs_world.read_resource::<IdMaps>().uid_entity(entity_uid);
|
let existing_entity = specs_world.read_resource::<IdMaps>().uid_entity(entity_uid);
|
||||||
|
|
||||||
|
// TODO: Are there any expected cases where there is an existing entity with
|
||||||
|
// this UID? If not, we may want to log an error. Otherwise, it may be useful to
|
||||||
|
// document these cases.
|
||||||
match existing_entity {
|
match existing_entity {
|
||||||
Some(entity) => entity,
|
Some(entity) => entity,
|
||||||
None => {
|
None => {
|
||||||
let entity_builder = specs_world.create_entity();
|
let entity_builder = specs_world.create_entity();
|
||||||
let uid = entity_builder
|
entity_builder
|
||||||
.world
|
.world
|
||||||
.write_resource::<IdMaps>()
|
.write_resource::<IdMaps>()
|
||||||
.allocate(entity_builder.entity, Some(entity_uid));
|
.add_entity(entity_uid, entity_builder.entity);
|
||||||
entity_builder.with(uid).build()
|
entity_builder.with(entity_uid).build()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,10 @@ impl Component for Presence {
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum PresenceKind {
|
pub enum PresenceKind {
|
||||||
Spectator,
|
Spectator,
|
||||||
Character(CharacterId),
|
|
||||||
// Note: we don't know if this character ID is valid and associated with the respective player
|
// Note: we don't know if this character ID is valid and associated with the respective player
|
||||||
// until it the character has loaded successfully.
|
// until it the character has loaded successfully.
|
||||||
LoadingCharacter(CharacterId),
|
LoadingCharacter(CharacterId),
|
||||||
|
Character(CharacterId),
|
||||||
Possessor,
|
Possessor,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ slotmap::new_key_type! { pub struct FactionId; }
|
|||||||
|
|
||||||
slotmap::new_key_type! { pub struct ReportId; }
|
slotmap::new_key_type! { pub struct ReportId; }
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
pub struct RtSimEntity(pub NpcId);
|
pub struct RtSimEntity(pub NpcId);
|
||||||
|
|
||||||
impl Component for RtSimEntity {
|
impl Component for RtSimEntity {
|
||||||
|
@ -62,11 +62,10 @@ mod not_wasm {
|
|||||||
// -- Fields below only used on the server --
|
// -- Fields below only used on the server --
|
||||||
uid_allocator: UidAllocator,
|
uid_allocator: UidAllocator,
|
||||||
|
|
||||||
// Maps below are only used on the server.
|
|
||||||
/// Character IDs.
|
/// Character IDs.
|
||||||
cid_mapping: HashMap<CharacterId, Entity>,
|
cid_mapping: HashMap<CharacterId, Entity>,
|
||||||
/// Rtsim Entities.
|
/// Rtsim Entities.
|
||||||
rid_mapping: HashMap<RtsimEntity, Entity>,
|
rid_mapping: HashMap<RtSimEntity, Entity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IdMaps {
|
impl IdMaps {
|
||||||
@ -84,12 +83,12 @@ mod not_wasm {
|
|||||||
|
|
||||||
/// Given a `CharacterId` retrieve the corresponding `Entity`.
|
/// Given a `CharacterId` retrieve the corresponding `Entity`.
|
||||||
pub fn cid_entity(&self, id: CharacterId) -> Option<Entity> {
|
pub fn cid_entity(&self, id: CharacterId) -> Option<Entity> {
|
||||||
self.uid_mapping.get(&id).copied()
|
self.cid_mapping.get(&id).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `RtSimEntity` retrieve the corresponding `Entity`.
|
/// Given a `RtSimEntity` retrieve the corresponding `Entity`.
|
||||||
pub fn rid_entity(&self, id: RtSimEntity) -> Option<Entity> {
|
pub fn rid_entity(&self, id: RtSimEntity) -> Option<Entity> {
|
||||||
self.uid_mapping.get(&id).copied()
|
self.rid_mapping.get(&id).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: I think this is suitable to use on both the client and the server.
|
// TODO: I think this is suitable to use on both the client and the server.
|
||||||
@ -105,17 +104,19 @@ mod not_wasm {
|
|||||||
expected_entity: Option<Entity>,
|
expected_entity: Option<Entity>,
|
||||||
uid: Uid,
|
uid: Uid,
|
||||||
cid: Option<CharacterId>,
|
cid: Option<CharacterId>,
|
||||||
rid: Option<RtsimEntity>,
|
rid: Option<RtSimEntity>,
|
||||||
) -> Option<Entity> {
|
) -> Option<Entity> {
|
||||||
#[cold]
|
#[cold]
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn unexpected_entity<ID>() {
|
fn unexpected_entity<ID>() {
|
||||||
error!("Provided was {kind} mapped to an unexpected entity!");
|
let kind = core::any::type_name::<ID>();
|
||||||
|
error!("Provided {kind} was mapped to an unexpected entity!");
|
||||||
}
|
}
|
||||||
#[cold]
|
#[cold]
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn not_present<ID>() {
|
fn not_present<ID>() {
|
||||||
error!("Provided was {kind} not mapped to any entity!");
|
let kind = core::any::type_name::<ID>();
|
||||||
|
error!("Provided {kind} was not mapped to any entity!");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove<ID: Hash + Eq>(
|
fn remove<ID: Hash + Eq>(
|
||||||
@ -124,8 +125,8 @@ mod not_wasm {
|
|||||||
expected: Option<Entity>,
|
expected: Option<Entity>,
|
||||||
) -> Option<Entity> {
|
) -> Option<Entity> {
|
||||||
if let Some(id) = id {
|
if let Some(id) = id {
|
||||||
if let Some(e) = mapping.remove(id) {
|
if let Some(e) = mapping.remove(&id) {
|
||||||
if Some(expected) = expected && e != expected {
|
if expected.map_or(true, |expected| e != expected) {
|
||||||
unexpected_entity::<ID>();
|
unexpected_entity::<ID>();
|
||||||
}
|
}
|
||||||
Some(e)
|
Some(e)
|
||||||
|
@ -83,15 +83,19 @@ pub fn handle_loaded_character_data(
|
|||||||
))),
|
))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let result_msg = if let Err(err) = server.state.update_character_data(entity, loaded_components) {
|
|
||||||
handle_exit_igname(entity, false); // remove client from in-game state
|
let result_msg = if let Err(err) = server
|
||||||
|
.state
|
||||||
|
.update_character_data(entity, loaded_components)
|
||||||
|
{
|
||||||
|
handle_exit_ingame(server, entity, false); // remove client from in-game state
|
||||||
ServerGeneral::CharacterDataLoadResult(Err(err))
|
ServerGeneral::CharacterDataLoadResult(Err(err))
|
||||||
} else {
|
} else {
|
||||||
sys::subscription::initialize_region_subscription(server.state.ecs(), entity);
|
sys::subscription::initialize_region_subscription(server.state.ecs(), entity);
|
||||||
// We notify the client with the metadata result from the operation.
|
// We notify the client with the metadata result from the operation.
|
||||||
ServerGeneral::CharacterDataLoadResult(Ok(metadata))
|
ServerGeneral::CharacterDataLoadResult(Ok(metadata))
|
||||||
};
|
};
|
||||||
server.notify_client(entity, result_msg));
|
server.notify_client(entity, result_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_create_npc(server: &mut Server, pos: Pos, mut npc: NpcBuilder) -> EcsEntity {
|
pub fn handle_create_npc(server: &mut Server, pos: Pos, mut npc: NpcBuilder) -> EcsEntity {
|
||||||
|
@ -80,6 +80,8 @@ pub fn handle_exit_ingame(server: &mut Server, entity: EcsEntity, skip_persisten
|
|||||||
let ecs = state.ecs();
|
let ecs = state.ecs();
|
||||||
Some((
|
Some((
|
||||||
ecs.write_storage::<Client>().remove(entity)?,
|
ecs.write_storage::<Client>().remove(entity)?,
|
||||||
|
// TODO: we need to handle the case where the UID component is removed but there may be
|
||||||
|
// a character ID mapping that also needs to be removed!
|
||||||
ecs.write_storage::<Uid>().remove(entity)?,
|
ecs.write_storage::<Uid>().remove(entity)?,
|
||||||
ecs.write_storage::<comp::Player>().remove(entity)?,
|
ecs.write_storage::<comp::Player>().remove(entity)?,
|
||||||
))
|
))
|
||||||
@ -107,6 +109,10 @@ pub fn handle_exit_ingame(server: &mut Server, entity: EcsEntity, skip_persisten
|
|||||||
.write_resource::<IdMaps>()
|
.write_resource::<IdMaps>()
|
||||||
.allocate(entity_builder.entity, Some(uid.into()));
|
.allocate(entity_builder.entity, Some(uid.into()));
|
||||||
let new_entity = entity_builder.with(uid).build();
|
let new_entity = entity_builder.with(uid).build();
|
||||||
|
|
||||||
|
// Note, since the Uid has been removed from the old entity, that prevents
|
||||||
|
// `delete_entity_recorded` from making any changes to the group (TODO double check this
|
||||||
|
// logic)
|
||||||
if let Some(group) = maybe_group {
|
if let Some(group) = maybe_group {
|
||||||
let mut group_manager = state.ecs().write_resource::<group::GroupManager>();
|
let mut group_manager = state.ecs().write_resource::<group::GroupManager>();
|
||||||
if group_manager
|
if group_manager
|
||||||
|
@ -27,7 +27,7 @@ use common::{
|
|||||||
resources::{Secs, Time, TimeOfDay},
|
resources::{Secs, Time, TimeOfDay},
|
||||||
rtsim::{Actor, RtSimEntity},
|
rtsim::{Actor, RtSimEntity},
|
||||||
slowjob::SlowJobPool,
|
slowjob::SlowJobPool,
|
||||||
uid::{Uid, IdMaps},
|
uid::{IdMaps, Uid},
|
||||||
LoadoutBuilder, ViewDistances,
|
LoadoutBuilder, ViewDistances,
|
||||||
};
|
};
|
||||||
use common_net::{
|
use common_net::{
|
||||||
@ -38,7 +38,7 @@ use common_state::State;
|
|||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use specs::{Builder, Entity as EcsEntity, EntityBuilder as EcsEntityBuilder, Join, WorldExt};
|
use specs::{Builder, Entity as EcsEntity, EntityBuilder as EcsEntityBuilder, Join, WorldExt};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use tracing::{trace, warn};
|
use tracing::{error, trace, warn};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
pub trait StateExt {
|
pub trait StateExt {
|
||||||
@ -125,7 +125,11 @@ pub trait StateExt {
|
|||||||
fn initialize_spectator_data(&mut self, entity: EcsEntity, view_distances: ViewDistances);
|
fn initialize_spectator_data(&mut self, entity: EcsEntity, view_distances: ViewDistances);
|
||||||
/// Update the components associated with the entity's current character.
|
/// Update the components associated with the entity's current character.
|
||||||
/// Performed after loading component data from the database
|
/// Performed after loading component data from the database
|
||||||
fn update_character_data(&mut self, entity: EcsEntity, components: PersistedComponents);
|
fn update_character_data(
|
||||||
|
&mut self,
|
||||||
|
entity: EcsEntity,
|
||||||
|
components: PersistedComponents,
|
||||||
|
) -> Result<(), String>;
|
||||||
/// Iterates over registered clients and send each `ServerMsg`
|
/// Iterates over registered clients and send each `ServerMsg`
|
||||||
fn validate_chat_msg(
|
fn validate_chat_msg(
|
||||||
&self,
|
&self,
|
||||||
@ -1173,6 +1177,9 @@ impl StateExt for State {
|
|||||||
|
|
||||||
let (maybe_uid, maybe_presence, maybe_rtsim_entity, maybe_pos) = (
|
let (maybe_uid, maybe_presence, maybe_rtsim_entity, maybe_pos) = (
|
||||||
self.ecs().read_storage::<Uid>().get(entity).copied(),
|
self.ecs().read_storage::<Uid>().get(entity).copied(),
|
||||||
|
// TODO: what if one of these 2 components was removed from the entity?
|
||||||
|
// We could simulate rlinear types at runtime with a `dev_panic!` in the drop for these
|
||||||
|
// components?
|
||||||
self.ecs()
|
self.ecs()
|
||||||
.read_storage::<Presence>()
|
.read_storage::<Presence>()
|
||||||
.get(entity)
|
.get(entity)
|
||||||
@ -1184,16 +1191,28 @@ impl StateExt for State {
|
|||||||
self.ecs().read_storage::<comp::Pos>().get(entity).copied(),
|
self.ecs().read_storage::<comp::Pos>().get(entity).copied(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(uid) = a {
|
if let Some(uid) = maybe_uid {
|
||||||
if self.ecs().write_resource::<IdMaps>()
|
// TODO: exit_ingame for player doesn't hit this path since Uid is removed
|
||||||
.remove_entity().is_none()
|
self.ecs().write_resource::<IdMaps>().remove_entity(
|
||||||
|
Some(entity),
|
||||||
|
uid,
|
||||||
|
maybe_presence.and_then(|p| match p.kind {
|
||||||
|
PresenceKind::Spectator
|
||||||
|
| PresenceKind::Possessed
|
||||||
|
| PresenceKind::LoadingCharacter(_) => None,
|
||||||
|
PresenceKind::Character(id) => Some(id),
|
||||||
|
}),
|
||||||
|
maybe_rtsim_entity,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
warn!("Deleting entity without Uid component");
|
error!("Deleting entity without Uid component");
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = self.ecs_mut().delete_entity(entity);
|
let res = self.ecs_mut().delete_entity(entity);
|
||||||
if res.is_ok() {
|
if res.is_ok() {
|
||||||
if let (Some(uid), Some(pos)) = (maybe_uid, maybe_pos) {
|
if let (Some(uid), Some(pos)) = (maybe_uid, maybe_pos) {
|
||||||
|
// TODO: exit_ingame for player doesn't hit this path since Uid is removed, not
|
||||||
|
// sure if that is correct.
|
||||||
if let Some(region_key) = self
|
if let Some(region_key) = self
|
||||||
.ecs()
|
.ecs()
|
||||||
.read_resource::<common::region::RegionMap>()
|
.read_resource::<common::region::RegionMap>()
|
||||||
|
Loading…
Reference in New Issue
Block a user