veloren/server/src/events/entity_creation.rs

258 lines
7.1 KiB
Rust
Raw Normal View History

use crate::{client::Client, sys, Server, StateExt};
use common::{
character::CharacterId,
comp::{
2020-12-04 22:24:56 +00:00
self,
2021-01-18 22:58:56 +00:00
aura::{Aura, AuraKind, AuraTarget},
2020-12-04 22:24:56 +00:00
beam,
buff::{BuffCategory, BuffData, BuffKind, BuffSource},
inventory::loadout::Loadout,
shockwave, Agent, Alignment, Body, Health, HomeChunk, Inventory, Item, ItemDrop,
LightEmitter, Object, Ori, Poise, Pos, Projectile, Scale, SkillSet, Stats, Vel,
WaypointArea,
},
2020-07-31 17:16:20 +00:00
outcome::Outcome,
rtsim::RtSimEntity,
uid::Uid,
2020-11-23 15:39:03 +00:00
util::Dir,
2020-02-16 20:04:06 +00:00
};
use common_net::{msg::ServerGeneral, sync::WorldSyncExt};
2020-02-16 20:04:06 +00:00
use specs::{Builder, Entity as EcsEntity, WorldExt};
2020-12-04 22:24:56 +00:00
use std::time::Duration;
2020-02-16 20:04:06 +00:00
use vek::{Rgb, Vec3};
pub fn handle_initialize_character(
server: &mut Server,
entity: EcsEntity,
character_id: CharacterId,
) {
server.state.initialize_character_data(entity, character_id);
}
pub fn handle_loaded_character_data(
2020-02-16 20:04:06 +00:00
server: &mut Server,
entity: EcsEntity,
2020-11-03 00:12:49 +00:00
loaded_components: (
comp::Body,
comp::Stats,
comp::SkillSet,
2020-11-03 00:12:49 +00:00
comp::Inventory,
Option<comp::Waypoint>,
),
2020-02-16 20:04:06 +00:00
) {
2020-06-25 18:50:04 +00:00
server
.state
.update_character_data(entity, loaded_components);
sys::subscription::initialize_region_subscription(server.state.ecs(), entity);
2020-02-16 20:04:06 +00:00
}
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
2020-02-16 20:04:06 +00:00
pub fn handle_create_npc(
server: &mut Server,
pos: Pos,
stats: Stats,
skill_set: SkillSet,
health: Health,
poise: Poise,
loadout: Loadout,
2020-02-16 20:04:06 +00:00
body: Body,
2020-07-05 12:39:28 +00:00
agent: impl Into<Option<Agent>>,
2020-02-16 20:04:06 +00:00
alignment: Alignment,
scale: Scale,
drop_item: Option<Item>,
home_chunk: Option<HomeChunk>,
rtsim_entity: Option<RtSimEntity>,
2020-02-16 20:04:06 +00:00
) {
let inventory = Inventory::new_with_loadout(loadout);
let entity = server
2020-02-16 20:04:06 +00:00
.state
.create_npc(pos, stats, skill_set, health, poise, inventory, body)
2020-02-16 20:04:06 +00:00
.with(scale)
.with(alignment);
2020-07-05 12:39:28 +00:00
let entity = if let Some(agent) = agent.into() {
entity.with(agent)
} else {
entity
};
let entity = if let Some(drop_item) = drop_item {
entity.with(ItemDrop(drop_item))
} else {
entity
};
let entity = if let Some(home_chunk) = home_chunk {
entity.with(home_chunk)
} else {
entity
};
let entity = if let Some(rtsim_entity) = rtsim_entity {
entity.with(rtsim_entity)
} else {
entity
};
let new_entity = entity.build();
// Add to group system if a pet
if let comp::Alignment::Owned(owner_uid) = alignment {
let state = server.state();
let clients = state.ecs().read_storage::<Client>();
let uids = state.ecs().read_storage::<Uid>();
let mut group_manager = state.ecs().write_resource::<comp::group::GroupManager>();
if let Some(owner) = state.ecs().entity_from_uid(owner_uid.into()) {
group_manager.new_pet(
new_entity,
owner,
&mut state.ecs().write_storage(),
&state.ecs().entities(),
&state.ecs().read_storage(),
&uids,
&mut |entity, group_change| {
clients
.get(entity)
.and_then(|c| {
group_change
.try_map(|e| uids.get(e).copied())
.map(|g| (g, c))
})
.map(|(g, c)| {
c.send_fallible(ServerGeneral::GroupUpdate(g));
});
},
);
}
} else if let Some(group) = match alignment {
comp::Alignment::Wild => None,
comp::Alignment::Passive => None,
comp::Alignment::Enemy => Some(comp::group::ENEMY),
comp::Alignment::Npc | comp::Alignment::Tame => Some(comp::group::NPC),
comp::Alignment::Owned(_) => unreachable!(),
} {
let _ = server.state.ecs().write_storage().insert(new_entity, group);
}
2020-02-16 20:04:06 +00:00
}
#[allow(clippy::too_many_arguments)]
pub fn handle_create_ship(
server: &mut Server,
pos: comp::Pos,
ship: comp::ship::Body,
mountable: bool,
agent: Option<Agent>,
rtsim_entity: Option<RtSimEntity>,
) {
let mut entity = server.state.create_ship(pos, ship, mountable);
if let Some(agent) = agent {
entity = entity.with(agent);
}
if let Some(rtsim_entity) = rtsim_entity {
entity = entity.with(rtsim_entity);
}
entity.build();
}
#[allow(clippy::too_many_arguments)]
2020-02-16 20:04:06 +00:00
pub fn handle_shoot(
server: &mut Server,
entity: EcsEntity,
dir: Dir,
2020-02-16 20:04:06 +00:00
body: Body,
light: Option<LightEmitter>,
projectile: Projectile,
speed: f32,
object: Option<Object>,
2020-02-16 20:04:06 +00:00
) {
let state = server.state_mut();
let mut pos = if let Some(pos) = state.ecs().read_storage::<Pos>().get(entity) {
pos.0
} else {
return;
};
2020-02-16 20:04:06 +00:00
let vel = *dir * speed
+ state
.ecs()
.read_storage::<Vel>()
.get(entity)
.map_or(Vec3::zero(), |v| v.0);
2020-07-31 17:16:20 +00:00
// Add an outcome
2020-08-06 16:41:43 +00:00
state
.ecs()
.write_resource::<Vec<Outcome>>()
.push(Outcome::ProjectileShot { pos, body, vel });
2020-07-31 17:16:20 +00:00
let eye_height =
state
.ecs()
.read_storage::<comp::Body>()
.get(entity)
.map_or(0.0, |b| match b {
comp::Body::Golem(_) => b.height() * 0.45,
_ => b.eye_height(),
});
2020-06-13 08:21:47 +00:00
pos.z += eye_height;
2020-02-16 20:04:06 +00:00
2020-07-31 17:16:20 +00:00
let mut builder = state.create_projectile(Pos(pos), Vel(vel), body, projectile);
2020-02-16 20:04:06 +00:00
if let Some(light) = light {
builder = builder.with(light)
}
if let Some(object) = object {
builder = builder.with(object)
}
2020-02-16 20:04:06 +00:00
builder.build();
}
pub fn handle_shockwave(
server: &mut Server,
properties: shockwave::Properties,
pos: Pos,
ori: Ori,
) {
2020-08-08 20:53:55 +00:00
let state = server.state_mut();
state.create_shockwave(properties, pos, ori).build();
2020-08-08 20:53:55 +00:00
}
pub fn handle_beam(server: &mut Server, properties: beam::Properties, pos: Pos, ori: Ori) {
let state = server.state_mut();
let ecs = state.ecs();
ecs.write_resource::<Vec<Outcome>>().push(Outcome::Beam {
pos: pos.0,
specifier: properties.specifier,
});
state.create_beam(properties, pos, ori).build();
}
2020-02-16 20:04:06 +00:00
pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
server
.state
2020-02-16 20:04:06 +00:00
.create_object(Pos(pos), comp::object::Body::CampfireLit)
.with(LightEmitter {
2020-08-30 20:10:56 +00:00
col: Rgb::new(1.0, 0.3, 0.1),
strength: 5.0,
flicker: 1.0,
animated: true,
2020-02-16 20:04:06 +00:00
})
.with(WaypointArea::default())
.with(comp::Mass(10_f32.powi(10)))
.with(comp::Auras::new(vec![Aura::new(
2020-12-04 22:24:56 +00:00
AuraKind::Buff {
kind: BuffKind::CampfireHeal,
data: BuffData::new(0.02, Some(Duration::from_secs(1))),
2020-12-04 22:24:56 +00:00
category: BuffCategory::Natural,
source: BuffSource::World,
},
5.0,
None,
2021-01-18 22:58:56 +00:00
AuraTarget::All,
)]))
2020-02-16 20:04:06 +00:00
.build();
}