1use async_trait::async_trait;
2use log::info;
3use serde::{Deserialize, Serialize};
4use std::any::Any;
5use std::collections::HashMap;
6use std::fmt::{self, Display};
7use std::sync::Arc;
8use uuid::Uuid;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
12pub struct PlayerId(pub Uuid);
13
14impl PlayerId {
15 pub fn new() -> Self {
16 Self(Uuid::new_v4())
17 }
18}
19
20impl Default for PlayerId {
21 fn default() -> Self {
22 Self::new()
23 }
24}
25
26impl fmt::Display for PlayerId {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 write!(f, "{}", self.0)
29 }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
34pub struct RegionId(pub Uuid);
35
36impl RegionId {
37 pub fn new() -> Self {
38 Self(Uuid::new_v4())
39 }
40}
41
42impl Default for RegionId {
43 fn default() -> Self {
44 Self::new()
45 }
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
50pub struct EventNamespace(pub String);
51
52impl EventNamespace {
53 pub fn new(name: impl Into<String> + std::marker::Copy) -> Self {
54 Self(name.into())
55 }
56
57 pub fn plugin_default(plugin_name: &str) -> Self {
58 Self(format!("plugin.{}", plugin_name))
59 }
60}
61
62impl fmt::Display for EventNamespace {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "{}", self.0)
65 }
66}
67#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
69pub struct EventId {
70 pub namespace: EventNamespace,
71 pub event_type: String,
72}
73
74impl EventId {
75 pub fn new(namespace: EventNamespace, event_type: impl Into<String> + Clone) -> Self {
76 println!("Creating EventId with namespace: {}, event_type: {}", namespace, event_type.clone().into());
77 Self {
78 namespace,
79 event_type: event_type.into(),
80 }
81 }
82}
83
84impl fmt::Display for EventId {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 write!(f, "{}::{}", self.namespace, self.event_type)
87 }
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
92pub struct Position {
93 pub x: f64,
94 pub y: f64,
95 pub z: f64,
96}
97
98impl Position {
99 pub fn new(x: f64, y: f64, z: f64) -> Self {
100 Self { x, y, z }
101 }
102
103 pub fn distance_to(&self, other: &Position) -> f64 {
104 let dx = self.x - other.x;
105 let dy = self.y - other.y;
106 let dz = self.z - other.z;
107 (dx * dx + dy * dy + dz * dz).sqrt()
108 }
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct Player {
114 pub id: PlayerId,
115 pub name: String,
116 pub position: Position,
117 pub metadata: HashMap<String, String>,
118}
119
120impl Player {
121 pub fn new(name: impl Into<String>, position: Position) -> Self {
122 Self {
123 id: PlayerId::new(),
124 name: name.into(),
125 position,
126 metadata: HashMap::new(),
127 }
128 }
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
133#[serde(tag = "type", content = "data")]
134pub enum CoreEvent {
135 PlayerJoined { player: Player },
136 PlayerLeft { player_id: PlayerId },
137 PlayerMoved { player_id: PlayerId, old_position: Position, new_position: Position },
138 RegionChanged { region_id: RegionId },
139 CustomMessage { data: serde_json::Value },
140}
141
142pub trait GameEvent: fmt::Debug + Send + Sync + 'static {
144 fn event_type(&self) -> &'static str;
145 fn serialize(&self) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>>;
146 fn as_any(&self) -> &dyn Any;
147}
148
149impl GameEvent for CoreEvent {
150 fn event_type(&self) -> &'static str {
151 match self {
152 CoreEvent::PlayerJoined { .. } => "player_joined",
153 CoreEvent::PlayerLeft { .. } => "player_left",
154 CoreEvent::PlayerMoved { .. } => "player_moved",
155 CoreEvent::RegionChanged { .. } => "region_changed",
156 CoreEvent::CustomMessage { .. } => "custom_message",
157 }
158 }
159
160 fn serialize(&self) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
161 Ok(serde_json::to_vec(self)?)
162 }
163
164 fn as_any(&self) -> &dyn Any {
165 self
166 }
167}
168
169impl From<Box<dyn GameEvent>> for Arc<dyn GameEvent + Send + Sync> {
170 fn from(b: Box<dyn GameEvent>) -> Self {
171 let boxed: Box<dyn GameEvent + Send + Sync> = b as Box<dyn GameEvent + Send + Sync>;
173 Arc::from(boxed)
174 }
175}
176
177#[async_trait]
179pub trait ServerContext: Send + Sync {
180 async fn emit_event(&self, namespace: EventNamespace, event: Box<dyn GameEvent>) -> Result<(), ServerError>;
182
183 fn region_id(&self) -> RegionId;
185
186 async fn get_players(&self) -> Result<Vec<Player>, ServerError>;
188
189 async fn get_player(&self, id: PlayerId) -> Result<Option<Player>, ServerError>;
191
192 async fn send_to_player(&self, player_id: PlayerId, message: &[u8]) -> Result<(), ServerError>;
194
195 async fn broadcast_to_region(&self, message: &[u8]) -> Result<(), ServerError>;
197
198 fn log(&self, level: LogLevel, message: &str);
200}
201
202#[async_trait]
204pub trait Plugin: Send + Sync {
205 fn name(&self) -> &'static str;
207
208 fn version(&self) -> &'static str;
210
211 async fn pre_initialize(&mut self, context: &dyn ServerContext) -> Result<(), PluginError>;
213
214 async fn initialize(&mut self, context: &(dyn ServerContext + 'static)) -> Result<(), PluginError> {
216 info!("Initializing plugin: {} v{}", self.name(), self.version());
217 Ok(())
218 }
219
220 async fn handle_event(&mut self, event_id: &EventId, event: &dyn GameEvent, context: &dyn ServerContext) -> Result<(), PluginError>;
222
223 fn subscribed_events(&self) -> Vec<EventId>;
225
226 async fn shutdown(&mut self, context: &dyn ServerContext) -> Result<(), PluginError>;
228}
229
230#[repr(C)]
232pub struct PluginOpaque;
233
234pub type PluginCreateFn = unsafe extern "C" fn() -> *mut PluginOpaque;
236
237#[derive(thiserror::Error, Debug)]
239pub enum ServerError {
240 #[error("Network error: {0}")]
241 Network(String),
242 #[error("Serialization error: {0}")]
243 Serialization(String),
244 #[error("Player not found: {0}")]
245 PlayerNotFound(PlayerId),
246 #[error("Region error: {0}")]
247 Region(String),
248 #[error("Plugin error: {0}")]
249 Plugin(#[from] PluginError),
250 #[error("Internal error: {0}")]
251 Internal(String),
252}
253
254#[derive(thiserror::Error, Debug)]
256pub enum PluginError {
257 #[error("Plugin initialization failed: {0}")]
258 InitializationFailed(String),
259 #[error("Plugin execution error: {0}")]
260 ExecutionError(String),
261 #[error("Plugin configuration error: {0}")]
262 ConfigurationError(String),
263 #[error("Plugin dependency error: {0}")]
264 DependencyError(String),
265}
266
267#[derive(Debug, Clone, Copy)]
269pub enum LogLevel {
270 Error,
271 Warn,
272 Info,
273 Debug,
274 Trace,
275}
276
277#[derive(Debug, Clone, Serialize, Deserialize)]
279#[serde(tag = "type", content = "payload")]
280pub enum NetworkMessage {
281 PlayerJoin { name: String },
282 PlayerMove { position: Position },
283 PlayerLeave,
284 GameData { data: serde_json::Value },
285 PluginMessage { plugin: String, data: serde_json::Value },
286}
287
288#[derive(Debug, Clone)]
290pub struct ConnectionInfo {
291 pub player_id: PlayerId,
292 pub remote_addr: std::net::SocketAddr,
293 pub connected_at: std::time::SystemTime,
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
298pub struct RegionBounds {
299 pub min_x: f64,
300 pub max_x: f64,
301 pub min_y: f64,
302 pub max_y: f64,
303 pub min_z: f64,
304 pub max_z: f64,
305}
306
307impl RegionBounds {
308 pub fn contains(&self, position: &Position) -> bool {
309 position.x >= self.min_x && position.x <= self.max_x &&
310 position.y >= self.min_y && position.y <= self.max_y &&
311 position.z >= self.min_z && position.z <= self.max_z
312 }
313}