From b37c4ba35d0ef893578077c4753436a88905f001 Mon Sep 17 00:00:00 2001 From: Tiaansu Date: Sat, 28 Sep 2024 15:44:54 +0800 Subject: [PATCH] add custom args support --- README.md | 7 +++--- include/samp_cron.inc | 13 +++++----- src/internals.rs | 6 +++++ src/natives.rs | 58 ++++++++++++++++++++++++++++++++++++++++++- src/plugin.rs | 2 +- 5 files changed, 75 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 78268f3..67a258f 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,10 @@ cargo build --release > ``` ## API -* #### cron_new(const pattern[], const callback[]) +* #### cron_new(const pattern[], const callback[], const args[] = "", {Float, _}:...) * `pattern[]` - cron pattern * `callback[]` - callback to execute every call + * `args[]` - custom arguments **Returns** the cron job id @@ -43,13 +44,13 @@ cargo build --release new CRON:cron_id = INVALID_CRON_ID; main() { - cron_new("* * * * * *", "SecondTimer"); + cron_new("* * * * * *", "SecondTimer", "i", 5); } forward SecondTimer(); public SecondTimer() { - printf("Hi! I am called by cron id: %i", _:cron_id); + printf("Hi! I am called by cron id: %i and I also have a custom args: %i!", _:cron_id, num); } ``` diff --git a/include/samp_cron.inc b/include/samp_cron.inc index 3456725..ebb01c9 100644 --- a/include/samp_cron.inc +++ b/include/samp_cron.inc @@ -10,10 +10,11 @@ #define INVALID_CRON_ID (CRON:0) /* -cron_new(const pattern[], const callback[]) +cron_new(const pattern[], const callback[], const args[] = "", {Float, _}:...) Params `pattern[]` - cron pattern `callback[]` - callback to execute every call + `args[]` - custom arguments Returns the cron job id @@ -23,17 +24,17 @@ cron_new(const pattern[], const callback[]) new CRON:cron_id = INVALID_CRON_ID; main() { - cron_new("* * * * * *", "SecondTimer"); + cron_new("* * * * * *", "SecondTimer", "i", 5); } - forward SecondTimer(); - public SecondTimer() + forward SecondTimer(num); + public SecondTimer(num) { - printf("Hi! I am called by cron id: %i", _:cron_id); + printf("Hi! I am called by cron id: %i and I also have a custom args: %i!", _:cron_id, num); } ``` */ -native CRON:cron_new(const pattern[], const callback[]); +native CRON:cron_new(const pattern[], const callback[], const args[] = "", {Float, _}:...); /* bool:cron_is_valid(CRON:id) diff --git a/src/internals.rs b/src/internals.rs index 582d2fa..9facd29 100644 --- a/src/internals.rs +++ b/src/internals.rs @@ -1,6 +1,12 @@ use crate::SampCron; use rcron::Uuid; +#[derive(Debug)] +pub enum ArgumentTypes { + Primitive(i32), + String(Vec), +} + static mut GLOBAL_INDEX: usize = 0; pub fn insert_uuid( diff --git a/src/natives.rs b/src/natives.rs index 07e5854..1a87f08 100644 --- a/src/natives.rs +++ b/src/natives.rs @@ -1,4 +1,4 @@ -use crate::internals::insert_uuid; +use crate::internals::{insert_uuid, ArgumentTypes}; use log::error; use rcron::{Job, Schedule}; use samp::error::AmxError; @@ -10,11 +10,48 @@ impl super::SampCron<'static> { pub fn cron_new(&mut self, amx: &'static Amx, mut args: samp::args::Args) -> AmxResult { let cron_pattern = args.next::().ok_or(AmxError::Params)?.to_string(); let callback_name = args.next::().ok_or(AmxError::Params)?.to_string(); + let mut format: Vec = Vec::new(); + + if args.count() > 2 { + if let Some(specifiers) = args.next::() { + format = specifiers.to_bytes(); + } + } + + if !format.is_empty() && format.len() != args.count() - 3 { + error!( + "The argument count mismatch expected: {} provided: {}.", + format.len(), + args.count() - 3 + ); + return Ok(0); + } if Schedule::from_str(&cron_pattern).is_err() { error!("Invalid CRON expression: {}", cron_pattern); return Ok(0); } + + let mut optional_args: Vec = Vec::new(); + + for specifiers in format { + match specifiers { + b'd' | b'i' | b'f' => { + optional_args.push(ArgumentTypes::Primitive( + *args.next::>().ok_or(AmxError::Params)?, + )); + } + b's' => { + let argument: Ref = args.next().ok_or(AmxError::Params)?; + let amx_str = AmxString::from_raw(amx, argument.address())?; + optional_args.push(ArgumentTypes::String(amx_str.to_bytes())); + } + _ => { + error!("Unknown specifier type: {}", specifiers); + return Ok(0); + } + } + } let public_index = amx.find_public(&callback_name); @@ -24,6 +61,25 @@ impl super::SampCron<'static> { } let job = Job::new(cron_pattern.parse().unwrap(), move || { + let allocator = amx.allocator(); + + for param in optional_args.iter().rev() { + match param { + ArgumentTypes::Primitive(x) => { + if amx.push(x).is_err() { + error!("*Cannot execute callback {:?}", callback_name); + } + } + ArgumentTypes::String(data) => { + let buf = allocator.allot_buffer(data.len() + 1).unwrap(); + let amx_str = unsafe { AmxString::new(buf, data) }; + if amx.push(amx_str).is_err() { + error!("*Cannot execute callback {:?}", callback_name); + } + } + } + } + if amx.exec(public_index.as_ref().unwrap().to_owned()).is_err() { error!("Cannot execute callback: {:?}", callback_name); } diff --git a/src/plugin.rs b/src/plugin.rs index f82ea39..5573c25 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -12,7 +12,7 @@ pub struct SampCron<'a> { impl SampPlugin for SampCron<'static> { fn on_load(&mut self) { - info!("Version: 0.0.1"); + info!("Version: 0.1.0"); } fn on_unload(&mut self) {