mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Fix rtsim airships
This commit is contained in:
parent
a386c68df5
commit
06d7548dc6
@ -387,5 +387,9 @@ impl<'a, E> Emitter<'a, E> {
|
||||
}
|
||||
|
||||
impl<'a, E> Drop for Emitter<'a, E> {
|
||||
fn drop(&mut self) { self.bus.queue.lock().unwrap().append(&mut self.events); }
|
||||
fn drop(&mut self) {
|
||||
if !self.events.is_empty() {
|
||||
self.bus.queue.lock().unwrap().append(&mut self.events);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ impl Npc {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Riding {
|
||||
pub vehicle: VehicleId,
|
||||
pub steering: bool,
|
||||
|
@ -183,7 +183,7 @@ fn on_tick(ctx: EventCtx<SimulateNpcs, OnTick>) {
|
||||
match npc.controller.activity {
|
||||
// If steering, the NPC controls the vehicle's motion
|
||||
Some(NpcActivity::Goto(target, speed_factor)) if riding.steering => {
|
||||
let diff = target.xy() - vehicle.wpos.xy();
|
||||
let diff = target - vehicle.wpos;
|
||||
let dist2 = diff.magnitude_squared();
|
||||
|
||||
if dist2 > 0.5f32.powi(2) {
|
||||
@ -212,7 +212,7 @@ fn on_tick(ctx: EventCtx<SimulateNpcs, OnTick>) {
|
||||
}
|
||||
vehicle.dir = (target.xy() - vehicle.wpos.xy())
|
||||
.try_normalized()
|
||||
.unwrap_or(Vec2::unit_y());
|
||||
.unwrap_or(vehicle.dir);
|
||||
}
|
||||
},
|
||||
// When riding, other actions are disabled
|
||||
@ -294,7 +294,7 @@ fn on_tick(ctx: EventCtx<SimulateNpcs, OnTick>) {
|
||||
}
|
||||
}
|
||||
|
||||
for (_, vehicle) in data.npcs.vehicles.iter_mut() {
|
||||
for (id, vehicle) in data.npcs.vehicles.iter_mut() {
|
||||
// Try to keep ships above ground and within the map
|
||||
if matches!(vehicle.mode, SimulationMode::Simulated) {
|
||||
vehicle.wpos = vehicle
|
||||
@ -312,5 +312,12 @@ fn on_tick(ctx: EventCtx<SimulateNpcs, OnTick>) {
|
||||
),
|
||||
);
|
||||
}
|
||||
if let Some(Actor::Npc(driver)) = vehicle.driver
|
||||
&& data.npcs.npcs.get(driver).and_then(|driver| {
|
||||
Some(driver.riding.as_ref()?.vehicle != id)
|
||||
}).unwrap_or(true)
|
||||
{
|
||||
vehicle.driver = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -809,6 +809,8 @@ impl Server {
|
||||
self.state.delete_component::<Anchor>(entity);
|
||||
}
|
||||
|
||||
let mut rtsim = self.state.ecs().write_resource::<rtsim::RtSim>();
|
||||
let rtsim_entities = self.state.ecs().read_storage::<RtSimEntity>();
|
||||
// Remove NPCs that are outside the view distances of all players
|
||||
// This is done by removing NPCs in unloaded chunks
|
||||
let to_delete = {
|
||||
@ -818,9 +820,15 @@ impl Server {
|
||||
&self.state.ecs().read_storage::<comp::Pos>(),
|
||||
!&self.state.ecs().read_storage::<comp::Presence>(),
|
||||
self.state.ecs().read_storage::<Anchor>().maybe(),
|
||||
rtsim_entities.maybe(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(_, pos, _, anchor)| {
|
||||
.filter(|(_, pos, _, anchor, rtsim_entity)| {
|
||||
if rtsim_entity.map_or(false, |rtsim_entity| {
|
||||
!rtsim.can_unload_entity(*rtsim_entity)
|
||||
}) {
|
||||
return false;
|
||||
}
|
||||
let chunk_key = terrain.pos_key(pos.0.map(|e| e.floor() as i32));
|
||||
match anchor {
|
||||
Some(Anchor::Chunk(hc)) => {
|
||||
@ -835,13 +843,11 @@ impl Server {
|
||||
None => terrain.get_key_real(chunk_key).is_none(),
|
||||
}
|
||||
})
|
||||
.map(|(entity, _, _, _)| entity)
|
||||
.map(|(entity, _, _, _, _)| entity)
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
{
|
||||
let mut rtsim = self.state.ecs().write_resource::<rtsim::RtSim>();
|
||||
let rtsim_entities = self.state.ecs().read_storage::<RtSimEntity>();
|
||||
let rtsim_vehicles = self.state.ecs().read_storage::<RtSimVehicle>();
|
||||
|
||||
// Assimilate entities that are part of the real-time world simulation
|
||||
@ -856,6 +862,8 @@ impl Server {
|
||||
}
|
||||
}
|
||||
}
|
||||
drop(rtsim_entities);
|
||||
drop(rtsim);
|
||||
|
||||
// Actually perform entity deletion
|
||||
for entity in to_delete {
|
||||
|
@ -177,17 +177,23 @@ impl RtSim {
|
||||
}
|
||||
|
||||
pub fn hook_rtsim_entity_unload(&mut self, entity: RtSimEntity) {
|
||||
if let Some(npc) = self
|
||||
.state
|
||||
.get_data_mut()
|
||||
.npcs
|
||||
.get_mut(entity.0)
|
||||
.filter(|npc| npc.riding.is_none())
|
||||
{
|
||||
if let Some(npc) = self.state.get_data_mut().npcs.get_mut(entity.0) {
|
||||
npc.mode = SimulationMode::Simulated;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_unload_entity(&self, entity: RtSimEntity) -> bool {
|
||||
let data = self.state.data();
|
||||
data.npcs
|
||||
.get(entity.0)
|
||||
.and_then(|npc| {
|
||||
let riding = npc.riding.as_ref()?;
|
||||
let vehicle = data.npcs.vehicles.get(riding.vehicle)?;
|
||||
Some(matches!(vehicle.mode, SimulationMode::Simulated))
|
||||
})
|
||||
.unwrap_or(true)
|
||||
}
|
||||
|
||||
pub fn hook_rtsim_vehicle_unload(&mut self, entity: RtSimVehicle) {
|
||||
let data = self.state.get_data_mut();
|
||||
if let Some(vehicle) = data.npcs.vehicles.get_mut(entity.0) {
|
||||
|
@ -19,7 +19,7 @@ use rtsim::data::{
|
||||
npc::{Profession, SimulationMode},
|
||||
Npc, Sites,
|
||||
};
|
||||
use specs::{Join, Read, ReadExpect, ReadStorage, WriteExpect, WriteStorage};
|
||||
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, WriteExpect, WriteStorage};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tracing::error;
|
||||
use world::site::settlement::trader_loadout;
|
||||
@ -212,6 +212,7 @@ fn get_npc_entity_info(npc: &Npc, sites: &Sites, index: IndexRef) -> EntityInfo
|
||||
pub struct Sys;
|
||||
impl<'a> System<'a> for Sys {
|
||||
type SystemData = (
|
||||
Entities<'a>,
|
||||
Read<'a, DeltaTime>,
|
||||
Read<'a, Time>,
|
||||
Read<'a, TimeOfDay>,
|
||||
@ -234,6 +235,7 @@ impl<'a> System<'a> for Sys {
|
||||
fn run(
|
||||
_job: &mut Job<Self>,
|
||||
(
|
||||
entities,
|
||||
dt,
|
||||
time,
|
||||
time_of_day,
|
||||
@ -419,30 +421,40 @@ impl<'a> System<'a> for Sys {
|
||||
});
|
||||
}
|
||||
|
||||
let mut emitter = server_event_bus.emitter();
|
||||
// Synchronise rtsim NPC with entity data
|
||||
for (pos, rtsim_entity, agent) in
|
||||
(&positions, &rtsim_entities, (&mut agents).maybe()).join()
|
||||
for (entity, pos, rtsim_entity, agent) in (
|
||||
&entities,
|
||||
&positions,
|
||||
&rtsim_entities,
|
||||
(&mut agents).maybe(),
|
||||
)
|
||||
.join()
|
||||
{
|
||||
data.npcs
|
||||
.get_mut(rtsim_entity.0)
|
||||
.filter(|npc| matches!(npc.mode, SimulationMode::Loaded))
|
||||
.map(|npc| {
|
||||
// Update rtsim NPC state
|
||||
npc.wpos = pos.0;
|
||||
if let Some(npc) = data.npcs.get_mut(rtsim_entity.0) {
|
||||
match npc.mode {
|
||||
SimulationMode::Loaded => {
|
||||
// Update rtsim NPC state
|
||||
npc.wpos = pos.0;
|
||||
|
||||
// Update entity state
|
||||
if let Some(agent) = agent {
|
||||
agent.rtsim_controller.personality = npc.personality;
|
||||
agent.rtsim_controller.activity = npc.controller.activity;
|
||||
agent
|
||||
.rtsim_controller
|
||||
.actions
|
||||
.extend(std::mem::take(&mut npc.controller.actions));
|
||||
if let Some(rtsim_outbox) = &mut agent.rtsim_outbox {
|
||||
npc.inbox.append(rtsim_outbox);
|
||||
// Update entity state
|
||||
if let Some(agent) = agent {
|
||||
agent.rtsim_controller.personality = npc.personality;
|
||||
agent.rtsim_controller.activity = npc.controller.activity;
|
||||
agent
|
||||
.rtsim_controller
|
||||
.actions
|
||||
.extend(std::mem::take(&mut npc.controller.actions));
|
||||
if let Some(rtsim_outbox) = &mut agent.rtsim_outbox {
|
||||
npc.inbox.append(rtsim_outbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
SimulationMode::Simulated => {
|
||||
emitter.emit(ServerEvent::Delete(entity));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user