Skip to content

Commit

Permalink
Handle arrow shooting - resolves #101 (#121)
Browse files Browse the repository at this point in the history
  • Loading branch information
aramperes authored and caelunshun committed Sep 9, 2019
1 parent d9f9738 commit 02dab41
Show file tree
Hide file tree
Showing 14 changed files with 423 additions and 9 deletions.
3 changes: 3 additions & 0 deletions codegen/src/entity_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ enum EntryType {
String,
Slot,
Boolean,
OptUuid,
}

impl Parse for EntryType {
Expand All @@ -134,6 +135,7 @@ impl EntryType {
EntryType::String => "String",
EntryType::Slot => "Slot",
EntryType::Boolean => "bool",
EntryType::OptUuid => "OptUuid",
}
}

Expand All @@ -145,6 +147,7 @@ impl EntryType {
"String" => EntryType::String,
"bool" => EntryType::Boolean,
"Slot" => EntryType::Slot,
"OptUuid" => EntryType::OptUuid,
_ => panic!("Invalid entry type {}", ty),
}
}
Expand Down
10 changes: 9 additions & 1 deletion core/src/entitymeta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use crate::Slot;
use hashbrown::HashMap;
use uuid::Uuid;

type OptUuid = Option<Uuid>;

#[derive(Clone, Debug, PartialEq)]
pub enum MetaEntry {
Byte(i8),
Expand All @@ -23,7 +25,7 @@ pub enum MetaEntry {
Position(BlockPosition),
OptPosition(Option<BlockPosition>),
Direction(Direction),
OptUuid(Option<Uuid>),
OptUuid(OptUuid),
OptBlockId(Option<i32>),
Nbt, // TODO
Particle, // TODO
Expand Down Expand Up @@ -92,6 +94,12 @@ impl IntoMetaEntry for f32 {
}
}

impl IntoMetaEntry for OptUuid {
fn into_meta_entry(&self) -> MetaEntry {
MetaEntry::OptUuid(*self)
}
}

#[derive(Clone)]
pub struct EntityMetadata {
values: HashMap<u8, MetaEntry>,
Expand Down
6 changes: 3 additions & 3 deletions core/src/network/packet/implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ impl Packet for PlayerDigging {
2 => PlayerDiggingStatus::FinishedDigging,
3 => PlayerDiggingStatus::DropItemStack,
4 => PlayerDiggingStatus::DropItem,
5 => PlayerDiggingStatus::ShootArrow,
5 => PlayerDiggingStatus::ConsumeItem,
6 => PlayerDiggingStatus::SwapItemInHand,
_ => return Err(()),
}
Expand Down Expand Up @@ -472,7 +472,7 @@ pub enum PlayerDiggingStatus {
FinishedDigging = 2,
DropItemStack = 3,
DropItem = 4,
ShootArrow = 5,
ConsumeItem = 5,
SwapItemInHand = 6,
}

Expand Down Expand Up @@ -788,7 +788,7 @@ pub struct Pong {

// PLAY
#[allow(clippy::too_many_arguments)]
#[derive(Default, AsAny, new, Packet, Clone)]
#[derive(Default, AsAny, new, Packet, Clone, Debug)]
pub struct SpawnObject {
pub entity_id: VarInt,
pub object_uuid: Uuid,
Expand Down
67 changes: 67 additions & 0 deletions server/src/entity/arrow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use shrev::EventChannel;
use specs::{
Component, Entity, NullStorage, Read, ReadStorage, ReaderId, System, SystemData, World,
};

use feather_core::{Item, Position};

use crate::entity::NamedComponent;
use crate::player::PLAYER_EYE_HEIGHT;
use crate::util::Util;

/// Component for arrow entities.
#[derive(Default)]
pub struct ArrowComponent;

impl Component for ArrowComponent {
type Storage = NullStorage<Self>;
}

/// Event triggered when arrow is shot.
#[derive(Debug, Clone)]
pub struct ShootArrowEvent {
pub arrow_type: Item,
pub shooter: Option<Entity>,
pub position: Position,
pub critical: bool,
}

#[derive(Default)]
pub struct ShootArrowSystem {
reader: Option<ReaderId<ShootArrowEvent>>,
}

impl<'a> System<'a> for ShootArrowSystem {
type SystemData = (
Read<'a, Util>,
Read<'a, EventChannel<ShootArrowEvent>>,
ReadStorage<'a, NamedComponent>,
);

fn run(&mut self, data: Self::SystemData) {
let (util, shoot_arrow_events, nameds) = data;

for event in shoot_arrow_events.read(self.reader.as_mut().unwrap()) {
let mut pos = event.position
+ glm::vec3(0.0, PLAYER_EYE_HEIGHT, 0.0)
+ event.position.direction() * 1.5;
pos.on_ground = false;

// TODO: Scale velocity based on power
let velocity = pos.direction();

let shooter = match event.shooter {
Some(e) => Some(nameds.get(e).unwrap().uuid),
None => None,
};

util.spawn_arrow(pos, velocity, event.critical, shooter);
}
}

fn setup(&mut self, world: &mut World) {
Self::SystemData::setup(world);

self.reader = Some(world.fetch_mut::<EventChannel<_>>().register_reader());
}
}
18 changes: 18 additions & 0 deletions server/src/entity/broadcast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,24 @@ fn packet_to_spawn_entity(

Box::new(packet)
}
EntityType::Arrow => {
let packet = SpawnObject {
entity_id: entity.id() as i32,
object_uuid: Uuid::new_v4(),
ty: 60,
x: position.current.x,
y: position.current.y,
z: position.current.z,
pitch: degrees_to_stops(position.current.pitch),
yaw: degrees_to_stops(position.current.yaw),
data: 1, // TODO: Shooter entity ID
velocity_x,
velocity_y,
velocity_z,
};

Box::new(packet)
}
_ => unimplemented!(),
}
}
Expand Down
18 changes: 18 additions & 0 deletions server/src/entity/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use specs::{
BitSet, Component, Entities, FlaggedStorage, Join, Read, ReaderId, System, VecStorage,
WriteStorage,
};
use uuid::Uuid;

type OptUuid = Option<Uuid>;

bitflags! {
pub struct EntityBitMask: u8 {
Expand All @@ -23,6 +26,14 @@ bitflags! {
}
}

bitflags! {
#[derive(Default)]
pub struct ArrowBitMask: u8 {
const CRITICAL = 0x01;
const NO_CLIP = 0x02;
}
}

entity_metadata! {
Metadata,
Entity {
Expand All @@ -47,6 +58,13 @@ entity_metadata! {
displayed_skin_parts: u8() = 13,
main_hand: u8() = 14,
},
Arrow: Entity {
arrow_bit_mask: u8() = 6,
shooter: OptUuid() = 7,
},
TippedArrow: Arrow {
color: VarInt() = 8,
},
}

impl Component for Metadata {
Expand Down
6 changes: 5 additions & 1 deletion server/src/entity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! and `PlayerComponent`. In the future, will also
//! provide entity-specific components and systems.
mod arrow;
mod broadcast;
mod chunk;
mod component;
Expand All @@ -14,8 +15,9 @@ mod types;
use crate::systems::{
CHUNK_CROSS, CHUNK_ENTITIES_UPDATE, ENTITY_DESTROY, ENTITY_DESTROY_BROADCAST,
ENTITY_METADATA_BROADCAST, ENTITY_MOVE_BROADCAST, ENTITY_SEND, ENTITY_SPAWN_BROADCAST,
ENTITY_VELOCITY_BROADCAST, ITEM_COLLECT, ITEM_MERGE, ITEM_SPAWN, JOIN_BROADCAST,
ENTITY_VELOCITY_BROADCAST, ITEM_COLLECT, ITEM_MERGE, ITEM_SPAWN, JOIN_BROADCAST, SHOOT_ARROW,
};
pub use arrow::{ArrowComponent, ShootArrowEvent};
pub use broadcast::EntitySendSystem;
pub use broadcast::EntitySender;
pub use broadcast::EntitySpawnEvent;
Expand All @@ -28,6 +30,7 @@ pub use metadata::{EntityBitMask, Metadata};
pub use movement::broadcast_entity_movement;
pub use types::EntityType;

use crate::entity::arrow::ShootArrowSystem;
use crate::entity::destroy::EntityDestroyBroadcastSystem;
use crate::entity::item::ItemCollectSystem;
use crate::entity::metadata::MetadataBroadcastSystem;
Expand Down Expand Up @@ -56,6 +59,7 @@ pub fn init_handlers(dispatcher: &mut DispatcherBuilder) {
ENTITY_METADATA_BROADCAST,
&[],
);
dispatcher.add(ShootArrowSystem::default(), SHOOT_ARROW, &[]);
}

pub fn init_broadcast(dispatcher: &mut DispatcherBuilder) {
Expand Down
6 changes: 6 additions & 0 deletions server/src/entity/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub enum EntityType {
Item,
ExperienceOrb,
Thunderbolt,
Arrow,
TippedArrow,
#[cfg(test)]
Test,
// TODO more...
Expand All @@ -31,6 +33,10 @@ impl EntityType {
self == EntityType::Item
}

pub fn is_arrow(self) -> bool {
self == EntityType::Arrow || self == EntityType::TippedArrow
}

pub fn is_other(self) -> bool {
self == EntityType::ExperienceOrb || self == EntityType::Thunderbolt
}
Expand Down
1 change: 1 addition & 0 deletions server/src/physics/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ fn bbox_for_type(ty: EntityType) -> Option<AABB<f64>> {
match ty {
EntityType::Item => Some(bbox(0.25, 0.25)),
EntityType::Player => Some(bbox(0.6, 1.7)),
EntityType::Arrow | EntityType::TippedArrow => Some(bbox(0.5, 0.5)),
_ => None,
}
}
Expand Down
14 changes: 13 additions & 1 deletion server/src/physics/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl<'a> System<'a> for EntityPhysicsSystem {
velocity.0.y += gravity / 4.0;
}
_ => {
let slip_multiplier = 0.6;
let slip_multiplier = slip_multiplier(*ty);
if pending_position.on_ground {
velocity.0.x *= slip_multiplier;
velocity.0.z *= slip_multiplier;
Expand All @@ -180,6 +180,14 @@ impl<'a> System<'a> for EntityPhysicsSystem {
}
}

fn slip_multiplier(ty: EntityType) -> f64 {
if ty.is_arrow() {
0.0
} else {
0.6
}
}

/// Retrieves the gravitational acceleration in blocks per tick squared
/// for a given entity type.
///
Expand All @@ -190,6 +198,8 @@ fn gravitational_acceleration(ty: EntityType) -> f64 {
-0.08
} else if ty.is_item() {
-0.04
} else if ty.is_arrow() {
-0.05
} else {
0.0
}
Expand All @@ -213,6 +223,8 @@ fn terminal_velocity(ty: EntityType) -> f32 {
fn drag_force(ty: EntityType) -> f64 {
if ty.is_living() || ty.is_item() {
0.98
} else if ty.is_arrow() {
0.99
} else {
0.0
}
Expand Down
Loading

0 comments on commit 02dab41

Please sign in to comment.