Added rtsim entity unload hook

This commit is contained in:
Joshua Barretto 2022-08-11 11:05:01 +01:00
parent f349e99cfb
commit 1dc7518200
10 changed files with 209 additions and 27 deletions

View File

@ -9,10 +9,10 @@ use vek::*;
use crate::comp::dialogue::MoodState;
pub type RtSimId = usize;
slotmap::new_key_type! { pub struct NpcId; }
#[derive(Copy, Clone, Debug)]
pub struct RtSimEntity(pub RtSimId);
pub struct RtSimEntity(pub NpcId);
impl Component for RtSimEntity {
type Storage = specs::VecStorage<Self>;

View File

@ -386,7 +386,7 @@ fn basic_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32) {
let accel = if let Some(block) = data.physics.on_ground {
// FRIC_GROUND temporarily used to normalize things around expected values
data.body.base_accel()
* data.scale.map_or(1.0, |s| s.0)
* data.scale.map_or(1.0, |s| s.0.sqrt())
* block.get_traction()
* block.get_friction() / FRIC_GROUND
} else {
@ -438,7 +438,7 @@ pub fn handle_forced_movement(
data.body.base_accel() * block.get_traction() * block.get_friction() / FRIC_GROUND
}) {
update.vel.0 +=
Vec2::broadcast(data.dt.0) * accel * data.scale.map_or(1.0, |s| s.0) * Vec2::from(*data.ori) * strength;
Vec2::broadcast(data.dt.0) * accel * data.scale.map_or(1.0, |s| s.0.sqrt()) * Vec2::from(*data.ori) * strength;
}
},
ForcedMovement::Reverse(strength) => {
@ -448,7 +448,7 @@ pub fn handle_forced_movement(
data.body.base_accel() * block.get_traction() * block.get_friction() / FRIC_GROUND
}) {
update.vel.0 +=
Vec2::broadcast(data.dt.0) * accel * data.scale.map_or(1.0, |s| s.0) * -Vec2::from(*data.ori) * strength;
Vec2::broadcast(data.dt.0) * accel * data.scale.map_or(1.0, |s| s.0.sqrt()) * -Vec2::from(*data.ori) * strength;
}
},
ForcedMovement::Sideways(strength) => {
@ -470,7 +470,7 @@ pub fn handle_forced_movement(
}
};
update.vel.0 += Vec2::broadcast(data.dt.0) * accel * data.scale.map_or(1.0, |s| s.0) * direction * strength;
update.vel.0 += Vec2::broadcast(data.dt.0) * accel * data.scale.map_or(1.0, |s| s.0.sqrt()) * direction * strength;
}
},
ForcedMovement::DirectedReverse(strength) => {
@ -519,7 +519,7 @@ pub fn handle_forced_movement(
dir.y,
vertical,
)
* data.scale.map_or(1.0, |s| s.0)
* data.scale.map_or(1.0, |s| s.0.sqrt())
// Multiply decreasing amount linearly over time (with average of 1)
* 2.0 * progress
// Apply direction
@ -533,7 +533,7 @@ pub fn handle_forced_movement(
},
ForcedMovement::Hover { move_input } => {
update.vel.0 = Vec3::new(data.vel.0.x, data.vel.0.y, 0.0) + move_input
* data.scale.map_or(1.0, |s| s.0)
* data.scale.map_or(1.0, |s| s.0.sqrt())
* data.inputs.move_dir.try_normalized().unwrap_or_default();
},
}
@ -575,7 +575,7 @@ pub fn handle_orientation(
};
// unit is multiples of 180°
let half_turns_per_tick = data.body.base_ori_rate()
/ data.scale.map_or(1.0, |s| s.0)
/ data.scale.map_or(1.0, |s| s.0.sqrt())
* efficiency
* if data.physics.on_ground.is_some() {
1.0
@ -1075,7 +1075,7 @@ pub fn handle_jump(
output_events.emit_local(LocalEvent::Jump(
data.entity,
strength * impulse / data.mass.0
* data.scale.map_or(1.0, |s| s.0.sqrt())
* data.scale.map_or(1.0, |s| s.0.powf(0.25))
* data.stats.move_speed_modifier,
));
})

