mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-04-06 15:56:18 +00:00
wip player identifiers stuff
This commit is contained in:
71
Cargo.lock
generated
71
Cargo.lock
generated
@@ -26,6 +26,21 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.75"
|
||||
@@ -106,6 +121,7 @@ dependencies = [
|
||||
"pretty_env_logger",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde-aux",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"toml",
|
||||
@@ -166,6 +182,18 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"num-traits",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.3"
|
||||
@@ -511,6 +539,29 @@ dependencies = [
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.4.0"
|
||||
@@ -1084,6 +1135,17 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-aux"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3dfe1b7eb6f9dcf011bd6fad169cdeaae75eda0d61b1a99a3f015b41b0cae39"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.192"
|
||||
@@ -1537,6 +1599,15 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.51.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
|
||||
@@ -22,6 +22,7 @@ futures = "0.3.29"
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "*"
|
||||
serde-aux = "4.2.0"
|
||||
|
||||
toml = "0.5"
|
||||
flate2 = "1.0"
|
||||
|
||||
@@ -7,6 +7,7 @@ end
|
||||
|
||||
function onPlayerAuthenticated(joined_name, role, is_guest, identifiers)
|
||||
print("hi welcome mista " .. joined_name)
|
||||
print("u a guest? " .. tostring(is_guest))
|
||||
|
||||
print("current players:")
|
||||
for id, name in pairs(MP.GetPlayers()) do
|
||||
@@ -16,11 +17,22 @@ function onPlayerAuthenticated(joined_name, role, is_guest, identifiers)
|
||||
|
||||
print("Player count: " .. MP.GetPlayerCount())
|
||||
|
||||
return 0 -- 0 = do not block
|
||||
for key, value in pairs(identifiers) do
|
||||
print(key .. ": " .. value)
|
||||
end
|
||||
|
||||
-- print("now trying with getting it ourself")
|
||||
-- for key, value in pairs(MP.GetPlayerIdentifiers(pid)) do
|
||||
-- print(key .. ": " .. value)
|
||||
-- end
|
||||
|
||||
return 0 -- 0 = do not cancel
|
||||
end
|
||||
|
||||
function onPlayerDisconnect(pid)
|
||||
print("Player with PID " .. pid .. " has left!")
|
||||
function onPlayerDisconnect(pid, name, identifiers)
|
||||
-- Player is already gone here, so for now, player data is no longer
|
||||
-- requestable for player with the id `pid`
|
||||
print("Player " .. name .. " (" .. pid .. ") has left!")
|
||||
end
|
||||
|
||||
MP.RegisterEventHandler("onInit", "onPluginLoaded")
|
||||
|
||||
@@ -14,5 +14,6 @@ pub async fn authentication_request<R: DeserializeOwned>(
|
||||
.json(&map)
|
||||
.send()
|
||||
.await?;
|
||||
// panic!("json: {:?}", resp.text().await);
|
||||
Ok(resp.json().await?)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ use tokio::task::JoinHandle;
|
||||
use nalgebra::*;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde_aux::prelude::*;
|
||||
|
||||
use super::backend::*;
|
||||
use super::car::*;
|
||||
@@ -39,6 +40,8 @@ pub enum ClientState {
|
||||
|
||||
#[derive(Deserialize, Debug, PartialEq, Clone)]
|
||||
pub struct UserData {
|
||||
#[serde(deserialize_with = "deserialize_number_from_string")]
|
||||
pub uid: u64,
|
||||
pub createdAt: String,
|
||||
pub guest: bool,
|
||||
pub roles: String,
|
||||
@@ -107,78 +110,6 @@ impl Client {
|
||||
pub async fn authenticate(&mut self, config: &super::Config) -> anyhow::Result<bool> {
|
||||
debug!("Authenticating client {}...", self.id);
|
||||
|
||||
self.socket.readable().await?;
|
||||
// let mut tmp = vec![0u8; 1];
|
||||
// while self.socket.peek(&mut tmp).await? == 0 {}
|
||||
// // Authentication works a little differently than normal
|
||||
// // Not sure why, but the BeamMP source code shows they
|
||||
// // also only read a single byte during authentication
|
||||
// let code = self.read_raw(1).await?[0];
|
||||
// debug!("code: '{}' / {}", code as char, code);
|
||||
// match code as char {
|
||||
// 'C' => {
|
||||
//
|
||||
// break 'waiting_for_c;
|
||||
// }
|
||||
// 'D' => {
|
||||
// // The download sequence is so awful
|
||||
// // It currently requires us to track what the next file is that
|
||||
// // we need to provide, which is hard to do with the current
|
||||
// // server design.
|
||||
// // I think I will simply keep a counter around that will
|
||||
// // track what the next mod is per client.
|
||||
// // TODO: Clean this up. It also needs to be moved out of the client code IMO
|
||||
//
|
||||
// let id = self.read_raw(1).await?[0] as usize;
|
||||
// debug!("HandleDownload connection for client id: {}", id);
|
||||
//
|
||||
// let mut mod_name = {
|
||||
// let mut lock = CLIENT_MOD_PROGRESS.lock().await;
|
||||
// if lock.get(&id).is_none() { lock.insert(id, 0); }
|
||||
// let next_id = lock.get_mut(&id).unwrap();
|
||||
//
|
||||
// let bmod = &config.mods[*next_id]; // TODO: This is a bit uhh yeah
|
||||
// debug!("Mod name: {}", bmod.0);
|
||||
//
|
||||
// *next_id += 1;
|
||||
//
|
||||
// if *next_id >= config.mods.len() {
|
||||
// // I think this is where the connection should be closed, instead of after
|
||||
// // just 1 mod.
|
||||
// }
|
||||
//
|
||||
// bmod.0.clone()
|
||||
// };
|
||||
//
|
||||
// if mod_name.starts_with("/") == false {
|
||||
// mod_name = format!("/{mod_name}");
|
||||
// }
|
||||
//
|
||||
// let mod_path = format!("Resources/Client{mod_name}");
|
||||
// let file_data = std::fs::read(mod_path)?;
|
||||
//
|
||||
// let packet = RawPacket::from_data(file_data[(file_data.len()/2)..].to_vec());
|
||||
//
|
||||
// {
|
||||
// let mut lock = self.write_half.lock().await;
|
||||
// lock.writable().await?;
|
||||
// trace!("Sending packets!");
|
||||
// if let Err(e) = tcp_write_raw(lock.deref_mut(), Packet::Raw(packet)).await {
|
||||
// error!("{:?}", e);
|
||||
// }
|
||||
// trace!("Packets sent!");
|
||||
// drop(lock);
|
||||
// }
|
||||
//
|
||||
// // return Err(ClientError::IsDownloader.into());
|
||||
// return Ok(false);
|
||||
// }
|
||||
// _ => {
|
||||
// error!("Unknown code: {}", code);
|
||||
// return Err(ClientError::AuthenticateError.into());
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO: Check client version
|
||||
trace!("Client version packet");
|
||||
self.socket.readable().await?;
|
||||
@@ -354,6 +285,10 @@ impl Client {
|
||||
self.disconnect();
|
||||
}
|
||||
|
||||
pub fn get_userdata(&self) -> UserData {
|
||||
self.info.as_ref().unwrap().clone()
|
||||
}
|
||||
|
||||
// Panics when userdata is not set!
|
||||
pub fn get_name(&self) -> &str {
|
||||
&self.info.as_ref().unwrap().username
|
||||
|
||||
@@ -367,25 +367,29 @@ impl Server {
|
||||
// with the client acception runtime. If that one locks, the server won't accept
|
||||
// more clients, but it will at least still process all other clients
|
||||
let mut joined_names = Vec::new();
|
||||
if let Ok(mut clients_incoming_lock) = self.clients_incoming.try_lock() {
|
||||
if let Ok(mut clients_incoming_lock) = self.clients_incoming.try_lock() { // TODO: Why do I use try_lock here?
|
||||
if clients_incoming_lock.len() > 0 {
|
||||
trace!(
|
||||
"Accepting {} incoming clients...",
|
||||
clients_incoming_lock.len()
|
||||
);
|
||||
for i in 0..clients_incoming_lock.len() {
|
||||
let name = clients_incoming_lock[i]
|
||||
.info
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.username
|
||||
.clone();
|
||||
let (name, role, is_guest, beammp_id) = {
|
||||
let client = clients_incoming_lock[i]
|
||||
.info
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
(client.username.clone(), client.roles.clone(), client.guest, client.uid)
|
||||
};
|
||||
info!("Welcome {name}!");
|
||||
joined_names.push(name.clone());
|
||||
let mut vrx = Vec::new();
|
||||
for plugin in &self.plugins {
|
||||
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||
plugin.send_event(PluginBoundPluginEvent::CallEventHandler((ScriptEvent::OnPlayerAuthenticated { name: name.clone() }, Some(tx)))).await;
|
||||
plugin.send_event(PluginBoundPluginEvent::CallEventHandler((ScriptEvent::OnPlayerAuthenticated { name: name.clone(), role: role.clone(), is_guest, identifiers: PlayerIdentifiers {
|
||||
ip: String::from("not yet implemented"),
|
||||
beammp_id,
|
||||
} }, Some(tx)))).await;
|
||||
// TODO: This never returns, because it blocks the entire process function
|
||||
// from running, so it never manages to run the function correctly.
|
||||
// let res = rx.await.unwrap_or(Argument::Number(-1f32));
|
||||
@@ -447,7 +451,7 @@ impl Server {
|
||||
// TODO: Error handling (?)
|
||||
match event {
|
||||
ServerBoundPluginEvent::PluginLoaded => plugin.send_event(PluginBoundPluginEvent::CallEventHandler((ScriptEvent::OnPluginLoaded, None))).await,
|
||||
ServerBoundPluginEvent::RequestPlayerCount(responder) => { let _ = responder.send(PluginBoundPluginEvent::PlayerCount(self.clients.len() + self.clients_queue.len())); }
|
||||
ServerBoundPluginEvent::RequestPlayerCount(responder) => { let _ = responder.send(PluginBoundPluginEvent::PlayerCount(self.clients.len() + self.clients_queue.len())); },
|
||||
ServerBoundPluginEvent::RequestPlayers(responder) => {
|
||||
trace!("request players received");
|
||||
let mut players = HashMap::new();
|
||||
@@ -457,7 +461,17 @@ impl Server {
|
||||
trace!("sending player list...");
|
||||
let _ = responder.send(PluginBoundPluginEvent::Players(players));
|
||||
trace!("player list sent");
|
||||
}
|
||||
},
|
||||
ServerBoundPluginEvent::RequestPlayerIdentifiers((pid, responder)) => {
|
||||
if let Some(client) = self.clients.iter().find(|client| client.id == pid) {
|
||||
let _ = responder.send(PluginBoundPluginEvent::PlayerIdentifiers(PlayerIdentifiers {
|
||||
ip: String::from("not yet implemented"),
|
||||
beammp_id: client.get_userdata().uid,
|
||||
}));
|
||||
} else {
|
||||
let _ = responder.send(PluginBoundPluginEvent::None);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
@@ -498,8 +512,9 @@ impl Server {
|
||||
}
|
||||
|
||||
let id = self.clients[i].id;
|
||||
let name = self.clients[i].get_name().to_string();
|
||||
for plugin in &mut self.plugins {
|
||||
plugin.send_event(PluginBoundPluginEvent::CallEventHandler((ScriptEvent::OnPlayerDisconnect { pid: id }, None))).await;
|
||||
plugin.send_event(PluginBoundPluginEvent::CallEventHandler((ScriptEvent::OnPlayerDisconnect { pid: id, name: name.clone() }, None))).await;
|
||||
}
|
||||
|
||||
info!("Disconnecting client {}...", id);
|
||||
|
||||
@@ -137,8 +137,8 @@ impl Backend for BackendLua {
|
||||
fn call_event_handler(&mut self, event: ScriptEvent, resp: Option<oneshot::Sender<Argument>>) {
|
||||
let (event_name, args) = match event {
|
||||
ScriptEvent::OnPluginLoaded => ("onInit", vec![]),
|
||||
ScriptEvent::OnPlayerAuthenticated { name } => ("onPlayerAuth", vec![Argument::String(name)]),
|
||||
ScriptEvent::OnPlayerDisconnect { pid } => ("onPlayerDisconnect", vec![Argument::Number(pid as f32)]),
|
||||
ScriptEvent::OnPlayerAuthenticated { name, role, is_guest, identifiers } => ("onPlayerAuth", vec![Argument::String(name), Argument::String(role), Argument::Boolean(is_guest), Argument::Table(identifiers.to_map())]),
|
||||
ScriptEvent::OnPlayerDisconnect { pid, name } => ("onPlayerDisconnect", vec![Argument::Number(pid as f32), Argument::String(name)]),
|
||||
};
|
||||
|
||||
let mut ret = -1f32;
|
||||
@@ -150,11 +150,7 @@ impl Backend for BackendLua {
|
||||
let func: LuaResult<Function> = self.lua.globals().get(handler_name.clone());
|
||||
if let Ok(func) = func {
|
||||
let mapped_args = args.into_iter().map(|arg| {
|
||||
match arg {
|
||||
Argument::String(s) => if let Ok(lua_str) = self.lua.create_string(&s) { Some(Value::String(lua_str)) } else { None },
|
||||
Argument::Boolean(b) => Some(Value::Boolean(b)),
|
||||
Argument::Number(f) => Some(Value::Number(f as f64)),
|
||||
}
|
||||
arg_to_value(&self.lua, arg)
|
||||
}).filter(|v| v.is_some());
|
||||
match func.call::<_, Option<f32>>(Variadic::from_iter(mapped_args)) {
|
||||
Ok(res) => { trace!("fn ret: {:?}", ret); ret = res.unwrap_or(-1f32); }
|
||||
@@ -172,3 +168,26 @@ impl Backend for BackendLua {
|
||||
debug!("call_event_handler done");
|
||||
}
|
||||
}
|
||||
|
||||
fn arg_to_value(lua: &Lua, arg: Argument) -> Option<Value> {
|
||||
match arg {
|
||||
Argument::String(s) => if let Ok(lua_str) = lua.create_string(&s) { Some(Value::String(lua_str)) } else { None },
|
||||
Argument::Boolean(b) => Some(Value::Boolean(b)),
|
||||
Argument::Number(f) => Some(Value::Number(f as f64)),
|
||||
Argument::Integer(i) => Some(Value::Integer(i as i64)),
|
||||
Argument::Table(t) => {
|
||||
if let Ok(table) = lua.create_table() {
|
||||
for (key, value) in t {
|
||||
if let Some(v) = arg_to_value(lua, value) {
|
||||
if let Err(e) = table.set(key, v) {
|
||||
error!("[LUA] Error occured trying to put data into table: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Value::Table(table))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,23 +23,43 @@ pub enum Argument {
|
||||
String(String),
|
||||
Boolean(bool),
|
||||
Number(f32),
|
||||
Integer(i64),
|
||||
Table(HashMap<String, Argument>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PlayerIdentifiers {
|
||||
pub ip: String,
|
||||
pub beammp_id: u64,
|
||||
}
|
||||
|
||||
impl PlayerIdentifiers {
|
||||
pub fn to_map(&self) -> HashMap<String, Argument> {
|
||||
let mut m = HashMap::new();
|
||||
m.insert(String::from("ip"), Argument::String(self.ip.clone()));
|
||||
m.insert(String::from("beammp"), Argument::Integer(self.beammp_id as i64)); // TODO: Uhh we could lose data here
|
||||
m
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ScriptEvent {
|
||||
OnPluginLoaded,
|
||||
|
||||
OnPlayerAuthenticated { name: String },
|
||||
OnPlayerAuthenticated { name: String, role: String, is_guest: bool, identifiers: PlayerIdentifiers },
|
||||
|
||||
OnPlayerDisconnect { pid: u8 },
|
||||
OnPlayerDisconnect { pid: u8, name: String },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PluginBoundPluginEvent {
|
||||
None,
|
||||
|
||||
CallEventHandler((ScriptEvent, Option<oneshot::Sender<Argument>>)),
|
||||
|
||||
PlayerCount(usize),
|
||||
Players(HashMap<u8, String>),
|
||||
PlayerIdentifiers(PlayerIdentifiers),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -48,6 +68,7 @@ pub enum ServerBoundPluginEvent {
|
||||
|
||||
RequestPlayerCount(oneshot::Sender<PluginBoundPluginEvent>),
|
||||
RequestPlayers(oneshot::Sender<PluginBoundPluginEvent>),
|
||||
RequestPlayerIdentifiers((u8, oneshot::Sender<PluginBoundPluginEvent>)),
|
||||
}
|
||||
|
||||
pub struct Plugin {
|
||||
|
||||
Reference in New Issue
Block a user