Use entity instead of player
This commit is contained in:
parent
26b9727166
commit
4a906ae3dc
@ -4,11 +4,11 @@ import java.lang.foreign.*;
|
|||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
public class NativePatchBukkit {
|
public class NativePatchBukkit {
|
||||||
|
|
||||||
private static final Linker LINKER = Linker.nativeLinker();
|
private static final Linker LINKER = Linker.nativeLinker();
|
||||||
|
|
||||||
private static MethodHandle sendMessageNative;
|
private static MethodHandle sendMessageNative;
|
||||||
@ -18,7 +18,8 @@ public class NativePatchBukkit {
|
|||||||
private static MethodHandle getLocationNative;
|
private static MethodHandle getLocationNative;
|
||||||
|
|
||||||
// Struct layout matching Rust's #[repr(C)] AbilitiesFFI
|
// Struct layout matching Rust's #[repr(C)] AbilitiesFFI
|
||||||
private static final StructLayout ABILITIES_LAYOUT = MemoryLayout.structLayout(
|
private static final StructLayout ABILITIES_LAYOUT =
|
||||||
|
MemoryLayout.structLayout(
|
||||||
ValueLayout.JAVA_BOOLEAN.withName("invulnerable"),
|
ValueLayout.JAVA_BOOLEAN.withName("invulnerable"),
|
||||||
ValueLayout.JAVA_BOOLEAN.withName("flying"),
|
ValueLayout.JAVA_BOOLEAN.withName("flying"),
|
||||||
ValueLayout.JAVA_BOOLEAN.withName("allow_flying"),
|
ValueLayout.JAVA_BOOLEAN.withName("allow_flying"),
|
||||||
@ -31,20 +32,27 @@ public class NativePatchBukkit {
|
|||||||
|
|
||||||
// VarHandles for accessing struct fields
|
// VarHandles for accessing struct fields
|
||||||
private static final VarHandle INVULNERABLE = ABILITIES_LAYOUT.varHandle(
|
private static final VarHandle INVULNERABLE = ABILITIES_LAYOUT.varHandle(
|
||||||
MemoryLayout.PathElement.groupElement("invulnerable"));
|
MemoryLayout.PathElement.groupElement("invulnerable")
|
||||||
|
);
|
||||||
private static final VarHandle FLYING = ABILITIES_LAYOUT.varHandle(
|
private static final VarHandle FLYING = ABILITIES_LAYOUT.varHandle(
|
||||||
MemoryLayout.PathElement.groupElement("flying"));
|
MemoryLayout.PathElement.groupElement("flying")
|
||||||
|
);
|
||||||
private static final VarHandle ALLOW_FLYING = ABILITIES_LAYOUT.varHandle(
|
private static final VarHandle ALLOW_FLYING = ABILITIES_LAYOUT.varHandle(
|
||||||
MemoryLayout.PathElement.groupElement("allow_flying"));
|
MemoryLayout.PathElement.groupElement("allow_flying")
|
||||||
|
);
|
||||||
private static final VarHandle CREATIVE = ABILITIES_LAYOUT.varHandle(
|
private static final VarHandle CREATIVE = ABILITIES_LAYOUT.varHandle(
|
||||||
MemoryLayout.PathElement.groupElement("creative"));
|
MemoryLayout.PathElement.groupElement("creative")
|
||||||
private static final VarHandle ALLOW_MODIFY_WORLD = ABILITIES_LAYOUT.varHandle(
|
);
|
||||||
MemoryLayout.PathElement.groupElement("allow_modify_world"));
|
private static final VarHandle ALLOW_MODIFY_WORLD =
|
||||||
|
ABILITIES_LAYOUT.varHandle(
|
||||||
|
MemoryLayout.PathElement.groupElement("allow_modify_world")
|
||||||
|
);
|
||||||
private static final VarHandle FLY_SPEED = ABILITIES_LAYOUT.varHandle(
|
private static final VarHandle FLY_SPEED = ABILITIES_LAYOUT.varHandle(
|
||||||
MemoryLayout.PathElement.groupElement("fly_speed"));
|
MemoryLayout.PathElement.groupElement("fly_speed")
|
||||||
|
);
|
||||||
private static final VarHandle WALK_SPEED = ABILITIES_LAYOUT.varHandle(
|
private static final VarHandle WALK_SPEED = ABILITIES_LAYOUT.varHandle(
|
||||||
MemoryLayout.PathElement.groupElement("walk_speed"));
|
MemoryLayout.PathElement.groupElement("walk_speed")
|
||||||
|
);
|
||||||
|
|
||||||
// Struct layout for Vec3
|
// Struct layout for Vec3
|
||||||
private static final StructLayout VEC3_LAYOUT = MemoryLayout.structLayout(
|
private static final StructLayout VEC3_LAYOUT = MemoryLayout.structLayout(
|
||||||
@ -55,15 +63,17 @@ public class NativePatchBukkit {
|
|||||||
|
|
||||||
// VarHandles for Vec3 fields
|
// VarHandles for Vec3 fields
|
||||||
private static final VarHandle VEC3_X = VEC3_LAYOUT.varHandle(
|
private static final VarHandle VEC3_X = VEC3_LAYOUT.varHandle(
|
||||||
MemoryLayout.PathElement.groupElement("x"));
|
MemoryLayout.PathElement.groupElement("x")
|
||||||
|
);
|
||||||
private static final VarHandle VEC3_Y = VEC3_LAYOUT.varHandle(
|
private static final VarHandle VEC3_Y = VEC3_LAYOUT.varHandle(
|
||||||
MemoryLayout.PathElement.groupElement("y"));
|
MemoryLayout.PathElement.groupElement("y")
|
||||||
|
);
|
||||||
private static final VarHandle VEC3_Z = VEC3_LAYOUT.varHandle(
|
private static final VarHandle VEC3_Z = VEC3_LAYOUT.varHandle(
|
||||||
MemoryLayout.PathElement.groupElement("z"));
|
MemoryLayout.PathElement.groupElement("z")
|
||||||
|
);
|
||||||
|
|
||||||
public record Vec3(double x, double y, double z) {}
|
public record Vec3(double x, double y, double z) {}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Java record to hold player abilities.
|
* Java record to hold player abilities.
|
||||||
*/
|
*/
|
||||||
@ -78,38 +88,100 @@ public class NativePatchBukkit {
|
|||||||
) {
|
) {
|
||||||
// "Wither" methods - return a copy with one field changed
|
// "Wither" methods - return a copy with one field changed
|
||||||
public Abilities withInvulnerable(boolean value) {
|
public Abilities withInvulnerable(boolean value) {
|
||||||
return new Abilities(value, flying, allowFlying, creative, allowModifyWorld, flySpeed, walkSpeed);
|
return new Abilities(
|
||||||
|
value,
|
||||||
|
flying,
|
||||||
|
allowFlying,
|
||||||
|
creative,
|
||||||
|
allowModifyWorld,
|
||||||
|
flySpeed,
|
||||||
|
walkSpeed
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Abilities withFlying(boolean value) {
|
public Abilities withFlying(boolean value) {
|
||||||
return new Abilities(invulnerable, value, allowFlying, creative, allowModifyWorld, flySpeed, walkSpeed);
|
return new Abilities(
|
||||||
|
invulnerable,
|
||||||
|
value,
|
||||||
|
allowFlying,
|
||||||
|
creative,
|
||||||
|
allowModifyWorld,
|
||||||
|
flySpeed,
|
||||||
|
walkSpeed
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Abilities withAllowFlying(boolean value) {
|
public Abilities withAllowFlying(boolean value) {
|
||||||
return new Abilities(invulnerable, flying, value, creative, allowModifyWorld, flySpeed, walkSpeed);
|
return new Abilities(
|
||||||
|
invulnerable,
|
||||||
|
flying,
|
||||||
|
value,
|
||||||
|
creative,
|
||||||
|
allowModifyWorld,
|
||||||
|
flySpeed,
|
||||||
|
walkSpeed
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Abilities withCreative(boolean value) {
|
public Abilities withCreative(boolean value) {
|
||||||
return new Abilities(invulnerable, flying, allowFlying, value, allowModifyWorld, flySpeed, walkSpeed);
|
return new Abilities(
|
||||||
|
invulnerable,
|
||||||
|
flying,
|
||||||
|
allowFlying,
|
||||||
|
value,
|
||||||
|
allowModifyWorld,
|
||||||
|
flySpeed,
|
||||||
|
walkSpeed
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Abilities withAllowModifyWorld(boolean value) {
|
public Abilities withAllowModifyWorld(boolean value) {
|
||||||
return new Abilities(invulnerable, flying, allowFlying, creative, value, flySpeed, walkSpeed);
|
return new Abilities(
|
||||||
|
invulnerable,
|
||||||
|
flying,
|
||||||
|
allowFlying,
|
||||||
|
creative,
|
||||||
|
value,
|
||||||
|
flySpeed,
|
||||||
|
walkSpeed
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Abilities withFlySpeed(float value) {
|
public Abilities withFlySpeed(float value) {
|
||||||
return new Abilities(invulnerable, flying, allowFlying, creative, allowModifyWorld, value, walkSpeed);
|
return new Abilities(
|
||||||
|
invulnerable,
|
||||||
|
flying,
|
||||||
|
allowFlying,
|
||||||
|
creative,
|
||||||
|
allowModifyWorld,
|
||||||
|
value,
|
||||||
|
walkSpeed
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Abilities withWalkSpeed(float value) {
|
public Abilities withWalkSpeed(float value) {
|
||||||
return new Abilities(invulnerable, flying, allowFlying, creative, allowModifyWorld, flySpeed, value);
|
return new Abilities(
|
||||||
|
invulnerable,
|
||||||
|
flying,
|
||||||
|
allowFlying,
|
||||||
|
creative,
|
||||||
|
allowModifyWorld,
|
||||||
|
flySpeed,
|
||||||
|
value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called from Rust during initialization to register native function pointers.
|
* Called from Rust during initialization to register native function pointers.
|
||||||
*/
|
*/
|
||||||
public static void initCallbacks(long sendMessageAddr, long registerEventAddr, long getAbilitiesAddr, long setAbilitiesAddr, long getLocationAddr) {
|
public static void initCallbacks(
|
||||||
|
long sendMessageAddr,
|
||||||
|
long registerEventAddr,
|
||||||
|
long getAbilitiesAddr,
|
||||||
|
long setAbilitiesAddr,
|
||||||
|
long getLocationAddr
|
||||||
|
) {
|
||||||
// void rust_send_message(const char* uuid, const char* message)
|
// void rust_send_message(const char* uuid, const char* message)
|
||||||
sendMessageNative = LINKER.downcallHandle(
|
sendMessageNative = LINKER.downcallHandle(
|
||||||
MemorySegment.ofAddress(sendMessageAddr),
|
MemorySegment.ofAddress(sendMessageAddr),
|
||||||
@ -177,7 +249,9 @@ public class NativePatchBukkit {
|
|||||||
// Simple approach - pass plugin name, handle lookup in Rust
|
// Simple approach - pass plugin name, handle lookup in Rust
|
||||||
try (Arena arena = Arena.ofConfined()) {
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
MemorySegment pluginName = arena.allocateFrom(plugin.getName());
|
MemorySegment pluginName = arena.allocateFrom(plugin.getName());
|
||||||
MemorySegment listenerClass = arena.allocateFrom(listener.getClass().getName());
|
MemorySegment listenerClass = arena.allocateFrom(
|
||||||
|
listener.getClass().getName()
|
||||||
|
);
|
||||||
registerEventNative.invokeExact(listenerClass, pluginName);
|
registerEventNative.invokeExact(listenerClass, pluginName);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new RuntimeException("Failed to register event", t);
|
throw new RuntimeException("Failed to register event", t);
|
||||||
@ -195,7 +269,10 @@ public class NativePatchBukkit {
|
|||||||
MemorySegment uuidStr = arena.allocateFrom(uuid.toString());
|
MemorySegment uuidStr = arena.allocateFrom(uuid.toString());
|
||||||
MemorySegment outStruct = arena.allocate(ABILITIES_LAYOUT);
|
MemorySegment outStruct = arena.allocate(ABILITIES_LAYOUT);
|
||||||
|
|
||||||
boolean success = (boolean) getAbilitiesNative.invokeExact(uuidStr, outStruct);
|
boolean success = (boolean) getAbilitiesNative.invokeExact(
|
||||||
|
uuidStr,
|
||||||
|
outStruct
|
||||||
|
);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return null;
|
return null;
|
||||||
@ -225,11 +302,18 @@ public class NativePatchBukkit {
|
|||||||
FLYING.set(abilitiesStruct, 0L, abilities.flying());
|
FLYING.set(abilitiesStruct, 0L, abilities.flying());
|
||||||
ALLOW_FLYING.set(abilitiesStruct, 0L, abilities.allowFlying());
|
ALLOW_FLYING.set(abilitiesStruct, 0L, abilities.allowFlying());
|
||||||
CREATIVE.set(abilitiesStruct, 0L, abilities.creative());
|
CREATIVE.set(abilitiesStruct, 0L, abilities.creative());
|
||||||
ALLOW_MODIFY_WORLD.set(abilitiesStruct, 0L, abilities.allowModifyWorld());
|
ALLOW_MODIFY_WORLD.set(
|
||||||
|
abilitiesStruct,
|
||||||
|
0L,
|
||||||
|
abilities.allowModifyWorld()
|
||||||
|
);
|
||||||
FLY_SPEED.set(abilitiesStruct, 0L, abilities.flySpeed());
|
FLY_SPEED.set(abilitiesStruct, 0L, abilities.flySpeed());
|
||||||
WALK_SPEED.set(abilitiesStruct, 0L, abilities.walkSpeed());
|
WALK_SPEED.set(abilitiesStruct, 0L, abilities.walkSpeed());
|
||||||
|
|
||||||
return (boolean) setAbilitiesNative.invokeExact(uuidStr, abilitiesStruct);
|
return (boolean) setAbilitiesNative.invokeExact(
|
||||||
|
uuidStr,
|
||||||
|
abilitiesStruct
|
||||||
|
);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new RuntimeException("Failed to call native setAbilities", t);
|
throw new RuntimeException("Failed to call native setAbilities", t);
|
||||||
}
|
}
|
||||||
@ -246,7 +330,10 @@ public class NativePatchBukkit {
|
|||||||
MemorySegment uuidStr = arena.allocateFrom(uuid.toString());
|
MemorySegment uuidStr = arena.allocateFrom(uuid.toString());
|
||||||
MemorySegment outStruct = arena.allocate(VEC3_LAYOUT);
|
MemorySegment outStruct = arena.allocate(VEC3_LAYOUT);
|
||||||
|
|
||||||
boolean success = (boolean) getLocationNative.invokeExact(uuidStr, outStruct);
|
boolean success = (boolean) getLocationNative.invokeExact(
|
||||||
|
uuidStr,
|
||||||
|
outStruct
|
||||||
|
);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
8
rust/Cargo.lock
generated
8
rust/Cargo.lock
generated
@ -1875,15 +1875,15 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portable-atomic"
|
name = "portable-atomic"
|
||||||
version = "1.13.0"
|
version = "1.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950"
|
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portable-atomic-util"
|
name = "portable-atomic-util"
|
||||||
version = "0.2.4"
|
version = "0.2.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
|
checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
use std::ffi::c_char;
|
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};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -13,10 +15,14 @@ pub extern "C" fn rust_get_location(uuid_ptr: *const c_char, out: *mut Vec3FFI)
|
|||||||
let uuid_str = get_string(uuid_ptr);
|
let uuid_str = get_string(uuid_ptr);
|
||||||
if let Some(ctx) = CALLBACK_CONTEXT.get() {
|
if let Some(ctx) = CALLBACK_CONTEXT.get() {
|
||||||
let uuid = uuid::Uuid::parse_str(&uuid_str).unwrap();
|
let uuid = uuid::Uuid::parse_str(&uuid_str).unwrap();
|
||||||
let player = ctx.plugin_context.server.get_player_by_uuid(uuid);
|
let entity = ctx
|
||||||
if let Some(player) = player {
|
.plugin_context
|
||||||
|
.server
|
||||||
|
.select_entities(&TargetSelector::new(EntitySelectorType::Uuid(uuid)), None);
|
||||||
|
if entity.len() == 1 {
|
||||||
|
let entity = entity.first().unwrap().get_entity();
|
||||||
let position =
|
let position =
|
||||||
tokio::task::block_in_place(|| ctx.runtime.block_on(async { player.position() }));
|
tokio::task::block_in_place(|| ctx.runtime.block_on(async { entity.pos.load() }));
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
(*out).x = position.x;
|
(*out).x = position.x;
|
||||||
|
|||||||
@ -9,6 +9,7 @@ pub mod events;
|
|||||||
pub mod location;
|
pub mod location;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
pub mod world;
|
||||||
|
|
||||||
static CALLBACK_CONTEXT: OnceLock<CallbackContext> = OnceLock::new();
|
static CALLBACK_CONTEXT: OnceLock<CallbackContext> = OnceLock::new();
|
||||||
|
|
||||||
|
|||||||
27
rust/src/java/native_callbacks/world.rs
Normal file
27
rust/src/java/native_callbacks/world.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use std::ffi::{CString, c_char};
|
||||||
|
|
||||||
|
use pumpkin::command::args::entities::{EntitySelectorType, TargetSelector};
|
||||||
|
|
||||||
|
use crate::java::native_callbacks::{CALLBACK_CONTEXT, utils::get_string};
|
||||||
|
|
||||||
|
pub extern "C" fn rust_get_world(uuid_ptr: *const c_char) -> *const c_char {
|
||||||
|
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 world = entity.world.load();
|
||||||
|
|
||||||
|
let cstring = match CString::new(world.dimension.minecraft_name) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(_) => return std::ptr::null(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ptr::null()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user