From 4829d59c1ee8dc482288753fc0d9940e9fab04b6 Mon Sep 17 00:00:00 2001 From: Bjorn Beishline <75190918+BjornTheProgrammer@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:12:09 -0700 Subject: [PATCH] Refactor get location --- .../patchbukkit/bridge/NativePatchBukkit.java | 41 ------------- .../patchbukkit/entity/PatchBukkitEntity.java | 8 ++- proto/patchbukkit/bridge.proto | 4 ++ proto/patchbukkit/common/types.proto | 17 ++++++ rust/src/java/native_callbacks/abilities.rs | 2 +- rust/src/java/native_callbacks/location.rs | 58 ++++++++++++------- rust/src/java/native_callbacks/mod.rs | 2 - 7 files changed, 65 insertions(+), 67 deletions(-) diff --git a/java/patchbukkit/src/main/java/org/patchbukkit/bridge/NativePatchBukkit.java b/java/patchbukkit/src/main/java/org/patchbukkit/bridge/NativePatchBukkit.java index 999dd8c..d8ff5a9 100644 --- a/java/patchbukkit/src/main/java/org/patchbukkit/bridge/NativePatchBukkit.java +++ b/java/patchbukkit/src/main/java/org/patchbukkit/bridge/NativePatchBukkit.java @@ -14,7 +14,6 @@ public class NativePatchBukkit { private static final Linker LINKER = Linker.nativeLinker(); - private static MethodHandle getLocationNative; private static MethodHandle getWorldNative; private static MethodHandle freeStringNative; private static MethodHandle getRegistryDataNative; @@ -180,22 +179,12 @@ public class NativePatchBukkit { * Called from Rust during initialization to register native function pointers. */ public static void initCallbacks( - long getLocationAddr, long freeStringAddr, long getWorldAddr, long getRegistryDataAddr, long playerEntityPlaySoundAddr, long playerPlaySoundAddr ) { - // bool rust_get_location(const char* uuid, Vec3FFI* out) - getLocationNative = LINKER.downcallHandle( - MemorySegment.ofAddress(getLocationAddr), - FunctionDescriptor.of( - ValueLayout.JAVA_BOOLEAN, // return type - ValueLayout.ADDRESS, // uuid string - ValueLayout.ADDRESS // out pointer to Vec3FFI - ) - ); // const char* rust_get_world(const char* uuid) getWorldNative = LINKER.downcallHandle( @@ -246,36 +235,6 @@ public class NativePatchBukkit { ); } - /** - * Get a player's location by UUID. - * - * @param uuid The player's UUID - * @return The player's position, or null if player not found - */ - public static Vec3 getLocation(UUID uuid) { - try (Arena arena = Arena.ofConfined()) { - MemorySegment uuidStr = arena.allocateFrom(uuid.toString()); - MemorySegment outStruct = arena.allocate(VEC3_LAYOUT); - - boolean success = (boolean) getLocationNative.invokeExact( - uuidStr, - outStruct - ); - - if (!success) { - return null; - } - - return new Vec3( - (double) VEC3_X.get(outStruct, 0L), - (double) VEC3_Y.get(outStruct, 0L), - (double) VEC3_Z.get(outStruct, 0L) - ); - } catch (Throwable t) { - throw new RuntimeException("Failed to call native getLocation", t); - } - } - /** * Free a string allocated by the Rust side. */ diff --git a/java/patchbukkit/src/main/java/org/patchbukkit/entity/PatchBukkitEntity.java b/java/patchbukkit/src/main/java/org/patchbukkit/entity/PatchBukkitEntity.java index b2abfaa..1a5978f 100644 --- a/java/patchbukkit/src/main/java/org/patchbukkit/entity/PatchBukkitEntity.java +++ b/java/patchbukkit/src/main/java/org/patchbukkit/entity/PatchBukkitEntity.java @@ -37,6 +37,7 @@ import org.bukkit.util.BoundingBox; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.patchbukkit.bridge.BridgeUtils; import org.patchbukkit.bridge.NativePatchBukkit; import org.patchbukkit.world.PatchBukkitWorld; @@ -47,6 +48,7 @@ import io.papermc.paper.entity.TeleportFlag; import io.papermc.paper.threadedregions.scheduler.EntityScheduler; import net.kyori.adventure.text.Component; import net.kyori.adventure.util.TriState; +import patchbukkit.bridge.NativeBridgeFfi; public class PatchBukkitEntity implements Entity { @@ -262,8 +264,10 @@ public class PatchBukkitEntity implements Entity { @Override public @NotNull Location getLocation() { - var loc = NativePatchBukkit.getLocation(this.uuid); - return new Location(this.getWorld(), loc.x(), loc.y(), loc.z()); + var location = NativeBridgeFfi.getLocation(BridgeUtils.convertUuid(this.uuid)); + var world = PatchBukkitWorld.getOrCreate(BridgeUtils.convertUuid(location.getWorld().getUuid())); + var position = location.getPosition(); + return new Location(world, position.getX(), position.getY(), position.getZ(), location.getYaw(), location.getPitch()); } @Override diff --git a/proto/patchbukkit/bridge.proto b/proto/patchbukkit/bridge.proto index 7c75ff9..a4e7d8b 100644 --- a/proto/patchbukkit/bridge.proto +++ b/proto/patchbukkit/bridge.proto @@ -11,7 +11,11 @@ import "patchbukkit/message.proto"; service NativeBridge { rpc GetAbilities(patchbukkit.common.UUID) returns (patchbukkit.abilities.Abilities); rpc SetAbilities(patchbukkit.abilities.SetAbilitiesRequest) returns (patchbukkit.abilities.SetAbilitiesResponse); + rpc RegisterEvent(patchbukkit.events.RegisterEventRequest) returns (google.protobuf.Empty); rpc CallEvent(patchbukkit.events.CallEventRequest) returns (patchbukkit.events.CallEventResponse); + rpc SendMessage(patchbukkit.message.SendMessageRequest) returns (google.protobuf.Empty); + + rpc GetLocation(patchbukkit.common.UUID) returns (patchbukkit.common.Location); } diff --git a/proto/patchbukkit/common/types.proto b/proto/patchbukkit/common/types.proto index fca30a2..03d7341 100644 --- a/proto/patchbukkit/common/types.proto +++ b/proto/patchbukkit/common/types.proto @@ -8,3 +8,20 @@ option java_package = "patchbukkit.common"; message UUID { string value = 1; } + +message Vec3 { + double x = 1; + double y = 2; + double z = 3; +} + +message World { + UUID uuid = 1; +} + +message Location { + World world = 1; + Vec3 position = 2; + float yaw = 3; + float pitch = 4; +} diff --git a/rust/src/java/native_callbacks/abilities.rs b/rust/src/java/native_callbacks/abilities.rs index 6bdbdf0..ccb2cd4 100644 --- a/rust/src/java/native_callbacks/abilities.rs +++ b/rust/src/java/native_callbacks/abilities.rs @@ -6,7 +6,7 @@ use crate::proto::patchbukkit::{ pub fn ffi_native_bridge_get_abilities_impl(request: Uuid) -> Option { let ctx = CALLBACK_CONTEXT.get()?; - let player_uuid = uuid::Uuid::parse_str(&request.value).unwrap(); + let player_uuid = uuid::Uuid::parse_str(&request.value).ok()?; let mut abilities = Abilities::default(); let player = ctx.plugin_context.server.get_player_by_uuid(player_uuid)?; let pumpkin_abilities = tokio::task::block_in_place(|| { diff --git a/rust/src/java/native_callbacks/location.rs b/rust/src/java/native_callbacks/location.rs index 8526385..9ba6ff2 100644 --- a/rust/src/java/native_callbacks/location.rs +++ b/rust/src/java/native_callbacks/location.rs @@ -2,7 +2,10 @@ use std::ffi::c_char; use pumpkin::command::args::entities::{EntitySelectorType, TargetSelector}; -use crate::java::native_callbacks::{CALLBACK_CONTEXT, utils::get_string}; +use crate::{ + java::native_callbacks::{CALLBACK_CONTEXT, utils::get_string}, + proto::patchbukkit::common::{Location, Uuid, Vec3, World}, +}; #[repr(C)] pub struct Vec3FFI { @@ -11,28 +14,41 @@ pub struct Vec3FFI { pub z: f64, } -pub extern "C" fn rust_get_location(uuid_ptr: *const c_char, out: *mut Vec3FFI) -> bool { - let uuid_str = get_string(uuid_ptr); - if let Some(ctx) = CALLBACK_CONTEXT.get() { - let uuid = uuid::Uuid::parse_str(&uuid_str).unwrap(); - let entity = ctx - .plugin_context - .server - .select_entities(&TargetSelector::new(EntitySelectorType::Uuid(uuid)), None); - if entity.len() == 1 { - let entity = entity.first().unwrap().get_entity(); - let position = - tokio::task::block_in_place(|| ctx.runtime.block_on(async { entity.pos.load() })); +pub fn ffi_native_bridge_get_location_impl(entity_uuid: Uuid) -> Option { + let ctx = CALLBACK_CONTEXT.get()?; + let uuid = uuid::Uuid::parse_str(&entity_uuid.value).ok()?; - unsafe { - (*out).x = position.x; - (*out).y = position.y; - (*out).z = position.z; - } + let entity = ctx + .plugin_context + .server + .select_entities(&TargetSelector::new(EntitySelectorType::Uuid(uuid)), None); - return true; - } + if entity.len() == 1 { + let entity = entity.first().unwrap().get_entity(); + let position = entity.pos.load(); + let world = entity.world.load().uuid; + let yaw = entity.yaw.load(); + let pitch = entity.pitch.load(); + + let mut response_position = Vec3::default(); + response_position.x = position.x; + response_position.y = position.y; + response_position.z = position.z; + + let mut world_uuid = Uuid::default(); + world_uuid.value = world.to_string(); + + let mut response_world = World::default(); + response_world.uuid = Some(world_uuid); + + let mut location = Location::default(); + location.pitch = pitch; + location.position = Some(response_position); + location.world = Some(response_world); + location.yaw = yaw; + + return Some(location); } - false + None } diff --git a/rust/src/java/native_callbacks/mod.rs b/rust/src/java/native_callbacks/mod.rs index 03b62c0..8057a55 100644 --- a/rust/src/java/native_callbacks/mod.rs +++ b/rust/src/java/native_callbacks/mod.rs @@ -79,7 +79,6 @@ pub extern "C" fn rust_free_bytes(ptr: *mut u8, len: u32) { } pub fn initialize_callbacks(jvm: &Jvm) -> Result<()> { - let get_location_addr = location::rust_get_location as *const () as i64; let free_string_addr = memory::rust_free_string as *const () as i64; let get_world_addr = world::rust_get_world as *const () as i64; let rust_get_registry_data_addr = registry::rust_get_registry_data as *const () as i64; @@ -91,7 +90,6 @@ pub fn initialize_callbacks(jvm: &Jvm) -> Result<()> { "org.patchbukkit.bridge.NativePatchBukkit", "initCallbacks", &[ - InvocationArg::try_from(get_location_addr)?.into_primitive()?, InvocationArg::try_from(free_string_addr)?.into_primitive()?, InvocationArg::try_from(get_world_addr)?.into_primitive()?, InvocationArg::try_from(rust_get_registry_data_addr)?.into_primitive()?,