Add basis for projectiles

But we have no controller action to spawn them yet
This commit is contained in:
timokoesters
2019-08-25 14:27:17 +02:00
parent 814e858720
commit 3258fa3a3c
2 changed files with 125 additions and 73 deletions

View File

@ -22,6 +22,7 @@ pub enum ServerEvent {
cause: comp::HealthSource, cause: comp::HealthSource,
}, },
Respawn(EcsEntity), Respawn(EcsEntity),
Shoot(EcsEntity),
} }
pub struct EventBus<E> { pub struct EventBus<E> {

View File

@ -87,7 +87,9 @@ impl Server {
state state
.ecs_mut() .ecs_mut()
.add_resource(SpawnPoint(Vec3::new(16_384.0, 16_384.0, 512.0))); .add_resource(SpawnPoint(Vec3::new(16_384.0, 16_384.0, 512.0)));
state.ecs_mut().add_resource(EventBus::<ServerEvent>::default()); state
.ecs_mut()
.add_resource(EventBus::<ServerEvent>::default());
// Set starting time for the server. // Set starting time for the server.
state.ecs_mut().write_resource::<TimeOfDay>().0 = settings.start_time; state.ecs_mut().write_resource::<TimeOfDay>().0 = settings.start_time;
@ -176,6 +178,22 @@ impl Server {
//.with(comp::LightEmitter::default()) //.with(comp::LightEmitter::default())
} }
/// Build a projectile
pub fn create_projectile(
state: &mut State,
pos: comp::Pos,
vel: comp::Vel,
body: comp::Body,
) -> EcsEntityBuilder {
state
.ecs_mut()
.create_entity_synced()
.with(pos)
.with(vel)
.with(comp::Ori(Vec3::unit_y()))
.with(body)
}
pub fn create_player_character( pub fn create_player_character(
state: &mut State, state: &mut State,
entity: EcsEntity, entity: EcsEntity,
@ -215,70 +233,95 @@ impl Server {
/// Handle events coming through via the event bus /// Handle events coming through via the event bus
fn handle_events(&mut self) { fn handle_events(&mut self) {
let clients = &mut self.clients; let events = self
.state
let events = self.state.ecs().read_resource::<EventBus<ServerEvent>>().recv_all(); .ecs()
.read_resource::<EventBus<ServerEvent>>()
.recv_all();
for event in events { for event in events {
let ecs = self.state.ecs_mut(); let state = &mut self.state;
let mut todo_remove = None; let clients = &mut self.clients;
{
let terrain = ecs.read_resource::<TerrainMap>();
let mut block_change = ecs.write_resource::<BlockChange>();
let mut stats = ecs.write_storage::<comp::Stats>();
let mut positions = ecs.write_storage::<comp::Pos>();
let mut velocities = ecs.write_storage::<comp::Vel>();
let mut force_updates = ecs.write_storage::<comp::ForceUpdate>();
match event { match event {
ServerEvent::LandOnGround { entity, vel } => { ServerEvent::LandOnGround { entity, vel } => {
if let Some(stats) = stats.get_mut(entity) { if let Some(stats) = state
let falldmg = (vel.z / 1.5 + 10.0) as i32; .ecs_mut()
if falldmg < 0 { .write_storage::<comp::Stats>()
stats.health.change_by(falldmg, comp::HealthSource::World); .get_mut(entity)
} {
let falldmg = (vel.z / 1.5 + 10.0) as i32;
if falldmg < 0 {
stats.health.change_by(falldmg, comp::HealthSource::World);
} }
} }
ServerEvent::Explosion { pos, radius } => { }
const RAYS: usize = 500;
for _ in 0..RAYS { ServerEvent::Explosion { pos, radius } => {
let dir = Vec3::new( const RAYS: usize = 500;
rand::random::<f32>() - 0.5,
rand::random::<f32>() - 0.5,
rand::random::<f32>() - 0.5,
)
.normalized();
let _ = terrain for _ in 0..RAYS {
.ray(pos, pos + dir * radius) let dir = Vec3::new(
.until(|_| rand::random::<f32>() < 0.05) rand::random::<f32>() - 0.5,
.for_each(|pos| block_change.set(pos, Block::empty())) rand::random::<f32>() - 0.5,
.cast(); rand::random::<f32>() - 0.5,
} )
.normalized();
let ecs = state.ecs_mut();
let mut block_change = ecs.write_resource::<BlockChange>();
let _ = ecs
.read_resource::<TerrainMap>()
.ray(pos, pos + dir * radius)
.until(|_| rand::random::<f32>() < 0.05)
.for_each(|pos| block_change.set(pos, Block::empty()))
.cast();
} }
ServerEvent::Die { entity, cause } => { }
// Chat message
if let Some(player) = ecs.read_storage::<comp::Player>().get(entity) {
let msg = if let comp::HealthSource::Attack { by } = cause {
ecs.entity_from_uid(by.into()).and_then(|attacker| {
ecs.read_storage::<comp::Player>().get(attacker).map(
|attacker_alias| {
format!(
"{} was killed by {}",
&player.alias, &attacker_alias.alias
)
},
)
})
} else {
None
}
.unwrap_or(format!("{} died", &player.alias));
clients.notify_registered(ServerMsg::kill(msg)); ServerEvent::Shoot(entity) => {
let pos = state
.ecs()
.read_storage::<comp::Pos>()
.get(entity)
.unwrap()
.0;
Self::create_projectile(
state,
comp::Pos(pos),
comp::Vel(Vec3::new(0.0, 100.0, 3.0)),
comp::Body::Object(comp::object::Body::Bomb),
)
.build();
}
ServerEvent::Die { entity, cause } => {
let ecs = state.ecs_mut();
// Chat message
if let Some(player) = ecs.read_storage::<comp::Player>().get(entity) {
let msg = if let comp::HealthSource::Attack { by } = cause {
ecs.entity_from_uid(by.into()).and_then(|attacker| {
ecs.read_storage::<comp::Player>().get(attacker).map(
|attacker_alias| {
format!(
"{} was killed by {}",
&player.alias, &attacker_alias.alias
)
},
)
})
} else {
None
} }
.unwrap_or(format!("{} died", &player.alias));
clients.notify_registered(ServerMsg::kill(msg));
}
{
// Give EXP to the client // Give EXP to the client
let mut stats = ecs.write_storage::<comp::Stats>();
if let Some(entity_stats) = stats.get(entity).cloned() { if let Some(entity_stats) = stats.get(entity).cloned() {
if let comp::HealthSource::Attack { by } = cause { if let comp::HealthSource::Attack { by } = cause {
ecs.entity_from_uid(by.into()).map(|attacker| { ecs.entity_from_uid(by.into()).map(|attacker| {
@ -292,29 +335,37 @@ impl Server {
}); });
} }
} }
if let Some(client) = clients.get_mut(&entity) {
let _ = velocities.insert(entity, comp::Vel(Vec3::zero()));
let _ = force_updates.insert(entity, comp::ForceUpdate);
client.force_state(ClientState::Dead);
} else {
todo_remove = Some(entity.clone());
}
} }
ServerEvent::Respawn(entity) => {
// Only clients can respawn if let Some(client) = clients.get_mut(&entity) {
if let Some(client) = clients.get_mut(&entity) { let _ = ecs.write_storage().insert(entity, comp::Vel(Vec3::zero()));
client.allow_state(ClientState::Character); let _ = ecs.write_storage().insert(entity, comp::ForceUpdate);
stats.get_mut(entity).map(|stats| stats.revive()); client.force_state(ClientState::Dead);
positions.get_mut(entity).map(|pos| pos.0.z += 20.0); } else {
let _ = force_updates.insert(entity, comp::ForceUpdate); let _ = state.ecs_mut().delete_entity_synced(entity);
}
} }
} }
}
if let Some(entity) = todo_remove { ServerEvent::Respawn(entity) => {
let _ = ecs.delete_entity_synced(entity); // Only clients can respawn
if let Some(client) = clients.get_mut(&entity) {
client.allow_state(ClientState::Character);
state
.ecs_mut()
.write_storage::<comp::Stats>()
.get_mut(entity)
.map(|stats| stats.revive());
state
.ecs_mut()
.write_storage::<comp::Pos>()
.get_mut(entity)
.map(|pos| pos.0.z += 20.0);
let _ = state
.ecs_mut()
.write_storage()
.insert(entity, comp::ForceUpdate);
}
}
} }
} }
} }