Add itemmeta, fix some bugs regarding inventory syncing and missing impl (oops)

This commit is contained in:
sylvessa 2026-03-22 20:00:36 -05:00
parent aca05bad7b
commit 91b189e1bd
6 changed files with 467 additions and 7 deletions

View file

@ -35,6 +35,7 @@
#include "..\Minecraft.World\LightningBolt.h"
#include "..\Minecraft.World\Player.h"
#include "..\Minecraft.World\PlayerAbilitiesPacket.h"
#include "..\Minecraft.World\SetCarriedItemPacket.h"
#include "..\Minecraft.World\SimpleContainer.h"
#include "..\Minecraft.World\Slot.h"
#include "..\Minecraft.World\Tile.h"
@ -141,7 +142,7 @@ typedef void(__stdcall *fn_set_player_callbacks)(void *kickPlayer, void *banPlay
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);
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 int(__stdcall *fn_fire_player_interact)(int entityId, int action,
int itemId, int itemCount, int itemAux,
int clickedX, int clickedY, int clickedZ,
@ -1069,6 +1070,212 @@ static void __cdecl NativeGetContainerViewerEntityIds(int entityId, int *outIds,
*outCount = count;
}
// [nameLen:int32][nameUTF8:bytes][loreCount:int32][lore0Len:int32][lore0UTF8:bytes]
// todo: des muass i no a bissl überarwatn
static int __cdecl NativeGetItemMeta(int entityId, int slot, char *outBuf, int bufSize)
{
auto player = FindPlayer(entityId);
if (!player || !player->inventory)
{
return 0;
}
unsigned int size = player->inventory->getContainerSize();
if (slot < 0 || slot >= (int)size)
{
return 0;
}
auto item = player->inventory->getItem(slot);
if (!item || !item->hasTag())
{
return 0;
}
CompoundTag *tag = item->getTag();
if (!tag || !tag->contains(L"display"))
{
return 0;
}
CompoundTag *display = tag->getCompound(L"display");
bool hasName = display->contains(L"Name");
bool hasLore = display->contains(L"Lore");
if (!hasName && !hasLore)
{
return 0;
}
int offset = 0;
if (hasName)
{
std::wstring wname = display->getString(L"Name");
std::string nameUtf8 = ServerRuntime::StringUtils::WideToUtf8(wname);
int nameLen = (int)nameUtf8.size();
if (offset + 4 + nameLen > bufSize) return 0;
memcpy(outBuf + offset, &nameLen, 4);
offset += 4;
memcpy(outBuf + offset, nameUtf8.data(), nameLen);
offset += nameLen;
}
else
{
int zero = 0;
if (offset + 4 > bufSize) return 0;
memcpy(outBuf + offset, &zero, 4);
offset += 4;
}
if (hasLore)
{
ListTag<StringTag> *lore = (ListTag<StringTag> *)display->getList(L"Lore");
int loreCount = lore->size();
if (offset + 4 > bufSize) return 0;
memcpy(outBuf + offset, &loreCount, 4);
offset += 4;
for (int i = 0; i < loreCount; i++)
{
std::wstring wline = lore->get(i)->data;
std::string lineUtf8 = ServerRuntime::StringUtils::WideToUtf8(wline);
int lineLen = (int)lineUtf8.size();
if (offset + 4 + lineLen > bufSize) return 0;
memcpy(outBuf + offset, &lineLen, 4);
offset += 4;
memcpy(outBuf + offset, lineUtf8.data(), lineLen);
offset += lineLen;
}
}
else
{
int zero = 0;
if (offset + 4 > bufSize) return 0;
memcpy(outBuf + offset, &zero, 4);
offset += 4;
}
return offset;
}
static void __cdecl NativeSetItemMeta(int entityId, int slot, const char *inBuf, int bufSize)
{
auto player = FindPlayer(entityId);
if (!player || !player->inventory)
{
return;
}
unsigned int size = player->inventory->getContainerSize();
if (slot < 0 || slot >= (int)size)
{
return;
}
auto item = player->inventory->getItem(slot);
if (!item)
{
return;
}
if (inBuf == nullptr || bufSize <= 0)
{
item->resetHoverName();
if (item->hasTag())
{
CompoundTag *tag = item->getTag();
if (tag && tag->contains(L"display"))
{
CompoundTag *display = tag->getCompound(L"display");
display->remove(L"Lore");
if (display->isEmpty())
{
tag->remove(L"display");
if (tag->isEmpty())
{
item->setTag(nullptr);
}
}
}
}
return;
}
int offset = 0;
if (offset + 4 > bufSize) return;
int nameLen = 0;
memcpy(&nameLen, inBuf + offset, 4);
offset += 4;
if (nameLen > 0)
{
if (offset + nameLen > bufSize) return;
std::string nameUtf8(inBuf + offset, nameLen);
offset += nameLen;
std::wstring wname = ServerRuntime::StringUtils::Utf8ToWide(nameUtf8);
item->setHoverName(wname);
}
else
{
item->resetHoverName();
}
if (offset + 4 > bufSize) return;
int loreCount = 0;
memcpy(&loreCount, inBuf + offset, 4);
offset += 4;
if (loreCount > 0)
{
if (!item->hasTag()) item->setTag(new CompoundTag());
CompoundTag *tag = item->getTag();
if (!tag->contains(L"display")) tag->putCompound(L"display", new CompoundTag());
CompoundTag *display = tag->getCompound(L"display");
auto *loreList = new ListTag<StringTag>(L"Lore");
for (int i = 0; i < loreCount; i++)
{
if (offset + 4 > bufSize) break;
int lineLen = 0;
memcpy(&lineLen, inBuf + offset, 4);
offset += 4;
std::wstring wline;
if (lineLen > 0 && offset + lineLen <= bufSize)
{
std::string lineUtf8(inBuf + offset, lineLen);
offset += lineLen;
wline = ServerRuntime::StringUtils::Utf8ToWide(lineUtf8);
}
loreList->add(new StringTag(L"", wline));
}
display->put(L"Lore", loreList);
}
else
{
if (item->hasTag())
{
CompoundTag *tag = item->getTag();
if (tag && tag->contains(L"display"))
{
tag->getCompound(L"display")->remove(L"Lore");
}
}
}
}
static void __cdecl NativeSetHeldItemSlot(int entityId, int slot)
{
auto player = FindPlayer(entityId);
if (!player || !player->inventory) return;
if (slot < 0 || slot >= Inventory::getSelectionSize()) return;
player->inventory->selected = slot;
if (player->connection)
player->connection->queueSend(std::make_shared<SetCarriedItemPacket>(slot));
}
static std::wstring FindNet10SystemRoot()
{
// overengineered
@ -1362,7 +1569,10 @@ void Initialize()
(void *)&NativeSetContainerSlot,
(void *)&NativeGetContainerViewerEntityIds,
(void *)&NativeCloseContainer,
(void *)&NativeOpenVirtualContainer);
(void *)&NativeOpenVirtualContainer,
(void *)&NativeGetItemMeta,
(void *)&NativeSetItemMeta,
(void *)&NativeSetHeldItemSlot);
LogInfo("fourkit", "FourKit initialized successfully.");
}