Initial commit
This commit is contained in:
commit
87d9f2b882
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
199
Cargo.lock
generated
Normal file
199
Cargo.lock
generated
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "arrayref"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blake2b_simd"
|
||||||
|
version = "0.5.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
|
||||||
|
dependencies = [
|
||||||
|
"arrayref",
|
||||||
|
"arrayvec",
|
||||||
|
"constant_time_eq",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "constant_time_eq"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "3.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "142995ed02755914747cc6ca76fc7e4583cd18578746716d0508ea6ed558b9ff"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.71"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.1.56"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"redox_syscall",
|
||||||
|
"rust-argon2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-argon2"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"blake2b_simd",
|
||||||
|
"constant_time_eq",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-skse-plugin"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"dirs",
|
||||||
|
"log",
|
||||||
|
"simple-logging",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simple-logging"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b00d48e85675326bb182a2286ea7c1a0b264333ae10f27a937a72be08628b542"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"thread-id",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread-id"
|
||||||
|
version = "3.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.9.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||||
|
|
||||||
|
[[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"
|
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "rust-skse-plugin"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Tyler Hallada <tyler@hallada.net>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
log = "0.4"
|
||||||
|
simple-logging = "2.0"
|
||||||
|
dirs = "3.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "RustSKSEPlugin"
|
||||||
|
crate-type = ["cdylib"]
|
81
src/README.md
Normal file
81
src/README.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# Rust SKSE Plugin
|
||||||
|
|
||||||
|
This is my mostly failed attempt at creating a fully-Rust [SKSE (Skyrim Script Extender)](https://skse.silverlock.org/) plugin.
|
||||||
|
|
||||||
|
## Build and Install
|
||||||
|
|
||||||
|
1. Have Skyrim Special Edition version 1.5.97 or later installed with SKSE build 2.0.17 installed.
|
||||||
|
2. Checkout the repo and `cd rust-skse-plugin`.
|
||||||
|
3. Run `cargo build`.
|
||||||
|
4. Copy `target/debug/RustSKSEPlugin.dll` to `<Skyrim Special Edition install folder>\Data\SKSE\Plugins\`.
|
||||||
|
5. Start Skyrim Special Edition by running `skse_loader.exe`.
|
||||||
|
6. Open `<Your Documents Directory>\My Games\Skyrim Special Edition\SKSE\skse64.log`, and you should see this plugin being loaded:
|
||||||
|
```
|
||||||
|
checking plugin E:\Program Files (x86)\Steam\steamapps\common\Skyrim Special Edition\Data\SKSE\Plugins\\RustSKSEPlugin.dll
|
||||||
|
plugin E:\Program Files (x86)\Steam\steamapps\common\Skyrim Special Edition\Data\SKSE\Plugins\\RustSKSEPlugin.dll (00000001 My Rust SKSE Plugin 00000001) loaded correctly
|
||||||
|
```
|
||||||
|
7. Open `<Your Documents Directory>\My Games\Skyrim Special Edition\SKSE\RustSKSEPlugin.log`, and your should see some logs from the Rust SKSE plugin:
|
||||||
|
```
|
||||||
|
[00:00:00.000] (8c4) INFO SKSEPlugin_Query begin
|
||||||
|
[00:00:00.000] (8c4) INFO SKSEPlugin_Query successful
|
||||||
|
[00:00:00.000] (8c4) INFO SKSEPlugin_Load begin
|
||||||
|
[00:00:00.000] (8c4) INFO queryInterfaceFunc: 0x7ffea09c695a
|
||||||
|
[00:00:00.000] (8c4) INFO queryInterface: 0x7ffea0e4eba8
|
||||||
|
[00:00:00.000] (8c4) INFO papyrusInterface: 0x7ffea0e4eba8
|
||||||
|
[00:00:00.000] (8c4) INFO papyrusRegister: 0x7ffea09d2011
|
||||||
|
[00:00:00.000] (8c4) INFO SKSEPlugin_Load successful
|
||||||
|
[00:00:01.740] (7838) INFO RegisterFuncs begin
|
||||||
|
[00:00:01.740] (7838) INFO a_registry: 0x19510f93780
|
||||||
|
[00:00:01.740] (7838) INFO registerFunction: 0x7ff7c85384f0
|
||||||
|
[00:00:01.740] (7838) INFO nativeFunction: 0x26ebebf108
|
||||||
|
[00:00:01.740] (7838) INFO RegisterFuncs successful
|
||||||
|
```
|
||||||
|
|
||||||
|
## Where I got stuck
|
||||||
|
|
||||||
|
I was trying to replicate [Ryan-rsm-McKenzie's Native SKSE64 Papyrus Interface Implementation example](https://gist.github.com/Ryan-rsm-McKenzie/cabb89a80abb09663a1288cafddd21e6) in Rust via it's FFI to C. I was able to successfully register the plugin with SKSE and even acquire a reference to the `PapyrusInterface`.
|
||||||
|
|
||||||
|
However, it seems like the code needs to call a C++ constructor (e.g. `new NativeFunction0<StaticFunctionTag, BSFixedString>("HelloWorld", "MyClass", HelloWorld, a_registry)`) in order to register a new native Papyrus function. Unfortunately, calling a C++ constructor requires FFI with C++, and [Rust does not support FFI with C++](https://stackoverflow.com/a/45540511).
|
||||||
|
|
||||||
|
## Failed attempt at using cpp crate
|
||||||
|
|
||||||
|
The [`cpp`](https://docs.rs/cpp/0.5.4/cpp/) crate may provide a way to interface with the SKSE C++ classes, but I'm too inexperienced with C++ to figure out how to compile skse64 in the `build.rs`.
|
||||||
|
|
||||||
|
I was able to get `CommonLibSSE` to compile, but I could not figure out how to convert the abstract `RE::BSScript::IVirtualMachine` class that the `RegisterFuncs` function recieves into something useable on the Rust side. That work is not included in the source, but to get that to work you will need to first follow the [CommonLibSSE setup](https://github.com/Ryan-rsm-McKenzie/CommonLibSSE/wiki/Getting-Started#building-your-first-plugin) and make sure everything builds in Visual Studio first.
|
||||||
|
|
||||||
|
Then checkout this repo alongside the `CommonLibSSE` folder inside `skse64`. Add the `cpp` and `cpp_build` crates to `Cargo.toml` and create this `build.rs` file at the root of the project:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
extern crate cpp_build;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let include_path = r#"<path to skse src>\skse64\CommonLibSSE\include"#;
|
||||||
|
let lib_path = r#"<path to skse src>\skse64\x64\Debug"#;
|
||||||
|
let vcpkg_include_path = r#"<path to vcpkg folder>\installed\x64-windows-custom\include"#;
|
||||||
|
cpp_build::Config::new().include(include_path).include(vcpkg_include_path).flag("/std:c++17").build("src/lib.rs");
|
||||||
|
println!("cargo:rustc-link-search={}", lib_path);
|
||||||
|
println!("cargo:rustc-link-lib=CommonLibSSE");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And, add this to `src/lib.rs`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[macro_use]
|
||||||
|
extern crate cpp;
|
||||||
|
|
||||||
|
cpp!{{
|
||||||
|
#include "RE/Skyrim.h"
|
||||||
|
#include "REL/Relocation.h"
|
||||||
|
#include "SKSE/SKSE.h"
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can replace the `SKSEPapyrusInterface` struct with something like:
|
||||||
|
```rust
|
||||||
|
cpp_class!(pub unsafe struct PapyrusInterface as "SKSE::PapyrusInterface");
|
||||||
|
```
|
||||||
|
|
||||||
|
## What I'm probably going to do instead
|
||||||
|
|
||||||
|
Abandon my dream of a pure Rust SKSE plugin and just write a normal C++ one (with [CommonLibSSE](https://github.com/Ryan-rsm-McKenzie/CommonLibSSE)) which will execute functions exported from a Rust dll (with [cbindgen](https://crates.io/crates/cbindgen)) inside a native Papyrus function callback. This requires the user to place the Rust-generated dll file in their Skyrim install directory in addition to placing the C++ generated SKSE plugin dll in the SKSE plugins directory.
|
185
src/lib.rs
Normal file
185
src/lib.rs
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
#![allow(non_snake_case)]
|
||||||
|
extern crate simple_logging;
|
||||||
|
extern crate log;
|
||||||
|
extern crate dirs;
|
||||||
|
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::os::raw::{c_char, c_void};
|
||||||
|
use std::path::Path;
|
||||||
|
use log::{info, error, LevelFilter};
|
||||||
|
|
||||||
|
type PluginHandle = u32;
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct SKSEInterface {
|
||||||
|
pub skseVersion: u32,
|
||||||
|
pub runtimeVersion: u32,
|
||||||
|
pub editorVersion: u32,
|
||||||
|
pub isEditor: u32,
|
||||||
|
pub QueryInterface: fn(KInterface) -> *const c_void,
|
||||||
|
pub GetPluginHandle: fn() -> PluginHandle,
|
||||||
|
pub GetReleaseIndex: fn() -> u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct PluginInfo {
|
||||||
|
pub infoVersion: u32,
|
||||||
|
pub name: *mut c_char,
|
||||||
|
pub version: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct VMValue;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct VMState;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct NativeFunction {
|
||||||
|
InitParams: fn(*const VMClassRegistry) -> (),
|
||||||
|
Run: fn(*const VMValue, *const VMClassRegistry, u32, *const VMValue, *const VMState) -> bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeFunction {
|
||||||
|
fn new() -> NativeFunction {
|
||||||
|
NativeFunction {
|
||||||
|
InitParams: |registry| {
|
||||||
|
info!("NativeFunction InitParams begin");
|
||||||
|
info!("registry: {:?}", registry);
|
||||||
|
info!("NativeFunction InitParams successful");
|
||||||
|
},
|
||||||
|
Run: |baseValue, registry, stackId, resultValue, state| {
|
||||||
|
info!("NativeFunction Run begin");
|
||||||
|
info!("baseValue: {:?}", baseValue);
|
||||||
|
info!("registry: {:?}", registry);
|
||||||
|
info!("stackId: {:?}", stackId);
|
||||||
|
info!("resultValue: {:?}", resultValue);
|
||||||
|
info!("state: {:?}", state);
|
||||||
|
info!("NativeFunction Run successful");
|
||||||
|
true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct VMClassInfo;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct VMIdentifier;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct StringCacheRef;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct VMClassRegistry {
|
||||||
|
pub Unk_01: fn(c_void) -> c_void,
|
||||||
|
pub PrintToDebugLog: fn(*const c_char, u32, u32) -> c_void,
|
||||||
|
pub Unk_03: fn(c_void) -> c_void,
|
||||||
|
pub Unk_04: fn(c_void) -> c_void,
|
||||||
|
pub Unk_05: fn(c_void) -> c_void,
|
||||||
|
pub Unk_06: fn(c_void) -> c_void,
|
||||||
|
pub Unk_07: fn(c_void) -> c_void,
|
||||||
|
pub RegisterForm: fn(u32, *const c_char) -> c_void,
|
||||||
|
pub Unk_09: fn(c_void) -> c_void,
|
||||||
|
pub GetFormTypeClass: fn(u32, *const VMClassInfo) -> bool,
|
||||||
|
pub Unk_0B: fn(c_void) -> c_void,
|
||||||
|
pub Unk_0C: fn(c_void) -> c_void,
|
||||||
|
pub Unk_0D: fn(*const StringCacheRef, *const u32) -> bool,
|
||||||
|
pub Unk_0E: fn(c_void) -> c_void,
|
||||||
|
pub Unk_0F: fn(c_void) -> c_void,
|
||||||
|
pub Unk_10: fn(c_void) -> c_void,
|
||||||
|
pub Unk_11: fn(c_void) -> c_void,
|
||||||
|
pub Unk_12: fn(c_void) -> c_void,
|
||||||
|
pub Unk_13: fn(c_void) -> c_void,
|
||||||
|
pub Unk_14: fn(c_void) -> c_void,
|
||||||
|
pub Unk_15: fn(*const StringCacheRef, *const VMIdentifier) -> bool,
|
||||||
|
pub CreateArray: fn(*const VMValue, u32, *const VMValue) -> bool,
|
||||||
|
pub Unk_17: fn(c_void) -> c_void,
|
||||||
|
pub RegisterFunction: fn(*const NativeFunction) -> c_void,
|
||||||
|
// more...
|
||||||
|
}
|
||||||
|
|
||||||
|
type RegisterFunctions = fn(*const VMClassRegistry) -> bool;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct SKSEPapyrusInterface {
|
||||||
|
pub interfaceVersion: u32,
|
||||||
|
pub Register: fn(*const RegisterFunctions) -> bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum KInterface {
|
||||||
|
Invalid = 0,
|
||||||
|
Scaleform,
|
||||||
|
Papyrus,
|
||||||
|
Serialization,
|
||||||
|
Task,
|
||||||
|
Messaging,
|
||||||
|
Object,
|
||||||
|
Max,
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn make_exe_version(major: u32, minor: u32, build: u32, sub: u32) -> u32 {
|
||||||
|
(((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | (((build) & 0xFFF) << 4) | ((sub) & 0xF)
|
||||||
|
}
|
||||||
|
|
||||||
|
const RUNTIME_VERSION_1_5_97: u32 = make_exe_version(1, 5, 97, 0);
|
||||||
|
|
||||||
|
unsafe fn RegisterFuncs(a_registry: *const VMClassRegistry) -> bool {
|
||||||
|
info!("RegisterFuncs begin");
|
||||||
|
info!("a_registry: {:?}", a_registry);
|
||||||
|
let registerFunction = (*a_registry).RegisterFunction;
|
||||||
|
info!("registerFunction: {:?}", registerFunction);
|
||||||
|
let nativeFunction: *const NativeFunction = &NativeFunction::new();
|
||||||
|
info!("nativeFunction: {:?}", nativeFunction);
|
||||||
|
// This is as far as I can get. I have no idea how to register a native papyrus function.
|
||||||
|
// Doesn't work, throws exception "Access violation executing location"
|
||||||
|
// registerFunction(nativeFunction);
|
||||||
|
info!("RegisterFuncs successful");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn SKSEPlugin_Query(a_skse: *const SKSEInterface, a_info: *mut PluginInfo) -> bool {
|
||||||
|
let mut log_dir = dirs::document_dir().expect("could not get Documents directory");
|
||||||
|
log_dir.push(Path::new(r#"My Games\Skyrim Special Edition\SKSE\RustSKSEPlugin.log"#));
|
||||||
|
simple_logging::log_to_file(log_dir, LevelFilter::Info).unwrap();
|
||||||
|
info!("SKSEPlugin_Query begin");
|
||||||
|
|
||||||
|
(*a_info).infoVersion = 1;
|
||||||
|
(*a_info).name = CString::new("My Rust SKSE Plugin").expect("could not create CString").into_raw();
|
||||||
|
(*a_info).version = 1;
|
||||||
|
|
||||||
|
if (*a_skse).isEditor != 0 {
|
||||||
|
error!("Loaded in editor, marking as incompatible!");
|
||||||
|
return false;
|
||||||
|
} else if (*a_skse).runtimeVersion != RUNTIME_VERSION_1_5_97 {
|
||||||
|
error!("Unsupported runtime version {}!", (*a_skse).runtimeVersion);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("SKSEPlugin_Query successful");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn SKSEPlugin_Load(a_skse: *const SKSEInterface) -> bool {
|
||||||
|
info!("SKSEPlugin_Load begin");
|
||||||
|
|
||||||
|
let queryInterfaceFunc = (*a_skse).QueryInterface;
|
||||||
|
info!("queryInterfaceFunc: {:?}", queryInterfaceFunc);
|
||||||
|
let queryInterface = queryInterfaceFunc(KInterface::Papyrus);
|
||||||
|
info!("queryInterface: {:?}", queryInterface);
|
||||||
|
let papyrusInterface: *const SKSEPapyrusInterface = queryInterface as *const SKSEPapyrusInterface;
|
||||||
|
info!("papyrusInterface: {:?}", papyrusInterface);
|
||||||
|
let papyrusRegister = (*papyrusInterface).Register;
|
||||||
|
info!("papyrusRegister: {:?}", papyrusRegister);
|
||||||
|
if !papyrusRegister(RegisterFuncs as *const RegisterFunctions) {
|
||||||
|
error!("RegisterFuncs returned false!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("SKSEPlugin_Load successful");
|
||||||
|
true
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user