You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
3.7 KiB
Rust

use crate::plugin::{create_timer, get_mod_dir, log_message, start_timer, Events, LOG_INFO};
use crate::server::main_http_thread;
use crate::server_info::ServerInfoHandle;
use std::os::raw::{c_int, c_ulonglong, c_ushort};
use std::rc::Rc;
use std::sync::{Arc, RwLock};
use tokio::runtime::Runtime;
use warp::Future;
mod plugin;
mod server;
mod server_info;
#[derive(Clone)]
struct ServerHandle(Arc<RwLock<Server>>, Rc<RwLock<Runtime>>);
extern "C" fn tick() -> c_ulonglong {
let server_handle: &mut ServerHandle = unsafe { EVENTS_INSTANCE.as_mut() }.unwrap();
server_handle.clone().with(|server| {
let timer = server.timer;
server.tick += 1;
server_handle.block_on(async {
server.info.update_players(server.tick % 20 == 0).await;
});
server.tick %= 1000;
start_timer(timer)
});
0
}
impl ServerHandle {
fn with<O>(&self, mut block: impl FnMut(&mut Server) -> O) -> O {
let mut guard = self.0.write().unwrap();
block(&mut guard)
}
fn block_on<F: Future>(&mut self, future: F) -> F::Output {
self.1.write().unwrap().block_on(future)
}
}
#[derive(Clone, Debug)]
struct Server {
info: ServerInfoHandle,
timer: c_int,
tick: u64,
}
impl Server {
fn into_handle(self, runtime: Rc<RwLock<Runtime>>) -> ServerHandle {
ServerHandle(Arc::new(RwLock::new(self)), runtime)
}
}
impl Events for ServerHandle {
fn new() -> Self {
Server {
info: ServerInfoHandle::new(),
timer: -1,
tick: 0,
}
.into_handle(Rc::new(RwLock::new(
Runtime::new().expect("Failed to create Tokio runtime"),
)))
}
fn on_any(&mut self, event_name: &str) {
log_message(
plugin::LOG_VERBOSE,
format!("Got event: {}", event_name).as_str(),
)
}
fn on_gui_action(&mut self, player_id: u16, message_box_id: i32, data: Option<&str>) {
self.clone().with(|server| {
self.block_on(async {
server
.info
.gui_action(player_id, message_box_id, data)
.await;
});
});
}
fn on_player_connect(&mut self, player_id: c_ushort) {
self.clone().with(|server| -> () {
self.block_on(async {
server.info.add_player(player_id).await;
});
})
}
fn on_player_disconnect(&mut self, player_id: c_ushort) {
self.clone().with(|server| {
self.block_on(async {
server.info.remove_player(player_id).await;
})
})
}
fn on_server_init(&mut self) {
log_message(
LOG_INFO,
format!(
concat!(
"Loaded ",
env!("CARGO_PKG_NAME"),
" ",
env!("CARGO_PKG_VERSION"),
" (pwd: {:?}, mod_dir: {})"
),
std::env::current_dir(),
get_mod_dir()
)
.as_str(),
);
}
fn on_server_post_init(&mut self) {
let mut info = {
self.with(|server| {
server.timer = create_timer(tick, 50);
log_message(
LOG_INFO,
format!("nwahttp tick timer registered with id {}", server.timer).as_str(),
);
start_timer(server.timer);
server.info.clone()
})
};
std::thread::spawn(move || {
let info_clone = info.clone();
info.block_on(async { main_http_thread(info_clone).await });
});
log_message(LOG_INFO, "Started HTTP thread");
}
}
use_events!(ServerHandle);