Build offline OpenPrestige release bundles
Rename the injector and package it with an embedded payload for Windows, Linux, and macOS x64/ARM64. Add a core-only ImGui native build, multi-platform CI and release packaging, and shared per-user storage with legacy config migration.
This commit is contained in:
1 parent
5152e6e0a6
commit
2d6b2a3cd1
37 files changed
+1284
-451
No files matched your search
@@ -10,7 +10,10 @@ fn main() {
|
||||
Err(_) => newest_remapped_jar(),
|
||||
};
|
||||
if !jar.is_file() {
|
||||
panic!("payload jar not found: {} (run `gradlew remapJar` or set PRESTIGE_PAYLOAD)", jar.display());
|
||||
panic!(
|
||||
"payload jar not found: {} (run `gradlew remapJar` or set PRESTIGE_PAYLOAD)",
|
||||
jar.display()
|
||||
);
|
||||
}
|
||||
println!("cargo:rerun-if-changed={}", jar.display());
|
||||
println!("cargo:rustc-env=PRESTIGE_PAYLOAD_JAR={}", jar.display());
|
||||
@@ -22,14 +25,22 @@ fn newest_remapped_jar() -> PathBuf {
|
||||
if let Ok(entries) = fs::read_dir(&libs) {
|
||||
for entry in entries.flatten() {
|
||||
let name = entry.file_name().to_string_lossy().to_string();
|
||||
if !name.starts_with("prestige-") || !name.ends_with(".jar") || name.ends_with("-dev.jar") || name.ends_with("-sources.jar") {
|
||||
if !name.starts_with("prestige-")
|
||||
|| !name.ends_with(".jar")
|
||||
|| name.ends_with("-dev.jar")
|
||||
|| name.ends_with("-sources.jar")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
let time = entry.metadata().and_then(|m| m.modified()).unwrap_or(std::time::UNIX_EPOCH);
|
||||
let time = entry
|
||||
.metadata()
|
||||
.and_then(|m| m.modified())
|
||||
.unwrap_or(std::time::UNIX_EPOCH);
|
||||
if best.as_ref().map_or(true, |(t, _)| time > *t) {
|
||||
best = Some((time, entry.path()));
|
||||
}
|
||||
}
|
||||
}
|
||||
best.map(|(_, p)| p).unwrap_or_else(|| libs.join("prestige-0.1.0.jar"))
|
||||
best.map(|(_, p)| p)
|
||||
.unwrap_or_else(|| libs.join("prestige-0.1.0.jar"))
|
||||
}
|
||||
@@ -6,6 +6,8 @@
|
||||
mod bridge;
|
||||
mod jni;
|
||||
mod log;
|
||||
#[path = "../../paths.rs"]
|
||||
mod paths;
|
||||
mod worker;
|
||||
|
||||
use std::ffi::c_void;
|
||||
|
||||
@@ -1,61 +1,19 @@
|
||||
use std::ffi::c_void;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::OnceLock;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
#[cfg(windows)]
|
||||
extern "system" {
|
||||
fn GetModuleFileNameW(module: *mut c_void, buf: *mut u16, size: u32) -> u32;
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[repr(C)]
|
||||
struct DlInfo {
|
||||
dli_fname: *const std::ffi::c_char,
|
||||
dli_fbase: *mut c_void,
|
||||
dli_sname: *const std::ffi::c_char,
|
||||
dli_saddr: *mut c_void,
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
extern "C" {
|
||||
fn dladdr(addr: *const c_void, info: *mut DlInfo) -> i32;
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn module_path() -> PathBuf {
|
||||
fn anchor() {}
|
||||
let mut info = DlInfo { dli_fname: std::ptr::null(), dli_fbase: std::ptr::null_mut(), dli_sname: std::ptr::null(), dli_saddr: std::ptr::null_mut() };
|
||||
let ok = unsafe { dladdr(anchor as fn() as usize as *const c_void, &mut info) };
|
||||
if ok != 0 && !info.dli_fname.is_null() {
|
||||
let name = unsafe { std::ffi::CStr::from_ptr(info.dli_fname) };
|
||||
PathBuf::from(std::ffi::OsStr::from_bytes(name.to_bytes()))
|
||||
} else {
|
||||
std::env::temp_dir().join("libprestige_native")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn module_path() -> PathBuf {
|
||||
let mut buf = [0u16; 1024];
|
||||
let len = unsafe { GetModuleFileNameW(crate::MODULE, buf.as_mut_ptr(), buf.len() as u32) } as usize;
|
||||
PathBuf::from(String::from_utf16_lossy(&buf[..len]))
|
||||
}
|
||||
|
||||
fn log_path() -> &'static PathBuf {
|
||||
static PATH: OnceLock<PathBuf> = OnceLock::new();
|
||||
PATH.get_or_init(|| {
|
||||
module_path().with_file_name("prestige-native.log")
|
||||
})
|
||||
PATH.get_or_init(|| crate::paths::native_log(std::process::id()))
|
||||
}
|
||||
|
||||
/// Appends a line to prestige-native.log beside the DLL.
|
||||
pub fn log(message: &str) {
|
||||
let secs = SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_secs()).unwrap_or(0);
|
||||
if let Some(parent) = log_path().parent() {
|
||||
let _ = std::fs::create_dir_all(parent);
|
||||
}
|
||||
if let Ok(mut file) = OpenOptions::new().create(true).append(true).open(log_path()) {
|
||||
let _ = writeln!(file, "[{secs}] {message}");
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ pub fn run() {
|
||||
}
|
||||
|
||||
unsafe fn install() -> Result<(), String> {
|
||||
crate::paths::initialize().map_err(|error| format!("create OpenPrestige data directory: {error}"))?;
|
||||
let vm = find_vm()?;
|
||||
let env = attach_current_thread(vm)?;
|
||||
struct Detach(VmPtr);
|
||||
@@ -45,7 +46,7 @@ unsafe fn install() -> Result<(), String> {
|
||||
log!("JVMTI ready");
|
||||
|
||||
let jar = write_payload()?;
|
||||
log!("payload written to {}", jar.display());
|
||||
log!("using payload at {}", jar.display());
|
||||
|
||||
let loader = add_to_knot(&jni, &jar)?;
|
||||
log!("payload appended to the game class loader: {}", describe(&jni, loader));
|
||||
@@ -103,7 +104,8 @@ unsafe fn find_vm() -> Result<VmPtr, String> {
|
||||
}
|
||||
|
||||
fn write_payload() -> Result<PathBuf, String> {
|
||||
let dir = std::env::temp_dir().join("PrestigeLoader");
|
||||
let dir = crate::paths::initialize().map_err(|e| format!("create OpenPrestige data directory: {e}"))?
|
||||
.join("runtime").join("payloads");
|
||||
std::fs::create_dir_all(&dir).map_err(|e| format!("create {}: {e}", dir.display()))?;
|
||||
let path = dir.join(format!("prestige-payload-{}.jar", std::process::id()));
|
||||
std::fs::write(&path, PAYLOAD).map_err(|e| format!("write {}: {e}", path.display()))?;
|
||||
|
||||
Reference in new issue
Block a user