From f1d4882fe0e0792818f52d84ffc325507ecbdd25 Mon Sep 17 00:00:00 2001 From: DrPerkyLegit Date: Sat, 23 May 2026 10:56:05 -0400 Subject: [PATCH] book and quill implementation --- Minecraft.Client/PlayerConnection.cpp | 138 ++++++++++----------- Minecraft.World/Item.cpp | 8 +- Minecraft.World/Item.h | 4 +- Minecraft.World/ListTag.h | 5 + Minecraft.World/WritingBookItem.cpp | 26 ++++ Minecraft.World/WritingBookItem.h | 12 ++ Minecraft.World/WrittenBookItem.cpp | 48 +++++++ Minecraft.World/WrittenBookItem.h | 88 ++----------- Minecraft.World/net.minecraft.world.item.h | 2 + cmake/WorldSources.cmake | 2 + 10 files changed, 181 insertions(+), 152 deletions(-) create mode 100644 Minecraft.World/WritingBookItem.cpp create mode 100644 Minecraft.World/WritingBookItem.h create mode 100644 Minecraft.World/WrittenBookItem.cpp diff --git a/Minecraft.Client/PlayerConnection.cpp b/Minecraft.Client/PlayerConnection.cpp index 8e40a39..0090cd5 100644 --- a/Minecraft.Client/PlayerConnection.cpp +++ b/Minecraft.Client/PlayerConnection.cpp @@ -1440,113 +1440,111 @@ void PlayerConnection::handlePlayerAbilities(shared_ptr p void PlayerConnection::handleCustomPayload(shared_ptr customPayloadPacket) { -#if 0 - if (CustomPayloadPacket.CUSTOM_BOOK_PACKET.equals(customPayloadPacket.identifier)) + if (CustomPayloadPacket::CUSTOM_BOOK_PACKET.compare(customPayloadPacket->identifier) == 0) { ByteArrayInputStream bais(customPayloadPacket->data); DataInputStream input(&bais); - shared_ptr sentItem = Packet::readItem(input); + shared_ptr sentItem = Packet::readItem(&input); - if (!WritingBookItem.makeSureTagIsValid(sentItem.getTag())) + if (sentItem->tag == nullptr) { - throw new IOException("Invalid book tag!"); + throw new IOException(L"Invalid book tag!"); } // make sure the sent item is the currently carried item - ItemInstance carried = player.inventory.getSelected(); - if (sentItem != null && sentItem.id == Item.writingBook.id && sentItem.id == carried.id) + shared_ptr carried = player->inventory->getSelected(); + if (sentItem != nullptr && sentItem->id == Item::writingBook_Id && sentItem->id == carried->id) { - carried.addTagElement(WrittenBookItem.TAG_PAGES, sentItem.getTag().getList(WrittenBookItem.TAG_PAGES)); + player->inventory->setItem(player->inventory->selected, sentItem); } } - else if (CustomPayloadPacket.CUSTOM_BOOK_SIGN_PACKET.equals(customPayloadPacket.identifier)) + else if (CustomPayloadPacket::CUSTOM_BOOK_SIGN_PACKET.compare(customPayloadPacket->identifier) == 0) { - DataInputStream input = new DataInputStream(new ByteArrayInputStream(customPayloadPacket.data)); - ItemInstance sentItem = Packet.readItem(input); + ByteArrayInputStream bais(customPayloadPacket->data); + DataInputStream input(&bais); + shared_ptr sentItem = Packet::readItem(&input); - if (!WrittenBookItem.makeSureTagIsValid(sentItem.getTag())) + if (sentItem->tag == nullptr) { - throw new IOException("Invalid book tag!"); + throw new IOException(L"Invalid book tag!"); } // make sure the sent item is the currently carried item - ItemInstance carried = player.inventory.getSelected(); - if (sentItem != null && sentItem.id == Item.writtenBook.id && carried.id == Item.writingBook.id) + shared_ptr carried = player->inventory->getSelected(); + + if (sentItem != nullptr && sentItem->id == Item::writingBook_Id && sentItem->id == carried->id) { - carried.addTagElement(WrittenBookItem.TAG_AUTHOR, new StringTag(WrittenBookItem.TAG_AUTHOR, player.getName())); - carried.addTagElement(WrittenBookItem.TAG_TITLE, new StringTag(WrittenBookItem.TAG_TITLE, sentItem.getTag().getString(WrittenBookItem.TAG_TITLE))); - carried.addTagElement(WrittenBookItem.TAG_PAGES, sentItem.getTag().getList(WrittenBookItem.TAG_PAGES)); - carried.id = Item.writtenBook.id; + sentItem->setHoverName(sentItem->tag->getString(L"title")); + sentItem->id = 387; + player->inventory->setItem(player->inventory->selected, sentItem); } } - else -#endif - if (CustomPayloadPacket::TRADER_SELECTION_PACKET.compare(customPayloadPacket->identifier) == 0) + else if (CustomPayloadPacket::TRADER_SELECTION_PACKET.compare(customPayloadPacket->identifier) == 0) + { + ByteArrayInputStream bais(customPayloadPacket->data); + DataInputStream input(&bais); + int selection = input.readInt(); + + AbstractContainerMenu *menu = player->containerMenu; + if (dynamic_cast(menu)) + { + static_cast(menu)->setSelectionHint(selection); + } + } + else if (CustomPayloadPacket::SET_ADVENTURE_COMMAND_PACKET.compare(customPayloadPacket->identifier) == 0) + { + if (!server->isCommandBlockEnabled()) + { + app.DebugPrintf("Command blocks not enabled"); + //player->sendMessage(ChatMessageComponent.forTranslation("advMode.notEnabled")); + } + else + { + //player.sendMessage(ChatMessageComponent.forTranslation("advMode.notAllowed")); + } + } + else if (CustomPayloadPacket::SET_BEACON_PACKET.compare(customPayloadPacket->identifier) == 0) + { + if ( dynamic_cast( player->containerMenu) != nullptr) { ByteArrayInputStream bais(customPayloadPacket->data); DataInputStream input(&bais); - int selection = input.readInt(); + int primary = input.readInt(); + int secondary = input.readInt(); - AbstractContainerMenu *menu = player->containerMenu; - if (dynamic_cast(menu)) + BeaconMenu *beaconMenu = static_cast(player->containerMenu); + Slot *slot = beaconMenu->getSlot(0); + if (slot->hasItem()) { - static_cast(menu)->setSelectionHint(selection); + slot->remove(1); + shared_ptr beacon = beaconMenu->getBeacon(); + beacon->setPrimaryPower(primary); + beacon->setSecondaryPower(secondary); + beacon->setChanged(); } } - else if (CustomPayloadPacket::SET_ADVENTURE_COMMAND_PACKET.compare(customPayloadPacket->identifier) == 0) + } + else if (CustomPayloadPacket::SET_ITEM_NAME_PACKET.compare(customPayloadPacket->identifier) == 0) + { + AnvilMenu *menu = dynamic_cast( player->containerMenu); + if (menu) { - if (!server->isCommandBlockEnabled()) + if (customPayloadPacket->data.data == nullptr || customPayloadPacket->data.length < 1) { - app.DebugPrintf("Command blocks not enabled"); - //player->sendMessage(ChatMessageComponent.forTranslation("advMode.notEnabled")); + menu->setItemName(L""); } else - { - //player.sendMessage(ChatMessageComponent.forTranslation("advMode.notAllowed")); - } - } - else if (CustomPayloadPacket::SET_BEACON_PACKET.compare(customPayloadPacket->identifier) == 0) - { - if ( dynamic_cast( player->containerMenu) != nullptr) { ByteArrayInputStream bais(customPayloadPacket->data); - DataInputStream input(&bais); - int primary = input.readInt(); - int secondary = input.readInt(); - - BeaconMenu *beaconMenu = static_cast(player->containerMenu); - Slot *slot = beaconMenu->getSlot(0); - if (slot->hasItem()) + DataInputStream dis(&bais); + wstring name = dis.readUTF(); + if (name.length() <= 30) { - slot->remove(1); - shared_ptr beacon = beaconMenu->getBeacon(); - beacon->setPrimaryPower(primary); - beacon->setSecondaryPower(secondary); - beacon->setChanged(); - } - } - } - else if (CustomPayloadPacket::SET_ITEM_NAME_PACKET.compare(customPayloadPacket->identifier) == 0) - { - AnvilMenu *menu = dynamic_cast( player->containerMenu); - if (menu) - { - if (customPayloadPacket->data.data == nullptr || customPayloadPacket->data.length < 1) - { - menu->setItemName(L""); - } - else - { - ByteArrayInputStream bais(customPayloadPacket->data); - DataInputStream dis(&bais); - wstring name = dis.readUTF(); - if (name.length() <= 30) - { - menu->setItemName(name); - } + menu->setItemName(name); } } } + } } bool PlayerConnection::isDisconnected() diff --git a/Minecraft.World/Item.cpp b/Minecraft.World/Item.cpp index ffb3107..457e2a4 100644 --- a/Minecraft.World/Item.cpp +++ b/Minecraft.World/Item.cpp @@ -215,8 +215,8 @@ Item *Item::skull = nullptr; // TU14 -//Item *Item::writingBook = nullptr; -//Item *Item::writtenBook = nullptr; +Item *Item::writingBook = nullptr; +Item *Item::writtenBook = nullptr; Item *Item::emerald = nullptr; @@ -461,8 +461,8 @@ void Item::staticCtor() Item::skull = (new SkullItem(141)) ->setIconName(L"skull")->setDescriptionId(IDS_ITEM_SKULL)->setUseDescriptionId(IDS_DESC_SKULL); // TU14 - //Item::writingBook = (new WritingBookItem(130))->setIcon(11, 11)->setDescriptionId("writingBook"); - //Item::writtenBook = (new WrittenBookItem(131))->setIcon(12, 11)->setDescriptionId("writtenBook"); + Item::writingBook = (new WritingBookItem(130))->setIconName(L"writingBook")->setDescriptionId(-1)->setUseDescriptionId(-1)->setMaxStackSize(1); + Item::writtenBook = (new WrittenBookItem(131))->setIconName(L"writtenBook")->setDescriptionId(-1)->setUseDescriptionId(-1)->setMaxStackSize(1); Item::emerald = (new Item(132)) ->setBaseItemTypeAndMaterial(eBaseItemType_treasure, eMaterial_emerald)->setIconName(L"emerald")->setDescriptionId(IDS_ITEM_EMERALD)->setUseDescriptionId(IDS_DESC_EMERALD); diff --git a/Minecraft.World/Item.h b/Minecraft.World/Item.h index 83cfe55..88e3bd6 100644 --- a/Minecraft.World/Item.h +++ b/Minecraft.World/Item.h @@ -382,8 +382,8 @@ public: static Item *frame; // TU14 - //static Item writingBook; - //static Item writtenBook; + static Item* writingBook; + static Item* writtenBook; static Item *emerald; diff --git a/Minecraft.World/ListTag.h b/Minecraft.World/ListTag.h index f6e1c6a..83ed993 100644 --- a/Minecraft.World/ListTag.h +++ b/Minecraft.World/ListTag.h @@ -12,6 +12,11 @@ public: ListTag() : Tag(L"") {} ListTag(const wstring &name) : Tag(name) {} + //Needed type for some things + byte getType() const { return type; } + void setType(byte newType) { type = newType; } + vector& getList() { return list; } + void write(DataOutput *dos) { if (list.size() > 0) type = (list[0])->getId(); diff --git a/Minecraft.World/WritingBookItem.cpp b/Minecraft.World/WritingBookItem.cpp new file mode 100644 index 0000000..5d3c142 --- /dev/null +++ b/Minecraft.World/WritingBookItem.cpp @@ -0,0 +1,26 @@ +#include "stdafx.h" +#include "Item.h" +#include "Player.h" +#include "ItemInstance.h" +#include "WritingBookItem.h" +#include "../Minecraft.Client/Minecraft.h" +#include "../Minecraft.Client/MultiplayerLocalPlayer.h" + +WritingBookItem::WritingBookItem(int id) : Item(id) +{ + setMaxStackSize(1); +} + +shared_ptr WritingBookItem::use(shared_ptr instance, Level *level, shared_ptr player) +{ + //shared_ptr player1 = Minecraft::GetInstance()->player; + //player1->openItemInstanceGui(instance, player1); + player->openItemInstanceGui(instance); + + return instance; +} + +bool WritingBookItem::TestUse(shared_ptr itemInstance, Level* level, shared_ptr player) +{ + return true; +} \ No newline at end of file diff --git a/Minecraft.World/WritingBookItem.h b/Minecraft.World/WritingBookItem.h new file mode 100644 index 0000000..498c249 --- /dev/null +++ b/Minecraft.World/WritingBookItem.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Item.h" + +class WritingBookItem : public Item +{ +public: + WritingBookItem(int id); + + virtual shared_ptr use(shared_ptr instance, Level* level, shared_ptr player); + virtual bool TestUse(shared_ptr itemInstance, Level* level, shared_ptr player); +}; \ No newline at end of file diff --git a/Minecraft.World/WrittenBookItem.cpp b/Minecraft.World/WrittenBookItem.cpp new file mode 100644 index 0000000..c77d004 --- /dev/null +++ b/Minecraft.World/WrittenBookItem.cpp @@ -0,0 +1,48 @@ +#include "stdafx.h" +#include "HtmlString.h" +#include "WrittenBookItem.h" +#include "../Minecraft.Client/Minecraft.h" +#include "../Minecraft.Client/MultiplayerLocalPlayer.h" + +WrittenBookItem::WrittenBookItem(int id) : Item(id) +{ + +} + +bool WrittenBookItem::isFoil(shared_ptr itemInstance) +{ + return true; +} + +const Rarity* WrittenBookItem::getRarity(shared_ptr itemInstance) +{ + return Rarity::common; +} + +shared_ptr WrittenBookItem::use(shared_ptr instance, Level* level, shared_ptr player) +{ + //shared_ptr player1 = Minecraft::GetInstance()->player; + //player1->openItemInstanceGui(instance, player1); + player->openItemInstanceGui(instance); + + return instance; +} +bool WrittenBookItem::TestUse(shared_ptr itemInstance, Level* level, shared_ptr player) +{ + return true; +} + +void WrittenBookItem::appendHoverText(shared_ptr itemInstance, shared_ptr player, vector* lines, bool advanced) +{ + if (!itemInstance->hasTag()) + { + return; + } + HtmlString stringd = HtmlString(L"By " + (itemInstance->tag->getString(L"author")), eHTMLColor_7, false, false); + HtmlString stringf = HtmlString(L"Original", eHTMLColor_7, false, false); + + + lines->push_back(stringd); + lines->push_back(stringf); + //lines->push_back(wstring(L"tone")); +} \ No newline at end of file diff --git a/Minecraft.World/WrittenBookItem.h b/Minecraft.World/WrittenBookItem.h index 7464855..147d48b 100644 --- a/Minecraft.World/WrittenBookItem.h +++ b/Minecraft.World/WrittenBookItem.h @@ -1,82 +1,18 @@ #pragma once -/* -class WrittenBookItem extends Item { +#include "Item.h" - public static final int TITLE_LENGTH = 16; - public static final int PAGE_LENGTH = 256; - public static final int MAX_PAGES = 50; - public static final String TAG_TITLE = "title"; - public static final String TAG_AUTHOR = "author"; - public static final String TAG_PAGES = "pages"; +class WrittenBookItem : public Item +{ +public: - public WrittenBookItem(int id) { - super(id); - setMaxStackSize(1); - } + wstring authorName = L"Unknown"; - public static boolean makeSureTagIsValid(CompoundTag bookTag) { + WrittenBookItem(int id); + bool isFoil(shared_ptr itemInstance); + const Rarity* getRarity(shared_ptr itemInstance) override; + void appendHoverText(shared_ptr itemInstance, shared_ptr player, vector* lines, bool advanced); - if (!WritingBookItem.makeSureTagIsValid(bookTag)) { - return false; - } - - if (!bookTag.contains(TAG_TITLE)) { - return false; - } - String title = bookTag.getString(TAG_TITLE); - if (title == null || title.length() > TITLE_LENGTH) { - return false; - } - - if (!bookTag.contains(TAG_AUTHOR)) { - return false; - } - - return true; - } - - @Override - public String getHoverName(ItemInstance itemInstance) { - if (itemInstance.hasTag()) { - CompoundTag itemTag = itemInstance.getTag(); - - StringTag titleTag = (StringTag) itemTag.get(TAG_TITLE); - if (titleTag != null) { - return titleTag.toString(); - } - } - return super.getHoverName(itemInstance); - } - - @Override - public void appendHoverText(ItemInstance itemInstance, Player player, List lines, boolean advanced) { - - if (itemInstance.hasTag()) { - CompoundTag itemTag = itemInstance.getTag(); - - StringTag authorTag = (StringTag) itemTag.get(TAG_AUTHOR); - if (authorTag != null) { - lines.add(ChatFormatting.GRAY + String.format(I18n.get("book.byAuthor", authorTag.data))); - } - } - } - - @Override - public ItemInstance use(ItemInstance itemInstance, Level level, Player player) { - player.openItemInstanceGui(itemInstance); - return itemInstance; - } - - @Override - public boolean shouldOverrideMultiplayerNBT() { - return true; - } - - @Override - public boolean isFoil(ItemInstance itemInstance) { - return true; - } - -}; -*/ \ No newline at end of file + virtual shared_ptr use(shared_ptr instance, Level* level, shared_ptr player); + virtual bool TestUse(shared_ptr itemInstance, Level* level, shared_ptr player); +}; \ No newline at end of file diff --git a/Minecraft.World/net.minecraft.world.item.h b/Minecraft.World/net.minecraft.world.item.h index 0772806..183d47f 100644 --- a/Minecraft.World/net.minecraft.world.item.h +++ b/Minecraft.World/net.minecraft.world.item.h @@ -23,6 +23,8 @@ #include "LeafTileItem.h" #include "MapItem.h" #include "MinecartItem.h" +#include "WritingBookItem.h" +#include "WrittenBookItem.h" //#include "PaintingItem.h" #include "PickaxeItem.h" #include "PistonTileItem.h" diff --git a/cmake/WorldSources.cmake b/cmake/WorldSources.cmake index 4292148..d46ddd2 100644 --- a/cmake/WorldSources.cmake +++ b/cmake/WorldSources.cmake @@ -783,6 +783,8 @@ set(MINECRAFT_WORLD_SOURCES "WoolCarpetTile.cpp" "WoolTileItem.cpp" "WorkbenchTile.cpp" + "WrittenBookItem.cpp" + "WritingBookItem.cpp" "XZPacket.cpp" "Zombie.cpp" "ZoomLayer.cpp"