Skip to content

Instantly share code, notes, and snippets.

@BrettMayson
Last active December 17, 2021 21:28
Show Gist options
  • Save BrettMayson/bdcf16c539623a29f912d8b219875e09 to your computer and use it in GitHub Desktop.
Save BrettMayson/bdcf16c539623a29f912d8b219875e09 to your computer and use it in GitHub Desktop.
use arma_rs::{arma, Extension};
#[macro_use]
extern crate log;
mod task;
mod worker;
lazy_static::lazy_static! {
static ref QUEUE: Mutex<Worker<Task>> = Mutex::new(Worker::<Task>::new_fifo());
}
#[arma]
fn init() -> Extension {
*QUEUE.lock().unwrap() = worker::start();
Extension::build
.group(Group::new("side_select")
.command("from_file", side_select::from_file)
.command("from_url", side_select::from_url)
.finish()
}
mod side_select {
use crate::{worker::fn_task, QUEUE, arma_callback};
pub fn from_file(file: String) -> String {
if let Ok(q) = QUEUE.lock() {
let task = fn_task(|id| {
if let Ok(json) = std::fs::read_to_string("classes.json") {
arma_callback("ext", "classes", Some(vec![id, json]);
}
});
let id = task.id().to_string()
q.push(task);
id
} else {
error!("Failed to lock queue");
String::new()
}
}
pub fn from_url(url: String) -> String {
if let Ok(q) = QUEUE.lock() {
let task = fn_task(|id| {
if let Ok(response) = reqwest::blocking::Client::new().get(url).send() {
if let Ok(json) = response.text() {
arma_callback("ext", "classes", Some(vec![id, json]);
}
}
});
let id = task.id().to_string()
q.push(task);
id
} else {
error!("Failed to lock queue");
String::new()
}
}
}
EXT_CALLBACKS = createHashMap;
addMissionEventHandler ["ExtensionCallback", {
params ["_name", "_function", "_data"];
if (_name isNotEqualTo "ext") exitWith {};
if (_function isNotEqualTo "classes") exitWith {};
(parseSimpleArray _data) params ["_id", "_classes"];
[_classes] call (EXT_CALLBACKS getOrDefault [_id, {}]);
};
_callExtension = {
params ["_args", "_callback"];
("ext" callExtension _args) params ["_id", "_code"];
if (_code == 0) then {
EXT_CALLBACKS set [_id, _code];
};
};
// Get rifleman classes
[
["select_side:from_file", ["rifleman.json"]],
{
params ["_classes"];
["ext_rifleman_loaded", _classes] call CBA_fnc_localEvent;
}
] call _callExtension;
// Get medic classes
[
["select_side:from_url", ["https://example.io/medic.json"]],
{
params ["_classes"];
["ext_medic_loaded", _classes] call CBA_fnc_localEvent;
}
] call _callExtension;
use arma_rs::ArmaValue;
use uuid::Uuid;
pub struct Task {
id: String,
handler: Box<dyn Fn(String) -> Result<ArmaValue, String> + Send>,
}
impl Task {
pub fn id(&self) -> &str {
&self.id
}
pub fn execute(&self) -> Result<ArmaValue, String> {
(self.handler)(self.id.clone())
}
}
pub fn fn_task<T>(exe: T) -> Task
where
T: TaskExecutor + 'static + Send,
{
Task {
id: Uuid::new_v4().to_string(),
handler: Box::new(move |id| exe.execute(id)),
}
}
pub trait TaskExecutor {
fn execute(&self, id: String) -> Result<ArmaValue, String>;
}
impl<F> TaskExecutor for F
where
F: Fn(String) -> Result<ArmaValue, String> + Send,
{
fn execute(&self, id: String) -> Result<ArmaValue, String> {
self(id)
}
}
mod task;
use crossbeam_deque::Worker;
pub use task::{Task, TaskExecutor, fn_task};
pub fn init() -> Worker<Task> {
Worker::<Task>::new_fifo()
}
pub fn start() -> Worker<Task> {
let queue = init();
let stealer = queue.stealer();
std::thread::spawn(move || {
loop {
if let Steal::Success(task) = stealer.steal() {
task.execute();
}
}
});
queue
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment