diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..2311e5e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,62 @@ +name: Build + +on: + push: + branches: + - main + pull_request: + branches: + - master + +env: + RELEASE_BIN: samp_cron + RELEASE_ADDS: README.md LICENSE include/samp_cron.inc + +jobs: + build: + name: Build release + + runs-on: ${{ matrix.os }} + strategy: + matrix: + build: [linux, windows] + include: + - build: linux + os: ubuntu-20.04 + rust: stable-i686 + - build: windows + os: windows-latest + rust: stable-i686 + + steps: + - uses: actions/checkout@v4 + + - name: Install gcc-multilib + run: | + sudo apt update + sudo apt install gcc-multilib -y + if: matrix.os == 'ubuntu-20.04' + + - name: Install Rust (rustup) + run: rustup update ${{ matrix.os }} --no-self-update && rustup default ${{ matrix.rust }} + shell: bash + + - name: Build + run: cargo build --verbose --release + + - name: Create artifact directory + run: mkdir artifacts + + - name: Create archive for Linux + run: 7z a -ttar -so -an ./target/release/lib${{ env.RELEASE_BIN }}.so ${{ env.RELEASE_ADDS }} | 7z a -si ./artifacts/${{ env.RELEASE_BIN }}=linux-x86.tar.gz + if: matrix.os == 'ubuntu-20.04' + + - name: Create archive for Windows + run: 7z a -tzip ./artifacts/${{ env.RELEASE_BIN }}-windows-x86.zip ./target/release/${{ env.RELEASE_BIN }}.dll ${{ env.RELEASE_ADDS }} + if: matrix.os == 'windows-latest' + + - uses: actions/upload-artifact@v4 + name: Upload archive + with: + name: ${{ runner.os }} + path: artifacts/ \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..f144059 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,518 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[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 = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cc" +version = "1.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "colored" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f741c91823341bebf717d4c71bda820630ce065443b58bd1b7451af008355" +dependencies = [ + "is-terminal", + "lazy_static", + "winapi", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cron" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8c3e73077b4b4a6ab1ea5047c37c57aee77657bc8ecd6f29b0af082d0b0c07" +dependencies = [ + "chrono", + "nom", + "once_cell", +] + +[[package]] +name = "fern" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e69ab0d5aca163e388c3a49d284fed6c3d0810700e77c5ae2756a50ec1a4daaa" +dependencies = [ + "chrono", + "log", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +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 = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2 1.0.86", +] + +[[package]] +name = "rcron" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b090d835933c4940c552aaf016739e171886e8f3f85aee63f7cb24372fb3199" +dependencies = [ + "chrono", + "cron", + "uuid", +] + +[[package]] +name = "samp" +version = "0.1.3" +source = "git+https://github.com/Pycckue-Bnepeg/samp-rs#17ecb2f722bf0d74a98eb782745cd77e41c3c60a" +dependencies = [ + "fern", + "samp-codegen", + "samp-sdk", +] + +[[package]] +name = "samp-codegen" +version = "0.1.2" +source = "git+https://github.com/Pycckue-Bnepeg/samp-rs#17ecb2f722bf0d74a98eb782745cd77e41c3c60a" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "samp-cron" +version = "0.0.1" +dependencies = [ + "fern", + "log", + "rcron", + "samp", +] + +[[package]] +name = "samp-sdk" +version = "0.9.2" +source = "git+https://github.com/Pycckue-Bnepeg/samp-rs#17ecb2f722bf0d74a98eb782745cd77e41c3c60a" +dependencies = [ + "bitflags", + "colored", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "uuid" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +dependencies = [ + "getrandom", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote 1.0.37", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b61288a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "samp-cron" +version = "0.0.1" +edition = "2021" +authors = ["Tiaansu "] + +[lib] +name = "samp_cron" +crate-type = ["cdylib"] + +[profile.release] +lto = true +panic = "abort" + +[dependencies] +samp = {git="https://github.com/Pycckue-Bnepeg/samp-rs"} +log = "0.4.6" +fern = "0.5.7" +rcron = "1.2.3" \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a651376 --- /dev/null +++ b/README.md @@ -0,0 +1,96 @@ +# SampCRON + +A cron plugin for samp/open.mp in Rust. + +## Installation +- Download suitable binary files from releases for your operating system. +- Add it to your `plugins` folder +- Add `samp_cron` to server.cfg (config.json if you're using open.mp) or `samp_cron.so` (for linux) +- Add [samp_cron.inc](./include/samp_cron.inc) in includes folder + +## Building +- Clone the repo +```bash +git clone https://github.com/Tiaansu/samp-cron.git +``` +- Install Rust +```bash +rustup update stable-i686 --no-self-update && rustup default stable-i686 +``` +- Build using `cargo build` +```bash +cargo build --release +``` + +## API +* #### cron_new(const pattern[], const callback[]) + * `pattern[]` - cron pattern + * `callback[]` - callback to execute every call + + **Returns** + the cron job id + + **Example** + ```Pawn + new CRON:cron_id = INVALID_CRON_ID; + main() + { + cron_new("* * * * * *", "SecondTimer"); + } + + forward SecondTimer(); + public SecondTimer() + { + printf("Hi! I am called by cron id: %i", _:cron_id); + } + ``` + +* #### bool:cron_is_valid(CRON:id) + * `id` - id of cron job + + **Returns** + true - valid + false - invalid + + **Example** + ```Pawn + new CRON:cron_id = INVALID_CRON_ID; + main() + { + printf("Is cron job id %i valid? %i", _:cron_id, cron_is_valid(cron_id)); + } + ``` + +* #### bool:cron_delete(CRON:id) + * `id` - id of cron job + + **Returns** + true - succeed + false - failed + + **Example** + ```Pawn + new CRON:cron_id = INVALID_CRON_ID, current = 0; + main() + { + cron_id = cron_new("* * * * * *", "SecondTimer"); + } + + forward SecondTimer(); + public SecondTimer() + { + if (++ current <= 10) + { + printf("%i/10", current + 1); + } + else + { + printf("Is cron job id %i deleted? %i", _:cron_id, cron_delete(cron_id)); + } + } + ``` + +--- + +> [!NOTE] +> Most of the part of this README is from/based on [samp-bcrypt](https://github.com/Sreyas-Sreelal/samp-bcrypt) \ No newline at end of file diff --git a/include/samp_cron.inc b/include/samp_cron.inc new file mode 100644 index 0000000..3456725 --- /dev/null +++ b/include/samp_cron.inc @@ -0,0 +1,89 @@ +#if defined _inc_samp_cron + #undef _inc_samp_cron +#endif + +#if defined _samp_rcon_included + #endinput +#endif +#define _samp_rcon_included + +#define INVALID_CRON_ID (CRON:0) + +/* +cron_new(const pattern[], const callback[]) + Params + `pattern[]` - cron pattern + `callback[]` - callback to execute every call + + Returns + the cron job id + + Example + ``` + new CRON:cron_id = INVALID_CRON_ID; + main() + { + cron_new("* * * * * *", "SecondTimer"); + } + + forward SecondTimer(); + public SecondTimer() + { + printf("Hi! I am called by cron id: %i", _:cron_id); + } + ``` + */ +native CRON:cron_new(const pattern[], const callback[]); + +/* +bool:cron_is_valid(CRON:id) + Params + `id` - id of cron job + + Returns + true - valid + false - invalid + + Example + ``` + new CRON:cron_id = INVALID_CRON_ID; + main() + { + printf("Is cron job id %i valid? %i", _:cron_id, cron_is_valid(cron_id)); + } + ``` + */ +native bool:cron_is_valid(CRON:id); + +/* +bool:cron_delete(CRON:id) + Params + `id` - id of cron job + + Returns + true - succeed + false - failed + + Example + ``` + new CRON:cron_id = INVALID_CRON_ID, current = 0; + main() + { + cron_id = cron_new("* * * * * *", "SecondTimer"); + } + + forward SecondTimer(); + public SecondTimer() + { + if (++ current <= 10) + { + printf("%i/10", current + 1); + } + else + { + printf("Is cron job id %i deleted? %i", _:cron_id, cron_delete(cron_id)); + } + } + ``` + */ +native bool:cron_delete(CRON:id); \ No newline at end of file diff --git a/src/internals.rs b/src/internals.rs new file mode 100644 index 0000000..582d2fa --- /dev/null +++ b/src/internals.rs @@ -0,0 +1,15 @@ +use crate::SampCron; +use rcron::Uuid; + +static mut GLOBAL_INDEX: usize = 0; + +pub fn insert_uuid( + samp_cron: &mut SampCron, + uuid: Uuid +) -> usize { + unsafe { + samp_cron.schedules.push(uuid); + GLOBAL_INDEX += 1; + return GLOBAL_INDEX; + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..4921eda --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,33 @@ +mod plugin; +mod internals; +mod natives; + +use plugin::SampCron; +use rcron::JobScheduler; +use samp::initialize_plugin; + +initialize_plugin!( + natives: [ + SampCron::cron_new, + SampCron::cron_delete, + SampCron::cron_is_valid + ], + { + samp::plugin::enable_process_tick(); + let samp_logger = samp::plugin::logger() + .level(log::LevelFilter::Info); + + let _ = fern::Dispatch::new() + .format(|callback, message, record| { + callback.finish(format_args!("[SampCron] [{}]: {}", record.level().to_string().to_lowercase(), message)) + }) + .chain(samp_logger) + .apply(); + + SampCron { + amx_list:Vec::new(), + scheduler:JobScheduler::new(), + schedules: Vec::new() + } + } +); diff --git a/src/natives.rs b/src/natives.rs new file mode 100644 index 0000000..07e5854 --- /dev/null +++ b/src/natives.rs @@ -0,0 +1,52 @@ +use crate::internals::insert_uuid; +use log::error; +use rcron::{Job, Schedule}; +use samp::error::AmxError; +use samp::{native, prelude::*}; +use std::str::FromStr; + +impl super::SampCron<'static> { + #[native(raw, name = "cron_new")] + 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(); + + if Schedule::from_str(&cron_pattern).is_err() { + error!("Invalid CRON expression: {}", cron_pattern); + return Ok(0); + } + + let public_index = amx.find_public(&callback_name); + + if public_index.is_err() { + error!("Invalid public: {}", callback_name); + return Ok(0); + } + + let job = Job::new(cron_pattern.parse().unwrap(), move || { + if amx.exec(public_index.as_ref().unwrap().to_owned()).is_err() { + error!("Cannot execute callback: {:?}", callback_name); + } + }); + let uuid = self.scheduler.add(job); + let id = insert_uuid(self, uuid); + + Ok(id.as_cell()) + } + + #[native(name = "cron_is_valid")] + pub fn cron_is_valid(&mut self, _: &Amx, index: i32) -> AmxResult { + Ok(self.schedules.get(index as usize - 1).is_some()) + } + + #[native(name = "cron_delete")] + pub fn cron_delete(&mut self, _: &Amx, value: i32) -> AmxResult { + let index = value as usize - 1; + if let Some(job_id) = self.schedules.get(index).cloned() { + self.schedules.remove(index); + Ok(self.scheduler.remove(job_id)) + } else { + Ok(false) + } + } +} \ No newline at end of file diff --git a/src/plugin.rs b/src/plugin.rs new file mode 100644 index 0000000..f82ea39 --- /dev/null +++ b/src/plugin.rs @@ -0,0 +1,35 @@ +use log::info; +use rcron::{JobScheduler, Uuid}; +use samp::amx::AmxIdent; +use samp::plugin::SampPlugin; +use samp::prelude::*; + +pub struct SampCron<'a> { + pub amx_list: Vec, + pub scheduler: JobScheduler<'a>, + pub schedules: Vec, +} + +impl SampPlugin for SampCron<'static> { + fn on_load(&mut self) { + info!("Version: 0.0.1"); + } + + fn on_unload(&mut self) { + info!("unloading plugin..."); + } + + fn on_amx_load(&mut self, amx: &Amx) { + self.amx_list.push(amx.ident()); + } + + fn on_amx_unload(&mut self, amx: &Amx) { + let raw = amx.ident(); + let index = self.amx_list.iter().position(|x| *x == raw).unwrap(); + self.amx_list.remove(index); + } + + fn process_tick(&mut self) { + self.scheduler.tick(); + } +} \ No newline at end of file