MinecraftConsoles/Minecraft.Server.FourKit/FourKitHost.Events.cs
2026-03-24 21:13:15 -05:00

977 lines
34 KiB
C#

using System.Runtime.InteropServices;
using Minecraft.Server.FourKit.Block;
using Minecraft.Server.FourKit.Entity;
using Minecraft.Server.FourKit.Event;
using Minecraft.Server.FourKit.Event.Block;
using Minecraft.Server.FourKit.Event.Entity;
using Minecraft.Server.FourKit.Event.Player;
using Minecraft.Server.FourKit.Event.Inventory;
using Minecraft.Server.FourKit.Inventory;
namespace Minecraft.Server.FourKit;
public static partial class FourKitHost
{
[UnmanagedCallersOnly]
public static void FirePlayerJoin(int entityId, IntPtr namePtr, int nameByteLen, IntPtr uuidPtr, int uuidByteLen)
{
try
{
string name = nameByteLen > 0
? Marshal.PtrToStringUTF8(namePtr, nameByteLen) ?? string.Empty
: string.Empty;
string uuidStr = uuidByteLen > 0
? Marshal.PtrToStringUTF8(uuidPtr, uuidByteLen) ?? string.Empty
: string.Empty;
var player = FourKit.TrackPlayer(entityId, name);
player.SetPlayerUniqueIdInternal(ParseOrHashGuid(uuidStr));
SyncPlayerFromNative(player);
var evt = new PlayerJoinEvent(player);
FourKit.FireEvent(evt);
BroadcastNativeMessage(evt.getJoinMessage());
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerJoin error: {ex}");
}
}
[UnmanagedCallersOnly]
public static void FirePlayerQuit(int entityId)
{
try
{
var player = FourKit.UntrackPlayer(entityId);
if (player != null)
{
SyncPlayerFromNative(player);
var evt = new PlayerQuitEvent(player);
FourKit.FireEvent(evt);
BroadcastNativeMessage(evt.getQuitMessage());
}
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerQuit error: {ex}");
}
}
[UnmanagedCallersOnly]
public static int FirePlayerKick(int entityId, int disconnectReason,
IntPtr reasonPtr, int reasonByteLen,
IntPtr outBuf, int outBufSize, IntPtr outLenPtr)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
{
Marshal.WriteInt32(outLenPtr, 0);
return 0;
}
SyncPlayerFromNative(player);
var reason = Enum.IsDefined(typeof(DisconnectReason), disconnectReason)
? (DisconnectReason)disconnectReason
: DisconnectReason.NONE;
string defaultLeave = $"{player.getName()} was kicked from the game";
var evt = new PlayerKickEvent(player, reason, defaultLeave);
FourKit.FireEvent(evt);
if (evt.isCancelled())
{
Marshal.WriteInt32(outLenPtr, 0);
return 1;
}
string leaveMessage = evt.getLeaveMessage();
if (!string.IsNullOrEmpty(leaveMessage))
{
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(leaveMessage);
if (utf8Bytes.Length < outBufSize)
{
Marshal.Copy(utf8Bytes, 0, outBuf, utf8Bytes.Length);
Marshal.WriteInt32(outLenPtr, utf8Bytes.Length);
}
else
{
Marshal.WriteInt32(outLenPtr, 0);
}
}
else
{
Marshal.WriteInt32(outLenPtr, 0);
}
return 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerKick error: {ex}");
Marshal.WriteInt32(outLenPtr, 0);
return 0;
}
}
[UnmanagedCallersOnly]
public static int FirePlayerMove(int entityId,
double fromX, double fromY, double fromZ,
double toX, double toY, double toZ,
IntPtr outCoords)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
{
Marshal.Copy(new double[] { toX, toY, toZ }, 0, outCoords, 3);
return 0;
}
SyncPlayerFromNative(player);
var from = new Location(fromX, fromY, fromZ);
var to = new Location(toX, toY, toZ);
var evt = new PlayerMoveEvent(player, from, to);
FourKit.FireEvent(evt);
var finalTo = evt.getTo();
Marshal.Copy(new double[] { finalTo.X, finalTo.Y, finalTo.Z }, 0, outCoords, 3);
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerMove error: {ex}");
Marshal.Copy(new double[] { toX, toY, toZ }, 0, outCoords, 3);
return 0;
}
}
[UnmanagedCallersOnly]
public static void UpdatePlayerEntityId(int oldEntityId, int newEntityId)
{
try
{
FourKit.UpdatePlayerEntityId(oldEntityId, newEntityId);
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"UpdatePlayerEntityId error: {ex}");
}
}
[UnmanagedCallersOnly]
public static int FirePlayerChat(int entityId, IntPtr msgPtr, int msgByteLen,
IntPtr outBuf, int outBufSize, IntPtr outLenPtr)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
{
Marshal.WriteInt32(outLenPtr, 0);
return 0;
}
SyncPlayerFromNative(player);
string message = msgByteLen > 0
? Marshal.PtrToStringUTF8(msgPtr, msgByteLen) ?? string.Empty
: string.Empty;
var evt = new PlayerChatEvent(player, message);
FourKit.FireEvent(evt);
if (evt.isCancelled())
{
Marshal.WriteInt32(outLenPtr, 0);
return 1;
}
string formatted = JavaFormat(evt.getFormat(), player.getDisplayName(), evt.getMessage());
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(formatted);
if (utf8Bytes.Length < outBufSize)
{
Marshal.Copy(utf8Bytes, 0, outBuf, utf8Bytes.Length);
Marshal.WriteInt32(outLenPtr, utf8Bytes.Length);
}
else
{
Marshal.WriteInt32(outLenPtr, 0);
}
return 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerChat error: {ex}");
Marshal.WriteInt32(outLenPtr, 0);
return 0;
}
}
[UnmanagedCallersOnly]
public static int FireBlockPlace(int entityId, int dimId,
int placedX, int placedY, int placedZ,
int againstX, int againstY, int againstZ,
int itemId, int itemCount, int canBuild)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
return 0;
SyncPlayerFromNative(player);
var world = FourKit.getWorld(dimId);
var placedBlock = new Block.Block(world, placedX, placedY, placedZ);
var againstBlock = new Block.Block(world, againstX, againstY, againstZ);
Material mat = Enum.IsDefined(typeof(Material), itemId) ? (Material)itemId : Material.AIR;
var itemInHand = new ItemStack(mat, itemCount);
var evt = new BlockPlaceEvent(placedBlock, againstBlock, itemInHand, player, canBuild != 0);
FourKit.FireEvent(evt);
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FireBlockPlace error: {ex}");
return 0;
}
}
[UnmanagedCallersOnly]
public static int FireBlockBreak(int entityId, int dimId,
int x, int y, int z, int tileId, int data, int exp)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
return exp;
SyncPlayerFromNative(player);
var world = FourKit.getWorld(dimId);
var block = new Block.Block(world, x, y, z);
var evt = new BlockBreakEvent(block, player, exp);
FourKit.FireEvent(evt);
if (evt.isCancelled())
return -1;
return evt.getExpToDrop();
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FireBlockBreak error: {ex}");
return exp;
}
}
[UnmanagedCallersOnly]
public static int FireEntityDamage(int entityId, int entityTypeId, int dimId,
double x, double y, double z, int causeId, double damage, IntPtr outDamage,
int damagerEntityId, int damagerEntityTypeId,
double damagerX, double damagerY, double damagerZ)
{
try
{
Entity.Entity? entity = FourKit.GetPlayerByEntityId(entityId);
if (entity is Player player)
{
SyncPlayerFromNative(player);
}
else
{
var entityType = Enum.IsDefined(typeof(EntityType), entityTypeId)
? (EntityType)entityTypeId
: EntityType.UNKNOWN;
entity = new LivingEntity(entityId, entityType, dimId, x, y, z);
}
var cause = Enum.IsDefined(typeof(EntityDamageEvent.DamageCause), causeId)
? (EntityDamageEvent.DamageCause)causeId
: EntityDamageEvent.DamageCause.CUSTOM;
EntityDamageByEntityEvent? byEntityEvt = null;
if (damagerEntityId >= 0)
{
Entity.Entity? damager = FourKit.GetPlayerByEntityId(damagerEntityId);
if (damager is Player damagerPlayer)
{
SyncPlayerFromNative(damagerPlayer);
}
else
{
var damagerType = Enum.IsDefined(typeof(EntityType), damagerEntityTypeId)
? (EntityType)damagerEntityTypeId
: EntityType.UNKNOWN;
damager = new LivingEntity(damagerEntityId, damagerType, dimId, damagerX, damagerY, damagerZ);
}
byEntityEvt = new EntityDamageByEntityEvent(damager, entity!, cause, damage);
FourKit.FireEvent(byEntityEvt);
damage = byEntityEvt.getDamage();
}
var evt = new EntityDamageEvent(entity!, cause, damage);
if (byEntityEvt != null && byEntityEvt.isCancelled())
evt.setCancelled(true);
FourKit.FireEvent(evt);
Marshal.Copy(new double[] { evt.getDamage() }, 0, outDamage, 1);
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FireEntityDamage error: {ex}");
Marshal.Copy(new double[] { damage }, 0, outDamage, 1);
return 0;
}
}
[UnmanagedCallersOnly]
public static int FireSignChange(int entityId, int dimId,
int x, int y, int z,
IntPtr line0Ptr, int line0Len,
IntPtr line1Ptr, int line1Len,
IntPtr line2Ptr, int line2Len,
IntPtr line3Ptr, int line3Len,
IntPtr outBuf, int outBufSize, IntPtr outLensPtr)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
{
WriteSignOutLens(outLensPtr, [0, 0, 0, 0]);
return 0;
}
SyncPlayerFromNative(player);
string[] lines =
[
line0Len > 0 ? Marshal.PtrToStringUTF8(line0Ptr, line0Len) ?? string.Empty : string.Empty,
line1Len > 0 ? Marshal.PtrToStringUTF8(line1Ptr, line1Len) ?? string.Empty : string.Empty,
line2Len > 0 ? Marshal.PtrToStringUTF8(line2Ptr, line2Len) ?? string.Empty : string.Empty,
line3Len > 0 ? Marshal.PtrToStringUTF8(line3Ptr, line3Len) ?? string.Empty : string.Empty,
];
var world = FourKit.getWorld(dimId);
var block = new Block.Block(world, x, y, z);
var evt = new Event.Block.SignChangeEvent(block, player, lines);
FourKit.FireEvent(evt);
int offset = 0;
int[] lens = new int[4];
for (int i = 0; i < 4; i++)
{
byte[] utf8 = System.Text.Encoding.UTF8.GetBytes(evt.getLine(i));
if (offset + utf8.Length <= outBufSize)
{
Marshal.Copy(utf8, 0, outBuf + offset, utf8.Length);
lens[i] = utf8.Length;
offset += utf8.Length;
}
}
WriteSignOutLens(outLensPtr, lens);
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FireSignChange error: {ex}");
WriteSignOutLens(outLensPtr, [0, 0, 0, 0]);
return 0;
}
}
[UnmanagedCallersOnly]
public static int FireEntityDeath(int entityId, int entityTypeId, int dimId,
double x, double y, double z, int exp)
{
try
{
var entityType = Enum.IsDefined(typeof(EntityType), entityTypeId)
? (EntityType)entityTypeId
: EntityType.UNKNOWN;
var entity = new LivingEntity(entityId, entityType, dimId, x, y, z);
var drops = new List<ItemStack>();
var evt = new EntityDeathEvent(entity, drops, exp);
FourKit.FireEvent(evt);
return evt.getDroppedExp();
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FireEntityDeath error: {ex}");
return exp;
}
}
[UnmanagedCallersOnly]
public static int FirePlayerDeath(int entityId,
IntPtr deathMsgPtr, int deathMsgByteLen, int exp,
IntPtr outMsgBuf, int outMsgBufSize, IntPtr outMsgLenPtr, IntPtr outKeepInventoryPtr,
IntPtr outNewExpPtr, IntPtr outNewLevelPtr, IntPtr outKeepLevelPtr)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
{
Marshal.WriteInt32(outMsgLenPtr, 0);
Marshal.WriteInt32(outKeepInventoryPtr, 0);
Marshal.WriteInt32(outNewExpPtr, 0);
Marshal.WriteInt32(outNewLevelPtr, 0);
Marshal.WriteInt32(outKeepLevelPtr, 0);
return exp;
}
SyncPlayerFromNative(player);
string deathMessage = deathMsgByteLen > 0
? Marshal.PtrToStringUTF8(deathMsgPtr, deathMsgByteLen) ?? string.Empty
: string.Empty;
var drops = new List<ItemStack>();
var playerEvt = new PlayerDeathEvent(player, drops, exp, deathMessage);
FourKit.FireEvent(playerEvt);
var entityEvt = new EntityDeathEvent(player, playerEvt.getDrops(), playerEvt.getDroppedExp());
FourKit.FireEvent(entityEvt);
int finalExp = entityEvt.getDroppedExp();
string finalMsg = playerEvt.getDeathMessage();
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(finalMsg);
if (utf8Bytes.Length < outMsgBufSize)
{
Marshal.Copy(utf8Bytes, 0, outMsgBuf, utf8Bytes.Length);
Marshal.WriteInt32(outMsgLenPtr, utf8Bytes.Length);
}
else
{
Marshal.WriteInt32(outMsgLenPtr, 0);
}
Marshal.WriteInt32(outKeepInventoryPtr, playerEvt.getKeepInventory() ? 1 : 0);
Marshal.WriteInt32(outNewExpPtr, playerEvt.getNewExp());
Marshal.WriteInt32(outNewLevelPtr, playerEvt.getNewLevel());
Marshal.WriteInt32(outKeepLevelPtr, playerEvt.getKeepLevel() ? 1 : 0);
return finalExp;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerDeath error: {ex}");
Marshal.WriteInt32(outMsgLenPtr, 0);
Marshal.WriteInt32(outKeepInventoryPtr, 0);
Marshal.WriteInt32(outNewExpPtr, 0);
Marshal.WriteInt32(outNewLevelPtr, 0);
Marshal.WriteInt32(outKeepLevelPtr, 0);
return exp;
}
}
[UnmanagedCallersOnly]
public static long FirePlayerDropItem(int entityId, int itemId, int itemCount, int itemAux,
IntPtr outItemIdPtr, IntPtr outItemCountPtr, IntPtr outItemAuxPtr)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
{
Marshal.WriteInt32(outItemIdPtr, itemId);
Marshal.WriteInt32(outItemCountPtr, itemCount);
Marshal.WriteInt32(outItemAuxPtr, itemAux);
return 0;
}
SyncPlayerFromNative(player);
Material mat = Enum.IsDefined(typeof(Material), itemId) ? (Material)itemId : Material.AIR;
var itemStack = new ItemStack(mat, itemCount, (short)itemAux);
var evt = new PlayerDropItemEvent(player, itemStack);
FourKit.FireEvent(evt);
var result = evt.getItemDrop();
Marshal.WriteInt32(outItemIdPtr, result.getTypeId());
Marshal.WriteInt32(outItemCountPtr, result.getAmount());
Marshal.WriteInt32(outItemAuxPtr, result.getDurability());
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerDropItem error: {ex}");
Marshal.WriteInt32(outItemIdPtr, itemId);
Marshal.WriteInt32(outItemCountPtr, itemCount);
Marshal.WriteInt32(outItemAuxPtr, itemAux);
return 0;
}
}
[UnmanagedCallersOnly]
public static int FirePlayerInteract(int entityId, int action,
int itemId, int itemCount, int itemAux,
int clickedX, int clickedY, int clickedZ,
int blockFace, int dimId,
IntPtr outUseItemInHandPtr)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
{
Marshal.WriteInt32(outUseItemInHandPtr, 1);
return 0;
}
SyncPlayerFromNative(player);
var actionEnum = Enum.IsDefined(typeof(Block.Action), action)
? (Block.Action)action
: Block.Action.RIGHT_CLICK_AIR;
var faceEnum = Enum.IsDefined(typeof(Block.BlockFace), blockFace)
? (Block.BlockFace)blockFace
: Block.BlockFace.SELF;
ItemStack? itemStack = null;
if (itemId > 0)
itemStack = new ItemStack(itemId, itemCount, (short)itemAux);
Block.Block? clickedBlock = null;
bool hasBlock = actionEnum == Block.Action.LEFT_CLICK_BLOCK
|| actionEnum == Block.Action.RIGHT_CLICK_BLOCK
|| actionEnum == Block.Action.PHYSICAL;
if (hasBlock)
{
var world = FourKit.getWorld(dimId);
if (world != null)
clickedBlock = new Block.Block(world, clickedX, clickedY, clickedZ);
}
var evt = new PlayerInteractEvent(
player, actionEnum, itemStack, clickedBlock, faceEnum);
FourKit.FireEvent(evt);
Marshal.WriteInt32(outUseItemInHandPtr, evt.useItemInHand() ? 1 : 0);
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerInteract error: {ex}");
Marshal.WriteInt32(outUseItemInHandPtr, 1);
return 0;
}
}
[UnmanagedCallersOnly]
public static int FirePlayerInteractEntity(int playerEntityId,
int targetEntityId, int targetEntityTypeId,
int dimId, double targetX, double targetY, double targetZ,
float targetHealth, float targetMaxHealth, float targetEyeHeight)
{
try
{
var player = FourKit.GetPlayerByEntityId(playerEntityId);
if (player == null)
return 0;
SyncPlayerFromNative(player);
Entity.Entity? target = FourKit.GetPlayerByEntityId(targetEntityId);
if (target is Player targetPlayer)
{
SyncPlayerFromNative(targetPlayer);
}
else
{
var entityType = Enum.IsDefined(typeof(EntityType), targetEntityTypeId)
? (EntityType)targetEntityTypeId
: EntityType.UNKNOWN;
var living = new LivingEntity(targetEntityId, entityType, dimId, targetX, targetY, targetZ,
targetHealth, targetMaxHealth);
living.SetEyeHeightInternal(targetEyeHeight);
target = living;
}
var evt = new PlayerInteractEntityEvent(player, target);
FourKit.FireEvent(evt);
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerInteractEntity error: {ex}");
return 0;
}
}
[UnmanagedCallersOnly]
public static int FirePlayerPickupItem(int playerEntityId,
int itemEntityId, int dimId, double itemX, double itemY, double itemZ,
int itemId, int itemCount, int itemAux, int remaining,
IntPtr outItemIdPtr, IntPtr outItemCountPtr, IntPtr outItemAuxPtr)
{
try
{
var player = FourKit.GetPlayerByEntityId(playerEntityId);
if (player == null)
{
Marshal.WriteInt32(outItemIdPtr, itemId);
Marshal.WriteInt32(outItemCountPtr, itemCount);
Marshal.WriteInt32(outItemAuxPtr, itemAux);
// todo: fix
return 1;
}
SyncPlayerFromNative(player);
var itemStack = new Inventory.ItemStack(itemId, itemCount, (short)itemAux);
var item = new Entity.Item(itemEntityId, dimId, itemX, itemY, itemZ, itemStack);
var evt = new PlayerPickupItemEvent(player, item, remaining);
FourKit.FireEvent(evt);
var result = evt.getItem().getItemStack();
Marshal.WriteInt32(outItemIdPtr, result.getTypeId());
Marshal.WriteInt32(outItemCountPtr, result.getAmount());
Marshal.WriteInt32(outItemAuxPtr, result.getDurability());
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerPickupItem error: {ex}");
Marshal.WriteInt32(outItemIdPtr, itemId);
Marshal.WriteInt32(outItemCountPtr, itemCount);
Marshal.WriteInt32(outItemAuxPtr, itemAux);
return 0;
}
}
[UnmanagedCallersOnly]
public static int FireInventoryOpen(int entityId, int nativeContainerType,
IntPtr titlePtr, int titleByteLen, int containerSize)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null) return 0;
SyncPlayerFromNative(player);
string title = titleByteLen > 0
? Marshal.PtrToStringUTF8(titlePtr, titleByteLen) ?? string.Empty
: string.Empty;
InventoryType invType = MapNativeContainerType(nativeContainerType);
Inventory.Inventory topInv = CreateContainerInventory(invType, nativeContainerType, title, containerSize, entityId);
var bottomInv = player.getInventory();
var view = new InventoryView(topInv, bottomInv, player, invType);
var evt = new InventoryOpenEvent(view);
FourKit.FireEvent(evt);
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FireInventoryOpen error: {ex}");
return 0;
}
}
[UnmanagedCallersOnly]
public static int FireInventoryClick(int entityId, int slot, int button, int clickType,
int nativeContainerType, int containerSize, IntPtr titleUtf8Ptr, int titleByteLen)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null) return 0;
SyncPlayerFromNative(player);
ClickType click = MapNativeClickType(clickType, button);
InventoryAction action = DetermineInventoryAction(click, slot);
InventoryType invType;
Inventory.Inventory topInv;
if (nativeContainerType < 0)
{
invType = InventoryType.PLAYER;
topInv = player.getInventory();
}
else
{
invType = MapNativeContainerType(nativeContainerType);
int size = containerSize > 0 ? containerSize : invType.getDefaultSize();
string title = titleByteLen > 0 && titleUtf8Ptr != IntPtr.Zero
? Marshal.PtrToStringUTF8(titleUtf8Ptr, titleByteLen) ?? invType.getDefaultTitle()
: invType.getDefaultTitle();
topInv = CreateContainerInventory(invType, nativeContainerType, title, size, entityId);
}
var bottomInv = player.getInventory();
var view = new InventoryView(topInv, bottomInv, player, invType);
SlotType slotType = SlotType.CONTAINER;
if (slot == InventoryView.OUTSIDE)
slotType = SlotType.OUTSIDE;
Inventory.Inventory._slotModifiedByPlugin = false;
int hotbarKey = click == ClickType.NUMBER_KEY ? button : -1;
var evt = new InventoryClickEvent(view, slotType, slot, click, action, hotbarKey);
FourKit.FireEvent(evt);
if (evt.isCancelled()) return 1;
if (Inventory.Inventory._slotModifiedByPlugin) return 2;
return 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FireInventoryClick error: {ex}");
return 0;
}
}
[UnmanagedCallersOnly]
public static int HandlePlayerCommand(int entityId, IntPtr cmdUtf8, int cmdByteLen)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
return 0;
SyncPlayerFromNative(player);
string commandLine = cmdByteLen > 0
? Marshal.PtrToStringUTF8(cmdUtf8, cmdByteLen) ?? string.Empty
: string.Empty;
if (string.IsNullOrEmpty(commandLine))
return 0;
return FourKit.DispatchCommand(player, commandLine) ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"HandlePlayerCommand error: {ex}");
return 0;
}
}
[UnmanagedCallersOnly]
public static int HandleConsoleCommand(IntPtr cmdUtf8, int cmdByteLen)
{
try
{
string commandLine = cmdByteLen > 0
? Marshal.PtrToStringUTF8(cmdUtf8, cmdByteLen) ?? string.Empty
: string.Empty;
if (string.IsNullOrEmpty(commandLine))
return 0;
string trimmed = commandLine.StartsWith('/') ? commandLine[1..] : commandLine;
string[] parts = trimmed.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0)
return 0;
if (!FourKit.HasCommand(parts[0]))
return 0;
FourKit.DispatchCommand(FourKit.getConsoleSender(), commandLine);
return 1;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"HandleConsoleCommand error: {ex}");
return 0;
}
}
[UnmanagedCallersOnly]
public static int GetPluginCommandHelp(IntPtr outBuf, int outBufSize, IntPtr outLenPtr)
{
try
{
var entries = FourKit.GetRegisteredCommandHelp();
if (entries.Count == 0)
{
if (outLenPtr != IntPtr.Zero)
Marshal.WriteInt32(outLenPtr, 0);
return 0;
}
var sb = new System.Text.StringBuilder();
foreach (var (usage, description) in entries)
{
sb.Append(usage);
sb.Append('\0');
sb.Append(description);
sb.Append('\0');
}
byte[] utf8 = System.Text.Encoding.UTF8.GetBytes(sb.ToString());
int copyLen = Math.Min(utf8.Length, outBufSize);
if (outBuf != IntPtr.Zero && copyLen > 0)
Marshal.Copy(utf8, 0, outBuf, copyLen);
if (outLenPtr != IntPtr.Zero)
Marshal.WriteInt32(outLenPtr, copyLen);
return entries.Count;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"GetPluginCommandHelp error: {ex}");
if (outLenPtr != IntPtr.Zero)
Marshal.WriteInt32(outLenPtr, 0);
return 0;
}
}
[UnmanagedCallersOnly]
public static int FirePlayerTeleport(int entityId,
double fromX, double fromY, double fromZ, int fromDimId,
double toX, double toY, double toZ, int toDimId,
int cause, IntPtr outCoords)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
{
Marshal.Copy(new double[] { toX, toY, toZ }, 0, outCoords, 3);
return 0;
}
SyncPlayerFromNative(player);
var fromWorld = FourKit.getWorld(fromDimId);
var toWorld = FourKit.getWorld(toDimId);
var from = new Location(fromWorld, fromX, fromY, fromZ);
var to = new Location(toWorld, toX, toY, toZ);
var teleportCause = cause >= 0 && cause <= (int)PlayerTeleportEvent.TeleportCause.UNKNOWN
? (PlayerTeleportEvent.TeleportCause)cause
: PlayerTeleportEvent.TeleportCause.UNKNOWN;
var evt = new PlayerTeleportEvent(player, from, to, teleportCause);
FourKit.FireEvent(evt);
var finalTo = evt.getTo();
Marshal.Copy(new double[] { finalTo.X, finalTo.Y, finalTo.Z }, 0, outCoords, 3);
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerTeleport error: {ex}");
Marshal.Copy(new double[] { toX, toY, toZ }, 0, outCoords, 3);
return 0;
}
}
[UnmanagedCallersOnly]
public static int FirePlayerPortal(int entityId,
double fromX, double fromY, double fromZ, int fromDimId,
double toX, double toY, double toZ, int toDimId,
int cause, IntPtr outCoords)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null)
{
Marshal.Copy(new double[] { toX, toY, toZ }, 0, outCoords, 3);
return 0;
}
SyncPlayerFromNative(player);
var fromWorld = FourKit.getWorld(fromDimId);
var toWorld = FourKit.getWorld(toDimId);
var from = new Location(fromWorld, fromX, fromY, fromZ);
var to = new Location(toWorld, toX, toY, toZ);
var teleportCause = cause >= 0 && cause <= (int)PlayerTeleportEvent.TeleportCause.UNKNOWN
? (PlayerTeleportEvent.TeleportCause)cause
: PlayerTeleportEvent.TeleportCause.UNKNOWN;
var evt = new PlayerPortalEvent(player, from, to, teleportCause);
FourKit.FireEvent(evt);
var finalTo = evt.getTo();
Marshal.Copy(new double[] { finalTo.X, finalTo.Y, finalTo.Z }, 0, outCoords, 3);
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FirePlayerPortal error: {ex}");
Marshal.Copy(new double[] { toX, toY, toZ }, 0, outCoords, 3);
return 0;
}
}
[UnmanagedCallersOnly]
public static int FireBedEnter(int entityId, int dimId, int bedX, int bedY, int bedZ)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null) return 0;
SyncPlayerFromNative(player);
var world = FourKit.getWorld(dimId);
var bed = new Block.Block(world, bedX, bedY, bedZ);
var evt = new Event.Player.PlayerBedEnterEvent(player, bed);
FourKit.FireEvent(evt);
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FireBedEnter error: {ex}");
return 0;
}
}
[UnmanagedCallersOnly]
public static void FireBedLeave(int entityId, int dimId, int bedX, int bedY, int bedZ)
{
try
{
var player = FourKit.GetPlayerByEntityId(entityId);
if (player == null) return;
SyncPlayerFromNative(player);
var world = FourKit.getWorld(dimId);
var bed = new Block.Block(world, bedX, bedY, bedZ);
var evt = new Event.Player.PlayerBedLeaveEvent(player, bed);
FourKit.FireEvent(evt);
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FireBedLeave error: {ex}");
}
}
}