tirbofish/dropbear · commit
d45784d3a9abe8cc557478b45e3b8c6b13a69610
got the JDB and debugging working pretty nicely, as well as some additional fixes+tweaks.
Signature present but could not be verified.
Unverified
@@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget + plugins { alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.kotlinxSerialization) @@ -13,7 +15,9 @@ repositories { } kotlin { - jvm() + jvm { + withJava() + } val hostOs = System.getProperty("os.name") val isArm64 = System.getProperty("os.arch") == "aarch64" @@ -102,7 +106,7 @@ kotlin { } jvmMain { - kotlin.srcDirs("src/jvmMain/kotlin", "src/jvmMain/java", "build/magna-carta") + kotlin.srcDirs("src/jvmMain/kotlin", "build/magna-carta") dependencies { } @@ -30,8 +30,8 @@ rayon.workspace = true jni.workspace = true crossbeam-channel = "0.5.15" libloading = "0.8.9" -tokio-util = "0.7" app_dirs2.workspace = true +sha2 = "0.10" [features] # editor only stuff @@ -112,9 +112,9 @@ impl ScriptManager { _input_state: &InputState, ) -> anyhow::Result<()> { match &self.script_target { - ScriptTarget::JVM { library_path } => { + ScriptTarget::JVM { library_path: _ } => { if let Some(jvm) = &mut self.jvm { - jvm.init(library_path, world)?; + jvm.init(world)?; for tag in self.entity_tag_database.keys() { log::trace!("Loading systems for tag: {}", tag); jvm.load_systems_for_tag(tag)?; @@ -3,14 +3,16 @@ pub mod exception; +use std::fs; use dropbear_engine::entity::AdoptedEntity; use hecs::World; -use jni::objects::{GlobalRef, JClass, JObject, JString, JThrowable, JValue, JValueGen}; +use jni::objects::{GlobalRef, JClass, JString, JValue}; use jni::sys::jlong; use jni::sys::jobject; use jni::{InitArgsBuilder, JNIEnv, JNIVersion, JavaVM}; -use std::path::{Path, PathBuf}; -use crate::{info, APP_INFO}; +use std::path::{PathBuf}; +use crate::{success, APP_INFO}; +use sha2::{Digest, Sha256}; use crate::logging::{LOG_LEVEL}; use crate::ptr::WorldPtr; use crate::scripting::jni::exception::get_exception_info; @@ -30,17 +32,46 @@ impl JavaContext { pub fn new() -> anyhow::Result<Self> { let root = app_dirs2::app_root(app_dirs2::AppDataType::UserData, &APP_INFO)?; let deps = root.join("dependencies"); - let host_jar_filename = "dropbear-1.0-SNAPSHOT-all.jar"; + let host_jar_filename = "dropbear-jvm-fat-1.0-SNAPSHOT.jar"; let host_jar_path = deps.join(host_jar_filename); - - std::fs::create_dir_all(&deps)?; - - if !host_jar_path.exists() { - log::info!("Host library JAR not found at {:?}, writing embedded JAR.", host_jar_path); - std::fs::write(&host_jar_path, LIBRARY_PATH)?; - log::info!("Host library JAR written to {:?}", host_jar_path); + let hash_filename = format!("{}.sha256", host_jar_filename); + let hash_file_path = deps.join(hash_filename); + + fs::create_dir_all(&deps)?; + + let embedded_jar_hash = { + let mut hasher = Sha256::new(); + hasher.update(LIBRARY_PATH); + format!("{:x}", hasher.finalize()) + }; + + let stored_hash = fs::read_to_string(&hash_file_path).ok(); + + let should_update = match stored_hash { + Some(stored) => { + if stored.trim() == embedded_jar_hash { + log::debug!("Host library JAR hash matches stored hash. No update needed."); + false + } else { + log::info!("Host library JAR hash differs from stored hash. Update required."); + true + } + } + None => { + log::info!("Host library JAR hash file not found. Update required."); + true + } + }; + + if should_update { + log::info!("Writing (or updating) Host library JAR to {:?}.", host_jar_path); + fs::write(&host_jar_path, LIBRARY_PATH)?; + log::info!("Host library JAR written to {:?}.", host_jar_path); + + fs::write(&hash_file_path, &embedded_jar_hash)?; + log::debug!("Host library JAR hash written to {:?}.", hash_file_path); } else { - log::debug!("Host library JAR found at {:?}", host_jar_path); + log::debug!("Host library JAR at {:?} is up-to-date.", host_jar_path); } let jvm_args = InitArgsBuilder::new() @@ -59,7 +90,8 @@ impl JavaContext { let jvm_args = jvm_args.build()?; let jvm = JavaVM::new(jvm_args)?; - info!("JDB debugger enabled on localhost:6741"); + #[cfg(feature = "editor")] + success!("JDB debugger enabled on localhost:6741"); log::info!("Created JVM instance"); @@ -71,8 +103,7 @@ impl JavaContext { }) } - pub fn init(&mut self, jar_path: impl AsRef<Path>, world: WorldPtr) -> anyhow::Result<()> { - self.jar_path = jar_path.as_ref().to_owned(); + pub fn init(&mut self, world: WorldPtr) -> anyhow::Result<()> { let mut env = self.jvm.attach_current_thread()?; if let Some(old_ref) = self.dropbear_engine_class.take() { @@ -353,44 +384,45 @@ impl Drop for JavaContext { } } - - +#[unsafe(no_mangle)] +// JNIEXPORT jlong JNICALL Java_com_dropbear_ffi_JNINative_getEntity +// (JNIEnv *, jobject, jlong, jstring); pub fn Java_com_dropbear_ffi_JNINative_getEntity( mut env: JNIEnv, _obj: jobject, world_handle: jlong, label: JString, ) -> jlong { - eprintln!("JNI call started"); - eprintln!("world_handle: {}", world_handle); - eprintln!("label ptr: {:p}", label.as_raw()); - - if world_handle == 0 { - eprintln!("ERROR: world_handle is null!"); - return -1; - } - - let label_result = env.get_string(&label); - if label_result.is_err() { - eprintln!("ERROR: Failed to get string: {:?}", label_result.err()); - return -1; - } - let label = label_result.unwrap(); + let label_jni_result = env.get_string(&label); + let label_str = match label_jni_result { + Ok(java_string) => { + match java_string.to_str() { + Ok(rust_str) => rust_str.to_string(), + Err(e) => { + println!("[Java_com_dropbear_ffi_JNINative_getEntity] [ERROR] Failed to convert Java string to Rust string: {}", e); + return -1; + } + } + }, + Err(e) => { + println!("[Java_com_dropbear_ffi_JNINative_getEntity] [ERROR] Failed to get string from JNI: {}", e); + return -1; + } + }; let world = world_handle as *mut World; if world.is_null() { - eprintln!("ERROR: world pointer is null!"); + println!("[Java_com_dropbear_ffi_JNINative_getEntity] [ERROR] World pointer is null in Java_com_dropbear_ffi_JNINative_getEntity"); return -1; } let world = unsafe { &mut *world }; - let rust_label = label.to_str().unwrap().to_string(); for (id, entity) in world.query::<&AdoptedEntity>().iter() { - if entity.model.label == rust_label { - return jlong::from(id.id()); + if entity.model.label == label_str { + return id.id() as jlong; } } - jlong::from(-1) -} + -1 +} @@ -1,4 +1,3 @@ -use std::error::Error; use jni::JNIEnv; use jni::objects::JThrowable; @@ -659,7 +659,9 @@ impl InspectableComponent for AdoptedEntity { } cfg.label_last_edit = None; } - }) + }); + + ui.label(format!("Entity ID: {}", entity.id())); }); } } @@ -238,9 +238,7 @@ impl Mouse for Editor { #[cfg(target_os = "linux")] // this impl doesn't have the mouse being recentered back to the center (to be fixed), this works as a usable alternative for now fn mouse_move(&mut self, position: PhysicalPosition<f64>) { - if (self.is_viewport_focused && matches!(self.viewport_mode, ViewportMode::CameraMove)) - || (matches!(self.editor_state, EditorState::Playing) - && !self.input_state.is_cursor_locked) + if self.is_viewport_focused && matches!(self.viewport_mode, ViewportMode::CameraMove) { if let Some(last_pos) = self.input_state.last_mouse_pos { let dx = position.x - last_pos.0; @@ -266,37 +264,34 @@ impl Mouse for Editor { #[cfg(not(target_os = "linux"))] // for some reason, this doesn't work on linux but works on windows (not tested on anywhere else) fn mouse_move(&mut self, position: PhysicalPosition<f64>) { - // if ((self.is_viewport_focused && matches!(self.viewport_mode, ViewportMode::CameraMove)) - // || (matches!(self.editor_state, EditorState::Playing) - // && !self.input_state.is_cursor_locked)) - // && let Some(window) = &self.window - // { - // let size = window.inner_size(); - // let center = PhysicalPosition::new(size.width as f64 / 2.0, size.height as f64 / 2.0); - // - // let distance_from_center = - // ((position.x - center.x).powi(2) + (position.y - center.y).powi(2)).sqrt(); - // - // if distance_from_center > 5.0 { - // let dx = position.x - center.x; - // let dy = position.y - center.y; - // - // if let Some(active_camera) = *self.active_camera.lock() - // && let Ok(mut q) = self.world.query_one::<( - // &mut Camera, - // &CameraComponent, - // // Option<&CameraFollowTarget>, - // )>(active_camera) - // && let Some((camera, _)) = q.get() - // { - // camera.track_mouse_delta(dx, dy); - // } - // - // let _ = window.set_cursor_position(center); - // } - // - // window.set_cursor_visible(false); - // } + if (self.is_viewport_focused && matches!(self.viewport_mode, ViewportMode::CameraMove)) + && let Some(window) = &self.window + { + let size = window.inner_size(); + let center = PhysicalPosition::new(size.width as f64 / 2.0, size.height as f64 / 2.0); + + let distance_from_center = + ((position.x - center.x).powi(2) + (position.y - center.y).powi(2)).sqrt(); + + if distance_from_center > 5.0 { + let dx = position.x - center.x; + let dy = position.y - center.y; + + if let Some(active_camera) = *self.active_camera.lock() + && let Ok(mut q) = self.world.query_one::<( + &mut Camera, + &CameraComponent, + )>(active_camera) + && let Some((camera, _)) = q.get() + { + camera.track_mouse_delta(dx, dy); + } + + let _ = window.set_cursor_position(center); + } + + window.set_cursor_visible(false); + } self.input_state.mouse_pos = (position.x, position.y); } @@ -3,6 +3,7 @@ import org.gradle.kotlin.dsl.compileOnly plugins { `kotlin-dsl` `maven-publish` + id("com.gradle.plugin-publish") version "2.0.0" } group = "com.dropbear" @@ -18,11 +19,17 @@ dependencies { } gradlePlugin { + website.set("https://github.com/4tkbytes/dropbear") + vcsUrl.set("https://github.com/4tkbytes/dropbear") plugins { - create("dropbearPlugin") { + + create("magnaCartaPlugin") { id = "magna-carta" implementationClass = "com.dropbear.magna_carta.MagnaCartaPlugin" - version = "1.0-SNAPSHOT" + displayName = "magna-carta plugin" + description = "Gradle plugin for generating manifests from annotation data during compile time" + + " for use with KMP and the dropbear engine" + version = version as String } } }