mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-05-16 21:12:55 +00:00
fix bugs found regarding inventories
This commit is contained in:
parent
6e6697dbc2
commit
d26c79a11e
|
|
@ -11,7 +11,7 @@ public abstract class HumanEntity : LivingEntity, InventoryHolder
|
|||
private GameMode _gameMode = GameMode.SURVIVAL;
|
||||
private string _name = string.Empty;
|
||||
internal PlayerInventory _playerInventory = new();
|
||||
internal Inventory _enderChestInventory = new("Ender Chest", InventoryType.ENDER_CHEST, 27);
|
||||
internal EnderChestInventory? _enderChestInventory;
|
||||
private ItemStack? _cursorItem;
|
||||
private bool _sleeping;
|
||||
private int _sleepTicks;
|
||||
|
|
@ -59,6 +59,8 @@ public abstract class HumanEntity : LivingEntity, InventoryHolder
|
|||
/// <returns>The EnderChest of the player.</returns>
|
||||
public Inventory getEnderChest()
|
||||
{
|
||||
// AAAAAH
|
||||
_enderChestInventory ??= new EnderChestInventory(getEntityId());
|
||||
return _enderChestInventory;
|
||||
}
|
||||
|
||||
|
|
@ -86,14 +88,44 @@ public abstract class HumanEntity : LivingEntity, InventoryHolder
|
|||
/// Will always be empty if the player currently has no open window.
|
||||
/// </summary>
|
||||
/// <returns>The ItemStack of the item you are currently moving around.</returns>
|
||||
public ItemStack? getItemOnCursor() => _cursorItem;
|
||||
public ItemStack? getItemOnCursor()
|
||||
{
|
||||
if (NativeBridge.GetCarriedItem != null)
|
||||
{
|
||||
int[] buf = new int[3];
|
||||
var gh = System.Runtime.InteropServices.GCHandle.Alloc(buf, System.Runtime.InteropServices.GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
NativeBridge.GetCarriedItem(getEntityId(), gh.AddrOfPinnedObject());
|
||||
}
|
||||
finally
|
||||
{
|
||||
gh.Free();
|
||||
}
|
||||
int id = buf[0];
|
||||
int aux = buf[1];
|
||||
int count = buf[2];
|
||||
if (id > 0 && count > 0)
|
||||
_cursorItem = new ItemStack(id, count, (short)aux);
|
||||
else
|
||||
_cursorItem = null;
|
||||
}
|
||||
return _cursorItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the item to the given ItemStack, this will replace whatever the
|
||||
/// user was moving. Will always be empty if the player currently has no open window.
|
||||
/// </summary>
|
||||
/// <param name="item">The ItemStack which will end up in the hand.</param>
|
||||
public void setItemOnCursor(ItemStack? item) => _cursorItem = item;
|
||||
public void setItemOnCursor(ItemStack? item)
|
||||
{
|
||||
_cursorItem = item;
|
||||
NativeBridge.SetCarriedItem?.Invoke(getEntityId(),
|
||||
item?.getTypeId() ?? 0,
|
||||
item?.getAmount() ?? 0,
|
||||
item?.getDurability() ?? 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the player currently has an inventory window open, this method will
|
||||
|
|
|
|||
|
|
@ -58,11 +58,11 @@ public static partial class FourKitHost
|
|||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
public static void SetInventoryCallbacks(IntPtr getPlayerInventory, IntPtr setPlayerInventorySlot, IntPtr getContainerContents, IntPtr setContainerSlot, IntPtr getContainerViewerEntityIds, IntPtr closeContainer, IntPtr openVirtualContainer, IntPtr getItemMeta, IntPtr setItemMeta, IntPtr setHeldItemSlot)
|
||||
public static void SetInventoryCallbacks(IntPtr getPlayerInventory, IntPtr setPlayerInventorySlot, IntPtr getContainerContents, IntPtr setContainerSlot, IntPtr getContainerViewerEntityIds, IntPtr closeContainer, IntPtr openVirtualContainer, IntPtr getItemMeta, IntPtr setItemMeta, IntPtr setHeldItemSlot, IntPtr getCarriedItem, IntPtr setCarriedItem, IntPtr getEnderChestContents, IntPtr setEnderChestSlot)
|
||||
{
|
||||
try
|
||||
{
|
||||
NativeBridge.SetInventoryCallbacks(getPlayerInventory, setPlayerInventorySlot, getContainerContents, setContainerSlot, getContainerViewerEntityIds, closeContainer, openVirtualContainer, getItemMeta, setItemMeta, setHeldItemSlot);
|
||||
NativeBridge.SetInventoryCallbacks(getPlayerInventory, setPlayerInventorySlot, getContainerContents, setContainerSlot, getContainerViewerEntityIds, closeContainer, openVirtualContainer, getItemMeta, setItemMeta, setHeldItemSlot, getCarriedItem, setCarriedItem, getEnderChestContents, setEnderChestSlot);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
85
Minecraft.Server.FourKit/Inventory/EnderChestInventory.cs
Normal file
85
Minecraft.Server.FourKit/Inventory/EnderChestInventory.cs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
namespace Minecraft.Server.FourKit.Inventory;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// todo: this needs to be removed at some point
|
||||
|
||||
internal class EnderChestInventory : Inventory
|
||||
{
|
||||
private readonly int _ownerEntityId;
|
||||
|
||||
internal EnderChestInventory(int ownerEntityId)
|
||||
: base("Ender Chest", InventoryType.ENDER_CHEST, 27)
|
||||
{
|
||||
_ownerEntityId = ownerEntityId;
|
||||
}
|
||||
|
||||
protected internal override void EnsureSynced()
|
||||
{
|
||||
if (NativeBridge.GetEnderChestContents == null)
|
||||
return;
|
||||
|
||||
int[] buf = new int[27 * 3];
|
||||
var gh = GCHandle.Alloc(buf, GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
NativeBridge.GetEnderChestContents(_ownerEntityId, gh.AddrOfPinnedObject());
|
||||
}
|
||||
finally
|
||||
{
|
||||
gh.Free();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 27; i++)
|
||||
{
|
||||
int id = buf[i * 3 + 0];
|
||||
int aux = buf[i * 3 + 1];
|
||||
int packed = buf[i * 3 + 2];
|
||||
|
||||
ushort count = (ushort)((packed >> 8) & 0xFFFF);
|
||||
|
||||
_items[i]?.UnbindFromInventory();
|
||||
if (id > 0 && count > 0)
|
||||
{
|
||||
if (_items[i] == null)
|
||||
{
|
||||
_items[i] = new ItemStack(id, count, (short)aux);
|
||||
}
|
||||
else
|
||||
{
|
||||
_items[i]!.setTypeId(id);
|
||||
_items[i]!.setAmount(count);
|
||||
_items[i]!.setDurability((short)aux);
|
||||
}
|
||||
_items[i]!.BindToInventory(this, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
_items[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void setItem(int index, ItemStack? item)
|
||||
{
|
||||
if (index >= 0 && index < _items.Length)
|
||||
{
|
||||
var old = _items[index];
|
||||
if (old != item)
|
||||
{
|
||||
old?.UnbindFromInventory();
|
||||
item?.BindToInventory(this, index);
|
||||
}
|
||||
_items[index] = item;
|
||||
_slotModifiedByPlugin = true;
|
||||
}
|
||||
|
||||
if (NativeBridge.SetEnderChestSlot != null && index >= 0 && index < _items.Length)
|
||||
{
|
||||
int id = item?.getTypeId() ?? 0;
|
||||
int count = item?.getAmount() ?? 0;
|
||||
int aux = item?.getDurability() ?? 0;
|
||||
NativeBridge.SetEnderChestSlot(_ownerEntityId, index, id, count, aux);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -123,6 +123,18 @@ internal static class NativeBridge
|
|||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void NativeSetHeldItemSlotDelegate(int entityId, int slot);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void NativeGetCarriedItemDelegate(int entityId, IntPtr outData);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void NativeSetCarriedItemDelegate(int entityId, int itemId, int count, int aux);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void NativeGetEnderChestContentsDelegate(int entityId, IntPtr outData);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void NativeSetEnderChestSlotDelegate(int entityId, int slot, int itemId, int count, int aux);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate void NativeSetSneakingDelegate(int entityId, int sneak);
|
||||
|
||||
|
|
@ -261,6 +273,10 @@ internal static class NativeBridge
|
|||
internal static NativeGetItemMetaDelegate? GetItemMeta;
|
||||
internal static NativeSetItemMetaDelegate? SetItemMeta;
|
||||
internal static NativeSetHeldItemSlotDelegate? SetHeldItemSlot;
|
||||
internal static NativeGetCarriedItemDelegate? GetCarriedItem;
|
||||
internal static NativeSetCarriedItemDelegate? SetCarriedItem;
|
||||
internal static NativeGetEnderChestContentsDelegate? GetEnderChestContents;
|
||||
internal static NativeSetEnderChestSlotDelegate? SetEnderChestSlot;
|
||||
internal static NativeSetSneakingDelegate? SetSneaking;
|
||||
internal static NativeSetVelocityDelegate? SetVelocity;
|
||||
internal static NativeSetAllowFlightDelegate? SetAllowFlight;
|
||||
|
|
@ -340,7 +356,7 @@ internal static class NativeBridge
|
|||
SendRaw = Marshal.GetDelegateForFunctionPointer<NativeSendRawDelegate>(sendRaw);
|
||||
}
|
||||
|
||||
internal static void SetInventoryCallbacks(IntPtr getPlayerInventory, IntPtr setPlayerInventorySlot, IntPtr getContainerContents, IntPtr setContainerSlot, IntPtr getContainerViewerEntityIds, IntPtr closeContainer, IntPtr openVirtualContainer, IntPtr getItemMeta, IntPtr setItemMeta, IntPtr setHeldItemSlot)
|
||||
internal static void SetInventoryCallbacks(IntPtr getPlayerInventory, IntPtr setPlayerInventorySlot, IntPtr getContainerContents, IntPtr setContainerSlot, IntPtr getContainerViewerEntityIds, IntPtr closeContainer, IntPtr openVirtualContainer, IntPtr getItemMeta, IntPtr setItemMeta, IntPtr setHeldItemSlot, IntPtr getCarriedItem, IntPtr setCarriedItem, IntPtr getEnderChestContents, IntPtr setEnderChestSlot)
|
||||
{
|
||||
GetPlayerInventory = Marshal.GetDelegateForFunctionPointer<NativeGetPlayerInventoryDelegate>(getPlayerInventory);
|
||||
SetPlayerInventorySlot = Marshal.GetDelegateForFunctionPointer<NativeSetPlayerInventorySlotDelegate>(setPlayerInventorySlot);
|
||||
|
|
@ -352,6 +368,10 @@ internal static class NativeBridge
|
|||
GetItemMeta = Marshal.GetDelegateForFunctionPointer<NativeGetItemMetaDelegate>(getItemMeta);
|
||||
SetItemMeta = Marshal.GetDelegateForFunctionPointer<NativeSetItemMetaDelegate>(setItemMeta);
|
||||
SetHeldItemSlot = Marshal.GetDelegateForFunctionPointer<NativeSetHeldItemSlotDelegate>(setHeldItemSlot);
|
||||
GetCarriedItem = Marshal.GetDelegateForFunctionPointer<NativeGetCarriedItemDelegate>(getCarriedItem);
|
||||
SetCarriedItem = Marshal.GetDelegateForFunctionPointer<NativeSetCarriedItemDelegate>(setCarriedItem);
|
||||
GetEnderChestContents = Marshal.GetDelegateForFunctionPointer<NativeGetEnderChestContentsDelegate>(getEnderChestContents);
|
||||
SetEnderChestSlot = Marshal.GetDelegateForFunctionPointer<NativeSetEnderChestSlotDelegate>(setEnderChestSlot);
|
||||
}
|
||||
|
||||
internal static void SetEntityCallbacks(IntPtr setSneaking, IntPtr setVelocity, IntPtr setAllowFlight, IntPtr playSound, IntPtr setSleepingIgnored)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ typedef void(__stdcall *fn_set_player_connection_callbacks)(void *sendRaw);
|
|||
typedef long long(__stdcall *fn_fire_player_drop_item)(int entityId,
|
||||
int itemId, int itemCount, int itemAux,
|
||||
int *outItemId, int *outItemCount, int *outItemAux);
|
||||
typedef void(__stdcall *fn_set_inventory_callbacks)(void *getPlayerInventory, void *setPlayerInventorySlot, void *getContainerContents, void *setContainerSlot, void *getContainerViewerEntityIds, void *closeContainer, void *openVirtualContainer, void *getItemMeta, void *setItemMeta, void *setHeldItemSlot);
|
||||
typedef void(__stdcall *fn_set_inventory_callbacks)(void *getPlayerInventory, void *setPlayerInventorySlot, void *getContainerContents, void *setContainerSlot, void *getContainerViewerEntityIds, void *closeContainer, void *openVirtualContainer, void *getItemMeta, void *setItemMeta, void *setHeldItemSlot, void *getCarriedItem, void *setCarriedItem, void *getEnderChestContents, void *setEnderChestSlot);
|
||||
typedef int(__stdcall *fn_fire_player_interact)(int entityId, int action,
|
||||
int itemId, int itemCount, int itemAux,
|
||||
int clickedX, int clickedY, int clickedZ,
|
||||
|
|
@ -318,7 +318,11 @@ void Initialize()
|
|||
(void *)&NativeOpenVirtualContainer,
|
||||
(void *)&NativeGetItemMeta,
|
||||
(void *)&NativeSetItemMeta,
|
||||
(void *)&NativeSetHeldItemSlot);
|
||||
(void *)&NativeSetHeldItemSlot,
|
||||
(void *)&NativeGetCarriedItem,
|
||||
(void *)&NativeSetCarriedItem,
|
||||
(void *)&NativeGetEnderChestContents,
|
||||
(void *)&NativeSetEnderChestSlot);
|
||||
|
||||
s_managedSetEntityCallbacks(
|
||||
(void *)&NativeSetSneaking,
|
||||
|
|
|
|||
|
|
@ -1072,6 +1072,68 @@ void __cdecl NativeSetHeldItemSlot(int entityId, int slot)
|
|||
player->connection->queueSend(std::make_shared<SetCarriedItemPacket>(slot));
|
||||
}
|
||||
|
||||
void __cdecl NativeGetCarriedItem(int entityId, int *outData)
|
||||
{
|
||||
outData[0] = 0;
|
||||
outData[1] = 0;
|
||||
outData[2] = 0;
|
||||
auto player = FindPlayer(entityId);
|
||||
if (!player || !player->inventory)
|
||||
return;
|
||||
auto item = player->inventory->getCarried();
|
||||
if (item)
|
||||
{
|
||||
outData[0] = item->id;
|
||||
outData[1] = item->getAuxValue();
|
||||
outData[2] = (int)item->count;
|
||||
}
|
||||
}
|
||||
|
||||
void __cdecl NativeSetCarriedItem(int entityId, int itemId, int count, int aux)
|
||||
{
|
||||
auto player = FindPlayer(entityId);
|
||||
if (!player || !player->inventory)
|
||||
return;
|
||||
if (itemId <= 0 || count <= 0)
|
||||
player->inventory->setCarried(nullptr);
|
||||
else
|
||||
player->inventory->setCarried(std::make_shared<ItemInstance>(itemId, count, aux));
|
||||
}
|
||||
|
||||
void __cdecl NativeGetEnderChestContents(int entityId, int *outData)
|
||||
{
|
||||
memset(outData, 0, 27 * 3 * sizeof(int));
|
||||
auto player = FindPlayer(entityId);
|
||||
if (!player)
|
||||
return;
|
||||
auto ec = player->getEnderChestInventory();
|
||||
if (!ec)
|
||||
return;
|
||||
unsigned int size = ec->getContainerSize();
|
||||
if (size > 27)
|
||||
size = 27;
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
{
|
||||
WriteInventoryItemData(ec->getItem(i), i, outData);
|
||||
}
|
||||
}
|
||||
|
||||
void __cdecl NativeSetEnderChestSlot(int entityId, int slot, int itemId, int count, int aux)
|
||||
{
|
||||
auto player = FindPlayer(entityId);
|
||||
if (!player)
|
||||
return;
|
||||
auto ec = player->getEnderChestInventory();
|
||||
if (!ec)
|
||||
return;
|
||||
if (slot < 0 || slot >= (int)ec->getContainerSize())
|
||||
return;
|
||||
if (itemId <= 0 || count <= 0)
|
||||
ec->setItem(slot, nullptr);
|
||||
else
|
||||
ec->setItem(slot, std::make_shared<ItemInstance>(itemId, count, aux));
|
||||
}
|
||||
|
||||
void __cdecl NativeSetSneaking(int entityId, int sneak)
|
||||
{
|
||||
auto player = FindPlayer(entityId);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,12 @@ namespace FourKitBridge
|
|||
void __cdecl NativeSetItemMeta(int entityId, int slot, const char *inBuf, int bufSize);
|
||||
void __cdecl NativeSetHeldItemSlot(int entityId, int slot);
|
||||
|
||||
// carried item (cursor) & ender chest
|
||||
void __cdecl NativeGetCarriedItem(int entityId, int *outData);
|
||||
void __cdecl NativeSetCarriedItem(int entityId, int itemId, int count, int aux);
|
||||
void __cdecl NativeGetEnderChestContents(int entityId, int *outData);
|
||||
void __cdecl NativeSetEnderChestSlot(int entityId, int slot, int itemId, int count, int aux);
|
||||
|
||||
// ent
|
||||
void __cdecl NativeSetSneaking(int entityId, int sneak);
|
||||
void __cdecl NativeSetVelocity(int entityId, double x, double y, double z);
|
||||
|
|
|
|||
Loading…
Reference in a new issue