forked from feather-rs/feather
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlib.rs
More file actions
151 lines (131 loc) · 4.58 KB
/
Copy pathlib.rs
File metadata and controls
151 lines (131 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#![forbid(unsafe_code)]
extern crate nalgebra_glm as glm;
mod broadcasters;
mod chat;
mod join;
mod packet_handlers;
mod view;
use feather_core::inventory::{Inventory, InventoryType};
use feather_core::items::{Item, ItemStack};
use feather_core::network::packets::{PlayerInfo, PlayerInfoAction, SpawnPlayer};
use feather_core::network::Packet;
use feather_core::text::Text;
use feather_core::util::{Gamemode, Position};
use feather_server_network::NewClientInfo;
use feather_server_types::{
ChunkHolder, CreationPacketCreator, EntityId, EntitySpawnEvent, Game, HeldItem,
InventoryUpdateEvent, LastKnownPositions, Name, Network, Player, PlayerJoinEvent,
PreviousPosition, ProfileProperties, SpawnPacketCreator, Uuid,
};
use feather_server_util::degrees_to_stops;
use fecs::{Entity, EntityRef, World};
pub use broadcasters::*;
pub use chat::*;
pub use join::*;
pub use packet_handlers::*;
use std::sync::atomic::Ordering;
pub use view::*;
pub const PLAYER_INVENTORY_SIZE: u32 = 46;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ItemTimedUse {
pub tick_start: u64,
}
/// Creates a new player from the given `NewClientInfo`.
///
/// This function also triggers events for the player join.
pub fn create(game: &mut Game, world: &mut World, info: NewClientInfo) -> Entity {
// TODO: blocked on https://github.com/TomGillen/legion/issues/36
let entity = info.entity;
world.add(entity, EntityId(entity::new_id())).unwrap();
world.add(entity, info.position).unwrap();
world.add(entity, PreviousPosition(info.position)).unwrap();
world.add(entity, info.uuid).unwrap();
world
.add(
entity,
Network {
tx: info.sender,
rx: info.receiver.into(),
},
)
.unwrap();
world.add(entity, info.ip).unwrap();
world.add(entity, ProfileProperties(info.profile)).unwrap();
world.add(entity, Name(info.username)).unwrap();
world.add(entity, ChunkHolder::default()).unwrap();
world.add(entity, LastKnownPositions::default()).unwrap();
world
.add(entity, SpawnPacketCreator(&create_spawn_packet))
.unwrap();
world
.add(entity, CreationPacketCreator(&create_initialization_packet))
.unwrap();
world
.add(entity, Gamemode::from_id(info.data.gamemode as u8))
.unwrap();
let items = info.data.inventory.iter().map(|slot| {
(
slot.slot as usize,
ItemStack::new(
Item::from_identifier(&slot.item).unwrap_or(Item::Air),
slot.count as u8,
),
)
});
let slots = info.data.inventory.iter().map(|slot| slot.slot as usize);
let mut inventory = Inventory::new(InventoryType::Player, PLAYER_INVENTORY_SIZE);
items.for_each(|(index, item)| inventory.set_item_at(index, item));
world.add(entity, inventory).unwrap();
world.add(entity, HeldItem(0)).unwrap(); // todo: load from player data
world.add(entity, Player).unwrap();
game.player_count.fetch_add(1, Ordering::SeqCst);
game.handle(world, EntitySpawnEvent { entity });
game.handle(world, PlayerJoinEvent { player: entity });
game.handle(
world,
InventoryUpdateEvent {
slots: slots.collect(),
player: entity,
},
);
entity
}
/// Function to create a `SpawnPlayer` packet to spawn the player.
fn create_spawn_packet(accessor: &EntityRef) -> Box<dyn Packet> {
let entity_id = accessor.get::<EntityId>().0;
let player_uuid = *accessor.get::<Uuid>();
let pos = *accessor.get::<Position>();
let packet = SpawnPlayer {
entity_id,
player_uuid,
x: pos.x,
y: pos.y,
z: pos.z,
yaw: degrees_to_stops(pos.yaw),
pitch: degrees_to_stops(pos.pitch),
metadata: Default::default(),
};
Box::new(packet)
}
/// Function to create a `PlayerInfo` packet to broadcast when the player joins.
fn create_initialization_packet(accessor: &EntityRef) -> Box<dyn Packet> {
let name = accessor.get::<Name>();
let props = accessor.get::<ProfileProperties>();
let uuid = *accessor.get::<Uuid>();
let props = props
.0
.iter()
.map(|prop| {
(
prop.name.clone(),
prop.value.clone(),
prop.signature.clone(),
)
})
.collect::<Vec<_>>();
let display_name = Text::of(name.0.clone()).into();
let action =
PlayerInfoAction::AddPlayer(name.0.clone(), props, Gamemode::Creative, 50, display_name);
let packet = PlayerInfo { action, uuid };
Box::new(packet)
}