View File

@ -5,7 +5,7 @@ use vek::*;
use std::ops::{Deref, DerefMut};
use common::uid::Uid;
slotmap::new_key_type! { pub struct NpcId; }
pub use common::rtsim::NpcId;
#[derive(Clone, Serialize, Deserialize)]
pub struct Npc {

View File

@ -3845,6 +3845,7 @@ fn handle_scale(
action: &ServerChatCommand,
) -> CmdResult<()> {
if let Some(scale) = parse_cmd_args!(args, f32) {
let scale = scale.clamped(0.025, 1000.0);
let _ = server
.state
.ecs_mut()

View File

@ -7,7 +7,7 @@ use crate::{
skillset::SkillGroupKind,
BuffKind, BuffSource, PhysicsState,
},
rtsim::RtSim,
// rtsim::RtSim,
sys::terrain::SAFE_ZONE_RADIUS,
Server, SpawnPoint, StateExt,
};
@ -26,8 +26,8 @@ use common::{
event::{EventBus, ServerEvent},
outcome::{HealthChangeInfo, Outcome},
resources::{Secs, Time},
rtsim::RtSimEntity,
states::utils::StageSection,
// rtsim::RtSimEntity,
states::utils::{AbilityInfo, StageSection},
terrain::{Block, BlockKind, TerrainGrid},
uid::{Uid, UidAllocator},
util::Dir,

View File

@ -30,7 +30,8 @@ pub mod metrics;
pub mod persistence;
mod pet;
pub mod presence;
pub mod rtsim;
// TODO: Remove
//pub mod rtsim;
pub mod rtsim2;
pub mod settings;
pub mod state_ext;
@ -65,7 +66,7 @@ use crate::{
login_provider::LoginProvider,
persistence::PersistedComponents,
presence::{Presence, RegionSubscription, RepositionOnChunkLoad},
rtsim::RtSim,
// rtsim::RtSim,
state_ext::StateExt,
sys::sentinel::DeletedEntities,
};
@ -386,6 +387,7 @@ impl Server {
state.ecs_mut().register::<comp::Pet>();
state.ecs_mut().register::<login_provider::PendingLogin>();
state.ecs_mut().register::<RepositionOnChunkLoad>();
state.ecs_mut().register::<RtSimEntity>();
// Load banned words list
let banned_words = settings.moderation.load_banned_words(data_dir);
@ -838,8 +840,8 @@ impl Server {
};
for entity in to_delete {
/*
// Assimilate entities that are part of the real-time world simulation
#[cfg(feature = "worldgen")]
if let Some(rtsim_entity) = self
.state
.ecs()
@ -849,10 +851,9 @@ impl Server {
{
self.state
.ecs()
.write_resource::<RtSim>()
.assimilate_entity(rtsim_entity.0);
.write_resource::<rtsim2::RtSim>()
.hook_rtsim_entity_unload(rtsim_entity);
}
*/
if let Err(e) = self.state.delete_entity_recorded(entity) {
error!(?e, "Failed to delete agent outside the terrain");

View File

@ -5,13 +5,17 @@ pub mod tick;
use common::{
grid::Grid,
slowjob::SlowJobPool,
rtsim::ChunkResource,
rtsim::{ChunkResource, RtSimEntity},
terrain::{TerrainChunk, Block},
vol::RectRasterableVol,
};
use common_ecs::{dispatch, System};
use rtsim2::{
data::{Data, ReadError},
data::{
npc::NpcMode,
Data,
ReadError,
},
rule::Rule,
RtState,
};
@ -116,6 +120,16 @@ impl RtSim {
}
}
pub fn hook_block_update(&mut self, wpos: Vec3<i32>, old: Block, new: Block) {
self.state.emit(event::OnBlockChange { wpos, old, new });
}
pub fn hook_rtsim_entity_unload(&mut self, entity: RtSimEntity) {
if let Some(npc) = self.state.data_mut().npcs.get_mut(entity.0) {
npc.mode = NpcMode::Simulated;
}
}
pub fn save(&mut self, slowjob_pool: &SlowJobPool) {
info!("Saving rtsim data...");
let file_path = self.file_path.clone();
@ -157,9 +171,6 @@ impl RtSim {
pub fn get_chunk_resources(&self, key: Vec2<i32>) -> EnumMap<ChunkResource, f32> {
self.state.data().nature.get_chunk_resources(key)
}
pub fn hook_block_update(&mut self, wpos: Vec3<i32>, old: Block, new: Block) {
self.state.emit(event::OnBlockChange { wpos, old, new });
}
}
struct ChunkStates(pub Grid<Option<LoadedChunkState>>);

View File

@ -8,6 +8,7 @@ use common::{
generation::{BodyBuilder, EntityConfig, EntityInfo},
resources::{DeltaTime, Time},
slowjob::SlowJobPool,
rtsim::RtSimEntity,
};
use common_ecs::{Job, Origin, Phase, System};
use rtsim2::data::npc::NpcMode;
@ -70,7 +71,7 @@ impl<'a> System<'a> for Sys {
scale: comp::Scale(10.0),
anchor: None,
loot: Default::default(),
rtsim_entity: None, // For now, the old one is used!
rtsim_entity: Some(RtSimEntity(npc_id)),
projectile: None,
});
}

View File

@ -2,7 +2,7 @@ pub mod behavior_tree;
pub use server_agent::{action_nodes, attack, consts, data, util};
use crate::{
rtsim::RtSim,
// rtsim::{entity::PersonalityTrait, RtSim},
sys::agent::{
behavior_tree::{BehaviorData, BehaviorTree},
data::{AgentData, ReadData},

View File

@ -0,0 +1,168 @@
// use crate::rtsim::Entity as RtSimData;
use common::{
comp::{
buff::Buffs, group, item::MaterialStatManifest, ActiveAbilities, Alignment, Body,
CharacterState, Combo, Energy, Health, Inventory, LightEmitter, LootOwner, Ori,
PhysicsState, Pos, Scale, SkillSet, Stats, Vel,
},
link::Is,
mounting::Mount,
path::TraversalConfig,
resources::{DeltaTime, Time, TimeOfDay},
// rtsim::RtSimEntity,
terrain::TerrainGrid,
uid::{Uid, UidAllocator},
};
use specs::{
shred::ResourceId, Entities, Entity as EcsEntity, Read, ReadExpect, ReadStorage, SystemData,
World,
};
use std::sync::Arc;
pub struct AgentData<'a> {
pub entity: &'a EcsEntity,
//pub rtsim_entity: Option<&'a RtSimData>,
pub uid: &'a Uid,
pub pos: &'a Pos,
pub vel: &'a Vel,
pub ori: &'a Ori,
pub energy: &'a Energy,
pub body: Option<&'a Body>,
pub inventory: &'a Inventory,
pub skill_set: &'a SkillSet,
#[allow(dead_code)] // may be useful for pathing
pub physics_state: &'a PhysicsState,
pub alignment: Option<&'a Alignment>,
pub traversal_config: TraversalConfig,
pub scale: f32,
pub damage: f32,
pub light_emitter: Option<&'a LightEmitter>,
pub glider_equipped: bool,
pub is_gliding: bool,
pub health: Option<&'a Health>,
pub char_state: &'a CharacterState,
pub active_abilities: &'a ActiveAbilities,
pub cached_spatial_grid: &'a common::CachedSpatialGrid,
pub msm: &'a MaterialStatManifest,
}
pub struct TargetData<'a> {
pub pos: &'a Pos,
pub body: Option<&'a Body>,
pub scale: Option<&'a Scale>,
}
impl<'a> TargetData<'a> {
pub fn new(pos: &'a Pos, body: Option<&'a Body>, scale: Option<&'a Scale>) -> Self {
Self { pos, body, scale }
}
}
pub struct AttackData {
pub min_attack_dist: f32,
pub dist_sqrd: f32,
pub angle: f32,
pub angle_xy: f32,
}
impl AttackData {
pub fn in_min_range(&self) -> bool { self.dist_sqrd < self.min_attack_dist.powi(2) }
}
#[derive(Eq, PartialEq)]
// When adding a new variant, first decide if it should instead fall under one
// of the pre-existing tactics
pub enum Tactic {
// General tactics
SimpleMelee,
SimpleBackstab,
ElevatedRanged,
Turret,
FixedTurret,
RotatingTurret,
RadialTurret,
// Tool specific tactics
Axe,
Hammer,
Sword,
Bow,
Staff,
Sceptre,
// Broad creature tactics
CircleCharge { radius: u32, circle_time: u32 },
QuadLowRanged,
TailSlap,
QuadLowQuick,
QuadLowBasic,
QuadLowBeam,
QuadMedJump,
QuadMedBasic,
Theropod,
BirdLargeBreathe,
BirdLargeFire,
BirdLargeBasic,
ArthropodMelee,
ArthropodRanged,
ArthropodAmbush,
// Specific species tactics
Mindflayer,
Minotaur,
ClayGolem,
TidalWarrior,
Yeti,
Harvester,
StoneGolem,
Deadwood,
Mandragora,
WoodGolem,
GnarlingChieftain,
OrganAura,
Dagon,
Cardinal,
}
#[derive(SystemData)]
pub struct ReadData<'a> {
pub entities: Entities<'a>,
pub uid_allocator: Read<'a, UidAllocator>,
pub dt: Read<'a, DeltaTime>,
pub time: Read<'a, Time>,
pub cached_spatial_grid: Read<'a, common::CachedSpatialGrid>,
pub group_manager: Read<'a, group::GroupManager>,
pub energies: ReadStorage<'a, Energy>,
pub positions: ReadStorage<'a, Pos>,
pub velocities: ReadStorage<'a, Vel>,
pub orientations: ReadStorage<'a, Ori>,
pub scales: ReadStorage<'a, Scale>,
pub healths: ReadStorage<'a, Health>,
pub inventories: ReadStorage<'a, Inventory>,
pub stats: ReadStorage<'a, Stats>,
pub skill_set: ReadStorage<'a, SkillSet>,
pub physics_states: ReadStorage<'a, PhysicsState>,
pub char_states: ReadStorage<'a, CharacterState>,
pub uids: ReadStorage<'a, Uid>,
pub groups: ReadStorage<'a, group::Group>,
pub terrain: ReadExpect<'a, TerrainGrid>,
pub alignments: ReadStorage<'a, Alignment>,
pub bodies: ReadStorage<'a, Body>,
pub is_mounts: ReadStorage<'a, Is<Mount>>,
pub time_of_day: Read<'a, TimeOfDay>,
pub light_emitter: ReadStorage<'a, LightEmitter>,
#[cfg(feature = "worldgen")]
pub world: ReadExpect<'a, Arc<world::World>>,
//pub rtsim_entities: ReadStorage<'a, RtSimEntity>,
pub buffs: ReadStorage<'a, Buffs>,
pub combos: ReadStorage<'a, Combo>,
pub active_abilities: ReadStorage<'a, ActiveAbilities>,
pub loot_owners: ReadStorage<'a, LootOwner>,
pub msm: ReadExpect<'a, MaterialStatManifest>,
}
pub enum Path {
Full,
Separate,
Partial,
}