From 973c71ffde630b45fdb6466f0f123d35a609196a Mon Sep 17 00:00:00 2001 From: piebot Date: Sun, 5 Apr 2026 13:04:15 +0200 Subject: [PATCH 1/2] Update .gitea/ISSUE_TEMPLATE/bug_report.yml --- .gitea/ISSUE_TEMPLATE/bug_report.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitea/ISSUE_TEMPLATE/bug_report.yml b/.gitea/ISSUE_TEMPLATE/bug_report.yml index 63c0478f..0505b8bb 100644 --- a/.gitea/ISSUE_TEMPLATE/bug_report.yml +++ b/.gitea/ISSUE_TEMPLATE/bug_report.yml @@ -59,6 +59,13 @@ body: validations: required: true + - type: input + id: smartcmd + attributes: + label: Is this reproducable in smartcmd/MinecraftConsoles? (https://github.com/smartcmd/MinecraftConsoles) + validations: + required: true + - type: checkboxes id: build attributes: From 546a279cc9b2e4434532b811a6adb25165840d88 Mon Sep 17 00:00:00 2001 From: SevenToaster509 Date: Sun, 5 Apr 2026 15:05:03 +0100 Subject: [PATCH 2/2] Book & Quill - Initial Commit Implement Book & Quill: - IUIScene_WritingBookMenu and UIScene_BookAndQuillMenu for UI - Edited UIControl_Label to add direct editing (quite hardcoded to my needs right now) - Reimplement scrapped custom payload packets for books and signing - Other misc changes TODO: - Coloured and scambled text - Book copying - Clean up code --- Minecraft.Client/Common/Audio/SoundNames.cpp | 3 + Minecraft.Client/Common/Consoles_App.cpp | 15 + Minecraft.Client/Common/Consoles_App.h | 1 + .../Common/Media/MediaWindows64.arc | Bin 28555724 -> 28585583 bytes .../UI/IUIScene_AbstractContainerMenu.cpp | 6 +- .../Common/UI/IUIScene_CreativeMenu.cpp | 6 + .../Common/UI/IUIScene_WritingBookMenu.cpp | 274 +++++++++ .../Common/UI/IUIScene_WritingBookMenu.h | 47 ++ Minecraft.Client/Common/UI/UI.h | 2 + Minecraft.Client/Common/UI/UIControl.h | 2 + Minecraft.Client/Common/UI/UIControl_Base.cpp | 15 + Minecraft.Client/Common/UI/UIControl_Base.h | 2 + Minecraft.Client/Common/UI/UIControl_Book.cpp | 55 ++ Minecraft.Client/Common/UI/UIControl_Book.h | 16 + .../Common/UI/UIControl_Label.cpp | 251 +++++++- Minecraft.Client/Common/UI/UIControl_Label.h | 35 +- .../Common/UI/UIControl_PageFlip.cpp | 55 ++ .../Common/UI/UIControl_PageFlip.h | 16 + Minecraft.Client/Common/UI/UIController.cpp | 2 +- Minecraft.Client/Common/UI/UIEnums.h | 2 +- Minecraft.Client/Common/UI/UILayer.cpp | 6 + Minecraft.Client/Common/UI/UIScene.cpp | 14 +- Minecraft.Client/Common/UI/UIScene.h | 5 + .../Common/UI/UIScene_BookAndQuillMenu.cpp | 572 ++++++++++++++++++ .../Common/UI/UIScene_BookAndQuillMenu.h | 106 ++++ Minecraft.Client/Common/UI/UIStructs.h | 10 + Minecraft.Client/LocalPlayer.cpp | 26 + Minecraft.Client/LocalPlayer.h | 1 + Minecraft.Client/Minecraft.cpp | 19 +- Minecraft.Client/PlayerConnection.cpp | 175 +++--- .../Windows64/Windows64_Minecraft.cpp | 10 +- .../Sound/Minecraft/UI/open_flip1.ogg | Bin 0 -> 8850 bytes .../Sound/Minecraft/UI/open_flip2.ogg | Bin 0 -> 8570 bytes .../Sound/Minecraft/UI/open_flip3.ogg | Bin 0 -> 7647 bytes Minecraft.Client/Windows64Media/strings.h | 11 +- Minecraft.Client/cmake/sources/Common.cmake | 4 + Minecraft.Client/cmake/sources/Windows.cmake | 6 + Minecraft.World/Item.cpp | 8 +- Minecraft.World/Item.h | 8 +- Minecraft.World/ListTag.h | 5 + Minecraft.World/Player.cpp | 3 +- Minecraft.World/Player.h | 2 +- Minecraft.World/Recipes.cpp | 7 + Minecraft.World/SoundTypes.h | 3 + Minecraft.World/WritingBookItem.cpp | 26 + Minecraft.World/WritingBookItem.h | 12 + Minecraft.World/WrittenBook.h | 18 + Minecraft.World/WrittenBookItem.cpp | 48 ++ Minecraft.World/cmake/sources/Common.cmake | 5 + 49 files changed, 1800 insertions(+), 115 deletions(-) create mode 100644 Minecraft.Client/Common/UI/IUIScene_WritingBookMenu.cpp create mode 100644 Minecraft.Client/Common/UI/IUIScene_WritingBookMenu.h create mode 100644 Minecraft.Client/Common/UI/UIControl_Book.cpp create mode 100644 Minecraft.Client/Common/UI/UIControl_Book.h create mode 100644 Minecraft.Client/Common/UI/UIControl_PageFlip.cpp create mode 100644 Minecraft.Client/Common/UI/UIControl_PageFlip.h create mode 100644 Minecraft.Client/Common/UI/UIScene_BookAndQuillMenu.cpp create mode 100644 Minecraft.Client/Common/UI/UIScene_BookAndQuillMenu.h create mode 100644 Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip1.ogg create mode 100644 Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip2.ogg create mode 100644 Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip3.ogg create mode 100644 Minecraft.World/WritingBookItem.cpp create mode 100644 Minecraft.World/WritingBookItem.h create mode 100644 Minecraft.World/WrittenBook.h create mode 100644 Minecraft.World/WrittenBookItem.cpp diff --git a/Minecraft.Client/Common/Audio/SoundNames.cpp b/Minecraft.Client/Common/Audio/SoundNames.cpp index 8e19216e..4f2373f7 100644 --- a/Minecraft.Client/Common/Audio/SoundNames.cpp +++ b/Minecraft.Client/Common/Audio/SoundNames.cpp @@ -243,4 +243,7 @@ const WCHAR *ConsoleSoundEngine::wchUISoundNames[eSFX_MAX]= L"focus", L"press", L"scroll", + L"open_flip1", + L"open_flip2", + L"open_flip3" }; diff --git a/Minecraft.Client/Common/Consoles_App.cpp b/Minecraft.Client/Common/Consoles_App.cpp index 9c094b6b..f5ede7d9 100644 --- a/Minecraft.Client/Common/Consoles_App.cpp +++ b/Minecraft.Client/Common/Consoles_App.cpp @@ -778,6 +778,21 @@ bool CMinecraftApp::LoadBeaconMenu(int iPad ,shared_ptr inventory, sh return success; } +bool CMinecraftApp::LoadWritingBookMenu(int iPad, shared_ptr instance, shared_ptr player, bool editable) +{ + bool success = true; + + WritingBookMenuParams* initData = new WritingBookMenuParams(); + initData->itemInstance = instance; + initData->player = player; + initData->iPad = iPad; + initData->isEditable = editable; + + success = ui.NavigateToScene(iPad, eUIScene_BookMenu, initData); + + return success; +} + ////////////////////////////////////////////// // GAME SETTINGS ////////////////////////////////////////////// diff --git a/Minecraft.Client/Common/Consoles_App.h b/Minecraft.Client/Common/Consoles_App.h index bd294b46..8a3d1c47 100644 --- a/Minecraft.Client/Common/Consoles_App.h +++ b/Minecraft.Client/Common/Consoles_App.h @@ -149,6 +149,7 @@ public: bool LoadHopperMenu(int iPad ,shared_ptr inventory, shared_ptr hopper); bool LoadHorseMenu(int iPad ,shared_ptr inventory, shared_ptr container, shared_ptr horse); bool LoadBeaconMenu(int iPad ,shared_ptr inventory, shared_ptr beacon); + bool LoadWritingBookMenu(int iPad, shared_ptr instance, shared_ptr player, bool editable); bool GetTutorialMode() { return m_bTutorialMode;} void SetTutorialMode(bool bSet) {m_bTutorialMode=bSet;} diff --git a/Minecraft.Client/Common/Media/MediaWindows64.arc b/Minecraft.Client/Common/Media/MediaWindows64.arc index 70c6ec67ee74241d25fa4a4362ad1cd306eaa5ae..4fa07d7313caaf21e4c55775a558c4794b28e90e 100644 GIT binary patch delta 36639 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 delta 6573 zcmZ9Pc|era`p3_CS(JTP2WFTZ1Z0ui1w>I$Oe_$$O4AW0nS>dF!7Z0e%W}sjH?ndq zazkxFvogE)nwgr}qTZWnU4NEKrCFw>_4_{HyyE@i^LgPsXM4{3zUQ6u^Vi2h4qrPO zk|u6#qVST?(sIQlr_o!AO-`p%N`kDTzfe+5MxVIu(}d{zo6z*HaMXI* zX0l?s8w8hUXbLp^Of=r~VehEtCWzzbav6?;oP4WPZf=|&Dl)OW$ z{S#yjz3-nWU!!v{iPuvn>bfbvuU*oWQoRb`FABC5X zZp2fPes9pbcCTnZqy6m+GMmn{v&bDJ+goRyM)g9hb(_A_jMnx}6k_mWA{5bbr$=46 zwa+aOqF26J?(Ki={!dXJiluI?udd|UKQK(z9yOqjur9va3L*OR5}JJEQqeY(b)HY@ z{q}J@!R`SfT#c)pt~-0aB^0fON~+2fF~}y5(-M@V()J*|oJ@y;bUBCc^mg7OBJ+#-53xI2wgq+cS8u;0L=WpdK{d(O zy6z)$ut9!7x$p!U9c+{V^d#J!8e0C|18<{~!6w;_ZUo!p35pL%zz&cXVv+{3hiKzI z!0pZyp#`q;Vz;BpyYib0u26kQ?5uS{8j{i4eWdil_n38pmXJ&BR(t4h_xSf_Hmx zo5HsDZEM%-h~6)v)g~NO$JsiyFL^?(atW;rwaL$DZ>Z5P9SsJO42uf#PJG*Z58Xzs zDl&)JU^Enh3jPxdN150chc!_lVZ3^e}(J)3en~=%TJ$abBxY9n= zyDV=NIPm4`)+XXj_^sLoN{`gZrdko%DkJ=cjSwSC)Jzumq9(M=-yo~U|%-p&i5 z4Utx?`GH8Ae2^|i8kCDaQ$UmvE0i2%nuU9x{xvVhow=#cO7pCFnA}$)tZ>+nqWU?&G;t9-HfnJB_ z^G=klZbiF$+Yvd4#b}Lq?zX8+LF9Z(N9y!;zZga`+9Fqz4UVURXsaxzis%lqFD;2q z!W-KhZBfKE`ggPud&*6C2F1phUSS~G@T5TeU%5j==L zqTaQ6|Jn0GmfyTn>Rp|Em(EaqY)ova@auC{gtW9!lRL1e3+;>5MXrOuCrS$3@hdJtC^e?wU|%pWvwFXV072ne7Yk z>=pb^)H{JQ=Z_&eSVZ5`RvqQ6Nl*1Ui!!o?-qcx@B_Gg9ox%U0584bMi(ad49^Z;V zWY8!04>bx={0F)8T6$C;sBDO($MuQI^)jm08-3r4G;7f*A)l-i+9HR& z+)>k#9nV``-}3=VML1W zMn*Wv9p7Hj#M9JxgHmxHt-@v73)CEMR4#9&6Y)lUmowNA#)>fS$H=>&7pCTt#-Q!K z{X6XQ8-&IiR|mUr?iobZ-;Jm#UDPGf7=uA6NucSt44pwQ8jMP*iT3j4UHXq9&M@p@ ze2VTD;X@p?wYZo4+*7>iU0k%0!i_rRqjr>TG%8{S4KbROtbOD{p+}+l_-|VdZNX)G z933{AmF?ftPq;MgC5=hjZO2j}GKY$=V!O*-W3RG%`@M7)nPd(Y8gD?&~Wbzck8KnU0xq4#Nu-tsjI!`SKN=8zta&@Y>wk5epuWV;c5kSj2|2D z?dtlsh*m@Q{P_9t)8EKqHY&bfP@XwX>9vbSn@vi!FU`PZ`bm1(Y*u#1&^%8hvR^RAwKcThrinJIGU5g; zvDw-$#8cMw2VtToY>{-t7OL#;N2hJc?XNeY{DRQ8l$#R*mDGAlORy>9Zc+&@Yv$3U zgaqYe46R8>Rw6#60|_Zg(M`IVkdX82G9j`TA+tO4Z2QXo_Mr)rk@p6@Yx3LgW-3XH zSJL9iooH6<*m4pr=H>jvd?TXTcBkHh>xWLz@kFa4Q|LM_d8MT5U{hw#q&^*zln*XY zMTaDx-~UdfWhl-0j+#3d@@52JdNCr}+u!g(JVEaqZtTVcvkfBV-mtpFH?HMSbdps` zpF_QpY)Zv)dNj$XY>20sN%6|*jkE@ra6ft{$)Mae(WxYhl4++~Xi&D2%*lqRm43)( zglNx4XFj&diccP)lH^#$?4gO))ET*HW((bC*AUMg45=dA+c%yrs$3Kpa19bwbnH%^=r6dzGU# zlD?4^ro;|h+*^p)O|1udwbiTG4Q$s$D7R|c=FpcyjN9K@USuEdsH|=2Yg_6Hx|Cv2 z@+VSYM}sndFr{=fD#sVmppI5W_cv8_w9T?VCB(pAvAF26)KTduYdKka@21@TI*#`P zr-PmYp4&E7_DIU4~%4H$64~yVo&MHUEo!wV9wI6^VHXq$7y>t6yQ*cO2X-G?5 z?_HBkVP6R0D=92BCN2`w_f2t{mp9u2nmJ$V1hs zvC7K6G(R<7`BFoTsfPH7bh!g&b#_V;e&hZ zf1=(g?wX8)Q_lk;`kuDx8tmG!neI!sD3_XPSh`h7m_t+24bfw%rN@AQHTLQXXIbrN z`Npa;+KdXg98EVWTL;ol=?VUCAHlr-o|Ba^FDpX=1^578;0OFcJJ22kfItugffDxF08CZZ7*gyhE1RX#UNCqjOBS-~lARX|$ zJAq7aALtCafUck$=ni^-o}d@V0@)x3^ai=059kZ>KtIqQU=ElIo&nE-dEhzl zJeUs_fQ4WYSPYhcrJx=x0|Z_G%fSk;608ENK?8UZtN|~9m%%GwEm#NEgAHIK*aTh$ zuYpGJI@k=hfURH~*bbV&4zLsK0&jpf!CT;M&VU%7rYDJ1Mh=<-~+H9dNR>q-E{;Mo6S=lb)lM3mYR~_*QINV$vairh!c@2$6z)|oiI0ilg z$HC{|3-BfQ3Y-8Z!71=>@E`CsI1Ro5XTVwTE%*-n7n}qC2hM}F#@E7=dK|`Zl0$2*mhvm!iWBIe%vD&i& zSb?k{Rxm4s70L=@X;|T`2v#I3iWSX@VQE>htT>jArDw&n3@jtd#4@uiEF1+J8gUYA zXiQ)wvO2JmSjnsuR!3GUD~*-T%3yV3WwP#Lb!K&8b!By9b!YWp^^H|TZo@dQxEnqEV zEn+QZEnzKX)w7ndi1h+%Ico)LC2JLHHLHR3B5MunCDzNVS6FLV>saeq8(14zn^>>1 kUSl<~UT1A)ZDDO?ZDVa`HL-TEcCvQKeGQFo$ef7(2L%V=hyVZp diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp index 918bd8e6..a393a097 100644 --- a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp +++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp @@ -1518,8 +1518,12 @@ bool IUIScene_AbstractContainerMenu::handleKeyDown(int iPad, int iAction, bool b { Tutorial::PopupMessageDetails *message = new Tutorial::PopupMessageDetails; message->m_messageId = item->getUseDescriptionId(); + if(Item::items[item->id] != nullptr) message->m_titleString = Item::items[item->id]->getHoverName(item); + if (item->id == 387) { + message->m_titleString = item->getHoverName(); + } message->m_titleId = item->getDescriptionId(); message->m_icon = item->id; @@ -1689,7 +1693,7 @@ vector *IUIScene_AbstractContainerMenu::GetItemDescription(Slot *slo { lines->at(0).color = slot->getItem()->getRarity()->color; - if(slot->getItem()->hasCustomHoverName()) + if (slot->getItem()->hasCustomHoverName() && slot->getItem()->id != 387) { lines->at(0).color = eTextColor_RenamedItemTitle; } diff --git a/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp index 7304dc00..6e2ad2b3 100644 --- a/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp +++ b/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp @@ -139,6 +139,8 @@ void IUIScene_CreativeMenu::staticCtor() ITEM(Item::door_acacia_Id) ITEM(Item::door_dark_Id) + + ITEM_AUX(Tile::stoneSlabHalf_Id,StoneSlabTile::STONE_SLAB) ITEM_AUX(Tile::stoneSlabHalf_Id,StoneSlabTile::SAND_SLAB) // AP - changed oak slab to be wood because it wouldn't burn @@ -402,6 +404,10 @@ void IUIScene_CreativeMenu::staticCtor() ITEM(Item::snowBall_Id) ITEM(Item::paper_Id) ITEM(Item::book_Id) + + //TU25 + ITEM(Item::writingBook_Id) + ITEM(Item::enderPearl_Id) ITEM(Item::eyeOfEnder_Id) ITEM(Item::nameTag_Id) diff --git a/Minecraft.Client/Common/UI/IUIScene_WritingBookMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_WritingBookMenu.cpp new file mode 100644 index 00000000..6d8ad23b --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_WritingBookMenu.cpp @@ -0,0 +1,274 @@ +#include "stdafx.h" +#include +#include "IUIScene_WritingBookMenu.h" +#include "MultiPlayerLocalPlayer.h" +#include "MultiPlayerLocalPlayer.h" +#include "Common\UI\UI.h" +#include "ClientConnection.h" +#include "../Minecraft.World/CustomPayloadPacket.h" + +void IUIScene_WritingBookMenu::Init(shared_ptr itemInstance) +{ + //m_itemInstance = make_shared(*itemInstance); + m_itemInstance = itemInstance; + + app.DebugPrintf(("itemInstance hasTag = " + std::to_string(itemInstance->hasTag()) + "\n").c_str()); + app.DebugPrintf(("m_itemInstance hasTag = " + std::to_string(m_itemInstance->hasTag()) + "\n").c_str()); + + if (itemInstance->hasTag()) //m_itemInstance->hasTag() + { + CompoundTag* itemTag = m_itemInstance->getTag(); + + if (itemTag->contains(L"pages")) + { + ListTag* pagesTag = itemTag->getList(L"pages"); + + if (pagesTag && pagesTag->size() > 0) + { + m_currentPage = pagesTag; + CompoundTag* firstPage = static_cast(pagesTag->get(0)); + + if (firstPage) + { + m_totalPages = pagesTag->size(); + updateTooltips(); + return; + } + } + } + + } + + if (!itemInstance) { + ListTag* pagesListTag = new ListTag(L"pages"); + m_currentPage = pagesListTag; // SET IT + + CompoundTag* firstPageTag = new CompoundTag(L""); + firstPageTag->putString(L"text", L""); + + pagesListTag->add(firstPageTag); + + m_totalPages = 1; + m_currentPageIndex = 0; + + if (!m_itemInstance->hasTag()) + { + CompoundTag* rootTag = new CompoundTag(L""); + rootTag->put(L"pages", pagesListTag); + itemInstance->setTag(rootTag); + m_itemInstance = itemInstance; + } + else + { + itemInstance->getTag()->put(L"pages", pagesListTag); + m_itemInstance = itemInstance; + } + updateTooltips(); + return; + } + + ListTag* pagesListTag = new ListTag(L"pages"); + m_currentPage = pagesListTag; + + CompoundTag* firstPageTag = new CompoundTag(L""); + firstPageTag->putString(L"text", L""); + + pagesListTag->add(firstPageTag); + + m_totalPages = 1; + updateTooltips(); + return; +} + + + +void IUIScene_WritingBookMenu::SaveChanges(bool signBook) +{ + ListTag* pagesTag = static_cast*>(m_currentPage); + if (!pagesTag) + return; + + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + + if (!m_itemInstance->hasTag()) + { + // Create new NBT tag structure + CompoundTag* rootTag = new CompoundTag(L""); + rootTag->put(L"pages", pagesTag); + m_itemInstance->setTag(rootTag); + + + } + else + { + // Update existing NBT + CompoundTag* rootTag = m_itemInstance->tag; + rootTag->put(L"pages", pagesTag); // Update pages + } + + if (signBook) + { + std::shared_ptr player = Minecraft::GetInstance()->localplayers[iPadLocal]; + std::wstring authorName = player->getName(); + + CompoundTag* rootTag = m_itemInstance->getTag(); + rootTag->putString(L"author", authorName); + + // Add title tag + rootTag->putString(L"title", m_bookTitle); + + Packet::writeItem(m_itemInstance, &dos); + Minecraft::GetInstance()->localplayers[iPadLocal]->connection->send(std::make_shared(CustomPayloadPacket::CUSTOM_BOOK_SIGN_PACKET, baos.toByteArray())); + + return; + } + + + Packet::writeItem(m_itemInstance, &dos); + Minecraft::GetInstance()->localplayers[iPadLocal]->connection->send(std::make_shared(CustomPayloadPacket::CUSTOM_BOOK_PACKET, baos.toByteArray())); + return; +} + +std::wstring IUIScene_WritingBookMenu::getCurrentPageText() +{ + if (!m_currentPage) return L"error"; + int index = m_currentPageIndex; + if (index < 0) return L"error"; + + ListTag* pagesList = static_cast*>(m_currentPage); + if (index >= pagesList->size()) return L"error"; + + CompoundTag* pageTag = static_cast(pagesList->get(index)); + + return pageTag->getString(L"text"); +} + +void IUIScene_WritingBookMenu::setCurrentPageText(const std::wstring& newText, int indexOverride) +{ + if (signing == true) return; + //if (newText.empty()) return; + if (!m_currentPage) return; + + int index = m_currentPageIndex; + if (index < 0) return; + + if (indexOverride >= 0) index = indexOverride; + + ListTag* pagesList = static_cast*>(m_currentPage); + if (index >= pagesList->size()) return; + + CompoundTag* pageTag = static_cast(pagesList->get(index)); + + pageTag->putString(L"text", newText); +} + +//Pretty sure im not using this +IUIScene_WritingBookMenu::IUIScene_WritingBookMenu() +{ + m_currentPage = nullptr; + + m_totalPages = 0; + m_currentPageIndex = 0; +} + +void IUIScene_WritingBookMenu::updateTooltips() +{ + ui.SetTooltipText(iPadLocal, eToolTipButtonA, IDS_TOOLTIPS_SELECT); + ui.SetTooltipText(iPadLocal, eToolTipButtonB, IDS_TOOLTIPS_BACK); + //ui.SetTooltips(iPadLocal); + + /*enum EToolTipButton + { + eToolTipButtonA = 0, + eToolTipButtonB, + eToolTipButtonX, + eToolTipButtonY, + eToolTipButtonLT, + eToolTipButtonRT, + eToolTipButtonLB, + eToolTipButtonRB, + eToolTipButtonLS, + eToolTipButtonRS, + eToolTipButtonBack, + eToolTipNumButtons + };*/ + + if ((m_currentPageIndex+1) < m_totalPages) { + //ui.SetTooltips(iPadLocal, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, -1, -1, -1, -1, IDS_TOOLTIPS_NEXTPAGE); + ui.SetTooltipText(iPadLocal, eToolTipButtonRB, IDS_TOOLTIPS_NEXTPAGE); + } + else if ((m_currentPageIndex + 1) == m_totalPages && !signedBook) { + //ui.SetTooltips(iPadLocal, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK, -1, -1, -1, -1, -1, IDS_TOOLTIPS_ADDPAGE); + ui.SetTooltipText(iPadLocal, eToolTipButtonRB, IDS_TOOLTIPS_ADDPAGE); + } + else if ((m_currentPageIndex + 1) == m_totalPages && signedBook) { + ui.ShowTooltip(iPadLocal, eToolTipButtonRB, false); + } + if (m_currentPageIndex != 0) { + ui.SetTooltipText(iPadLocal, eToolTipButtonLB, IDS_TOOLTIPS_BACKPAGE); + } + else if (m_currentPageIndex == 0) { + ui.ShowTooltip(iPadLocal, eToolTipButtonLB, false); + } +} + +shared_ptr IUIScene_WritingBookMenu::OnDoneButtonPress() +{ + if (0 == 1) //temporary, to check permissions later on + { + return nullptr; + } + + if (!signedBook) + { + SaveChanges(false); + app.DebugPrintf(("m_itemInstance hasTag = " + std::to_string(m_itemInstance->tag->getAllTags()->size()) + "\n").c_str()); + } + + ui.PlayUISFX(eSFX_Back); +} + +void IUIScene_WritingBookMenu::ScrollPageRight() +{ + if (m_currentPageIndex >= m_totalPages - 1) + { + if (signedBook) return; + + if (m_totalPages < 50) // Max 50 pages //TODO: Make this a controlled variable if I want to change it in the future + { + ListTag* pagesTag = static_cast*>(m_currentPage); + if (!pagesTag) + return; + + if (pagesTag->size() >= 50) + return; + + CompoundTag* newPageTag = new CompoundTag(L""); + newPageTag->putString(L"text", L""); + + pagesTag->add(newPageTag); + + m_totalPages++; + + } + else { + return; + } + } + int r = rand() % 3; + ESoundEffect sfx = static_cast(r + 6); + ui.PlayUISFX(sfx); + m_currentPageIndex++; +} + +void IUIScene_WritingBookMenu::ScrollPageLeft() +{ + if (!(m_currentPageIndex <= 0)) + { + m_currentPageIndex--; + int r = rand() % 3; + ESoundEffect sfx = static_cast(r + 6); + ui.PlayUISFX(sfx); + } +} \ No newline at end of file diff --git a/Minecraft.Client/Common/UI/IUIScene_WritingBookMenu.h b/Minecraft.Client/Common/UI/IUIScene_WritingBookMenu.h new file mode 100644 index 00000000..b997a43b --- /dev/null +++ b/Minecraft.Client/Common/UI/IUIScene_WritingBookMenu.h @@ -0,0 +1,47 @@ +#pragma once + +#include "Common/UI/IUIScene_AbstractContainerMenu.h" +#include "..\Minecraft.World\AbstractContainerMenu.h" + +class SimpleContainer; + +class IUIScene_WritingBookMenu +{ + public: + void IUIScene_WritingBookMenu::Init(shared_ptr itemInstance); + + IUIScene_WritingBookMenu::IUIScene_WritingBookMenu(); + + void IUIScene_WritingBookMenu::SaveChanges(bool signBook); + + std::wstring IUIScene_WritingBookMenu::getCurrentPageText(); + + shared_ptr IUIScene_WritingBookMenu::OnDoneButtonPress(); + + void IUIScene_WritingBookMenu::setCurrentPageText(const std::wstring& newText, int indexOverride = -1); + + void IUIScene_WritingBookMenu::ScrollPageRight(); + void IUIScene_WritingBookMenu::ScrollPageLeft(); + + + + shared_ptr m_itemInstance; + ItemInstance* m_itemInstanceCopy = new ItemInstance(0, 0, 0); + ListTag* m_currentPage; + ListTag m_currentPageCopy; + int m_totalPages = 2; + int m_currentPageIndex = 0; + int iRealWidth = 0; + + int iPadLocal; + + bool signing = false; + bool signedBook = false; + + std::wstring m_bookTitle = L""; + std::wstring m_label = L""; + + + protected: + virtual void updateTooltips(); +}; \ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UI.h b/Minecraft.Client/Common/UI/UI.h index a7c416f8..3159ced6 100644 --- a/Minecraft.Client/Common/UI/UI.h +++ b/Minecraft.Client/Common/UI/UI.h @@ -109,6 +109,8 @@ #include "UIScene_BeaconMenu.h" #include "UIScene_FireworksMenu.h" +#include "UIScene_BookAndQuillMenu.h" + #include "UIScene_CraftingMenu.h" #include "UIScene_SignEntryMenu.h" diff --git a/Minecraft.Client/Common/UI/UIControl.h b/Minecraft.Client/Common/UI/UIControl.h index 8445af0f..692e6a4e 100644 --- a/Minecraft.Client/Common/UI/UIControl.h +++ b/Minecraft.Client/Common/UI/UIControl.h @@ -31,6 +31,8 @@ public: eTexturePackList, eBitmapIcon, eTouchControl, + eBook, + ePageFlip, }; protected: eUIControlType m_eControlType; diff --git a/Minecraft.Client/Common/UI/UIControl_Base.cpp b/Minecraft.Client/Common/UI/UIControl_Base.cpp index 2c76b463..13fe3375 100644 --- a/Minecraft.Client/Common/UI/UIControl_Base.cpp +++ b/Minecraft.Client/Common/UI/UIControl_Base.cpp @@ -17,12 +17,27 @@ bool UIControl_Base::setupControl(UIScene *scene, IggyValuePath *parent, const s m_setLabelFunc = registerFastName(L"SetLabel"); m_initFunc = registerFastName(L"Init"); + m_funcGetH = registerFastName(L"height"); m_funcGetLabel = registerFastName(L"GetLabel"); m_funcCheckLabelWidths = registerFastName(L"CheckLabelWidths"); return success; } +int UIControl_Base::height() { + //IggyDataValue result; + //IggyResult out = IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, getIggyValuePath(), m_funcGetH, 0, nullptr); + F64 t; + IggyValueGetF64RS(getIggyValuePath(), m_funcGetH, nullptr, &t); + + if (t) + { + //m_label = wstring((wchar_t*)result.string16.string, result.string16.length); + return static_cast(t); + } + return -1; +} + void UIControl_Base::tick() { UIControl::tick(); diff --git a/Minecraft.Client/Common/UI/UIControl_Base.h b/Minecraft.Client/Common/UI/UIControl_Base.h index 73ecac5a..b106b53a 100644 --- a/Minecraft.Client/Common/UI/UIControl_Base.h +++ b/Minecraft.Client/Common/UI/UIControl_Base.h @@ -10,6 +10,7 @@ protected: IggyName m_initFunc; IggyName m_setLabelFunc; IggyName m_funcGetLabel; + IggyName m_funcGetH; IggyName m_funcCheckLabelWidths; bool m_bLabelChanged; @@ -21,6 +22,7 @@ public: virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); virtual void tick(); + int height(); virtual void setLabel(UIString label, bool instant = false, bool force = false); //virtual void setLabel(wstring label, bool instant = false, bool force = false) { this->setLabel(UIString::CONSTANT(label), instant, force); } diff --git a/Minecraft.Client/Common/UI/UIControl_Book.cpp b/Minecraft.Client/Common/UI/UIControl_Book.cpp new file mode 100644 index 00000000..77d276c9 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Book.cpp @@ -0,0 +1,55 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_Book.h" + +UIControl_Book::UIControl_Book() +{ +} + +bool UIControl_Book::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::eBook); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + return success; +} + +void UIControl_Book::init(UIString label, int id) +{ + m_label = label; + m_id = id; + + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = id; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 2 , value ); + +#ifdef __PSVITA__ + // 4J-PB - add this button to the vita touch box list + + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Error: + case eUILayer_Fullscreen: + case eUILayer_Scene: + case eUILayer_HUD: + ui.TouchBoxAdd(this,m_parentScene); + break; + } +#endif +} + +void UIControl_Book::ReInit() +{ + UIControl_Base::ReInit(); + + init(m_label, m_id); +} diff --git a/Minecraft.Client/Common/UI/UIControl_Book.h b/Minecraft.Client/Common/UI/UIControl_Book.h new file mode 100644 index 00000000..062d8ce0 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_Book.h @@ -0,0 +1,16 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_Book : public UIControl_Base +{ +public: + UIControl_Book(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(UIString label, int id); + //void init(const wstring &label, int id) { init(UIString::CONSTANT(label), id); } + + virtual void ReInit(); +}; \ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_Label.cpp b/Minecraft.Client/Common/UI/UIControl_Label.cpp index 2f400db5..d6b77de9 100644 --- a/Minecraft.Client/Common/UI/UIControl_Label.cpp +++ b/Minecraft.Client/Common/UI/UIControl_Label.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" #include "UI.h" #include "UIControl_Label.h" -#include "../../../Minecraft.World/StringHelpers.h" +#include "..\..\..\Minecraft.World\StringHelpers.h" UIControl_Label::UIControl_Label() { @@ -10,27 +10,50 @@ UIControl_Label::UIControl_Label() bool UIControl_Label::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) { + if (!parent) { + + } UIControl::setControlType(UIControl::eLabel); bool success = UIControl_Base::setupControl(scene,parent,controlName); //Label specific initialisers - + //m_funcGetLabel = registerFastName(L"gHeight"); + m_funcSetCaretIndex = registerFastName(L"SetCaretIndex"); return success; } -void UIControl_Label::init(UIString label) +void UIControl_Label::UpdateCaretIndex(int index) { + if (!m_parentScene || !m_parentScene->getMovie()) + return; + + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = index; + IggyResult out = IggyPlayerCallMethodRS(m_parentScene->getMovie(), &result, getIggyValuePath(), m_funcSetCaretIndex, 1, value); +} + +void UIControl_Label::init(UIString label, int id) { m_label = label; + m_id = id; IggyDataValue result; - IggyDataValue value[1]; + IggyDataValue value[2]; value[0].type = IGGY_DATATYPE_string_UTF16; IggyStringUTF16 stringVal; stringVal.string = (IggyUTF16*)label.c_str(); stringVal.length = label.length(); value[0].string16 = stringVal; - IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value ); + + value[1].type = IGGY_DATATYPE_number; + value[1].number = id; + + app.DebugPrintf(("Initialised with id" + std::to_string(id)).c_str()); + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 2 , value ); + + app.DebugPrintf(("Initialised with result " + std::to_string(out)).c_str()); } void UIControl_Label::ReInit() @@ -38,8 +61,224 @@ void UIControl_Label::ReInit() UIControl_Base::ReInit(); // 4J-JEV: This can't be reinitialised. - if (m_reinitEnabled) + /*if (m_reinitEnabled) { init(m_label); + }*/ + + init(m_label, m_id); +} + +#ifdef _WINDOWS64 + +void UIControl_Label::beginDirectEdit(int charLimit, bool bSigning, wstring author) +{ + m_textBeforeEdit = m_editBuffer; + m_iCharLimit = charLimit; + m_bDirectEditing = true; + m_iDirectEditCooldown = 0; + m_iCaretBlinkTimer = 0; + authorName = author; + + signing = bSigning; + + g_KBMInput.ClearCharBuffer(); +} + +UIControl_Label::EDirectEditResult UIControl_Label::tickDirectEdit() +{ + if (this->hasFocus() == false) { + //Clear characters typed while not in focus, or we'll get a suprise... ;3 + g_KBMInput.ClearCharBuffer(); + return eDirectEdit_Continue; + } + + auto parent = (UIScene_BookAndQuillMenu*)this->getParentScene(); + + if (m_iDirectEditCooldown > 0) + m_iDirectEditCooldown--; + + if (!m_bDirectEditing) + { + return eDirectEdit_Continue; + } + int bufferLen; + if (!signing) { + bufferLen = (int)m_editBuffer.length(); + } + else { + bufferLen = (int)m_editBuffer.length(); + } + + + // Clamp cursor position to valid range + if (m_iCursorPos < m_cPosMin) m_iCursorPos = m_cPosMin; + if (m_iCursorPos > bufferLen) m_iCursorPos = bufferLen; + + wstring display; + // Display cursor + if (!signing) { + display = m_editBuffer; + } + else { + display = L"Enter Book Title:\r" + m_editBuffer + L" \rby " + authorName + L"\r\rNote! When you sign the book, it will no longer be editable."; + } + + auto countLines = [](const wstring& text) -> int { + int total = 0; + size_t start = 0; + while (true) { + size_t newline = text.find(L'\r', start); + size_t segLen = (newline == wstring::npos) ? text.length() - start : newline - start; + total += max(1, (int)((segLen + 22) / 23)); + if (newline == wstring::npos) break; + start = newline + 1; + } + return total; + }; + + EDirectEditResult result = eDirectEdit_Continue; + bool changed = false; + + // Consume typed characters + wchar_t ch; + while (g_KBMInput.ConsumeChar(ch)) + { + iRealWidth = height(); + app.DebugPrintf(std::to_string(iRealWidth).c_str()); + + if (ch == 0x08) // Backspace + { + if (m_iCursorPos > 0 && m_iCursorPos <= (int)m_editBuffer.length()) + { + m_editBuffer.erase(m_iCursorPos - 1, 1); + m_iCursorPos--; + changed = true; + + } + } + else if (ch == 0x0D) // Enter + { + if (iRealWidth + 32 < 480) { + m_editBuffer.insert(m_iCursorPos, L"\r"); + m_iCursorPos++; + changed = true; + } + + } + else if (m_iCharLimit <= 0 || (int)m_editBuffer.length() < m_iCharLimit) + { + if (m_iCursorPos >= 0 && m_iCursorPos <= (int)m_editBuffer.length()) + { + if (iRealWidth + 32 < 480) { + m_editBuffer.insert(m_iCursorPos, 1, ch); + m_iCursorPos++; + changed = true; + } + } + } + } + // Paste from clipboard + if (g_KBMInput.IsKeyPressed('V') && g_KBMInput.IsKeyDown(VK_CONTROL)) + { + wstring pasted = Screen::getClipboard(); + wstring sanitized; + sanitized.reserve(pasted.length()); + + for (wchar_t pc : pasted) + { + if (pc >= 0x20) // Keep printable characters + { + if (m_iCharLimit > 0 && (m_editBuffer.length() + sanitized.length()) >= (size_t)m_iCharLimit) + break; + sanitized += pc; + } + } + + if (!sanitized.empty()) + { + m_editBuffer.insert(m_iCursorPos, sanitized); + m_iCursorPos += (int)sanitized.length(); + changed = true; + } + } + + setLabel(display); + if (!signing) { + parent->SetLocalLabel(m_editBuffer); + } + else { + parent->SetLocalLabel(display); + } + + parent->UpdateCaretIndex(m_iCursorPos); + + bufferLen = (int)m_editBuffer.length(); + if (g_KBMInput.IsKeyPressed(VK_UP || VK_DOWN)) + { + return eDirectEdit_Continue; + } + if (m_iCursorPos > bufferLen) { + m_iCursorPos = bufferLen; + } + + // Arrow keys + if (g_KBMInput.IsKeyPressed(VK_LEFT) && m_iCursorPos > 0) + { + m_iCursorPos--; + } + if (g_KBMInput.IsKeyPressed(VK_RIGHT) && m_iCursorPos < bufferLen) + { + m_iCursorPos++; + } + if (g_KBMInput.IsKeyPressed(VK_HOME)) + { + m_iCursorPos = 0; + } + if (g_KBMInput.IsKeyPressed(VK_END)) + { + m_iCursorPos = bufferLen; + } + if (g_KBMInput.IsKeyPressed(VK_DELETE)) + { + if (m_iCursorPos >= 0 && m_iCursorPos < bufferLen) + { + m_editBuffer.erase(m_iCursorPos, 1); + changed = true; + } + } + + // Escape + /*if (g_KBMInput.IsKeyPressed(VK_ESCAPE)) + { + m_editBuffer = m_textBeforeEdit; + m_bDirectEditing = false; + m_iDirectEditCooldown = 4; + setLabel(m_editBuffer.c_str()); + return eDirectEdit_Cancelled; + }*/ + + return eDirectEdit_Continue; +} + +void UIControl_Label::cancelDirectEdit() +{ + if (m_bDirectEditing) + { + m_editBuffer = m_textBeforeEdit; + m_bDirectEditing = false; + m_iDirectEditCooldown = 4; + setLabel(m_editBuffer.c_str(), true); } } + +void UIControl_Label::confirmDirectEdit() +{ + if (m_bDirectEditing) + { + m_bDirectEditing = false; + setLabel(m_editBuffer.c_str(), true, true); + } +} + +#endif \ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_Label.h b/Minecraft.Client/Common/UI/UIControl_Label.h index 21eb35a6..0f8844b0 100644 --- a/Minecraft.Client/Common/UI/UIControl_Label.h +++ b/Minecraft.Client/Common/UI/UIControl_Label.h @@ -10,10 +10,43 @@ private: public: UIControl_Label(); +#ifdef _WINDOWS64 + bool m_bDirectEditing = false; + wstring m_textBeforeEdit; + IggyName m_funcSetCaretIndex; + wstring m_editBuffer; + int m_iCursorPos; + int m_iCharLimit; + int m_iLineLimit = 15; + int m_iDirectEditCooldown; + int m_iCaretBlinkTimer; + bool m_bhasBeenSelected = false; + bool signing = false; + int iRealWidth = 0; + + int m_cPosMin = 0; + int m_cPosMax; +#endif + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); - void init(UIString label); + void init(UIString label, int id = -1); virtual void ReInit(); void disableReinitialisation() { m_reinitEnabled = false; } + + enum EDirectEditResult + { + eDirectEdit_Continue, + eDirectEdit_Confirmed, + eDirectEdit_Cancelled, + }; + + wstring authorName; + + void beginDirectEdit(int charLimit, bool bSigning, wstring author); + void UpdateCaretIndex(int index); + EDirectEditResult tickDirectEdit(); + void cancelDirectEdit(); + void confirmDirectEdit(); }; \ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIControl_PageFlip.cpp b/Minecraft.Client/Common/UI/UIControl_PageFlip.cpp new file mode 100644 index 00000000..a7b63470 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_PageFlip.cpp @@ -0,0 +1,55 @@ +#include "stdafx.h" +#include "UI.h" +#include "UIControl_PageFlip.h" + +UIControl_PageFlip::UIControl_PageFlip() +{ +} + +bool UIControl_PageFlip::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName) +{ + UIControl::setControlType(UIControl::ePageFlip); + bool success = UIControl_Base::setupControl(scene,parent,controlName); + + return success; +} + +void UIControl_PageFlip::init(UIString label, int id) +{ + m_label = label; + m_id = id; + + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)label.c_str(); + stringVal.length = label.length(); + value[0].string16 = stringVal; + + value[1].type = IGGY_DATATYPE_number; + value[1].number = id; + IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 2 , value ); + +#ifdef __PSVITA__ + // 4J-PB - add this button to the vita touch box list + + switch(m_parentScene->GetParentLayer()->m_iLayer) + { + case eUILayer_Error: + case eUILayer_Fullscreen: + case eUILayer_Scene: + case eUILayer_HUD: + ui.TouchBoxAdd(this,m_parentScene); + break; + } +#endif +} + +void UIControl_PageFlip::ReInit() +{ + UIControl_Base::ReInit(); + + init(m_label, m_id); +} diff --git a/Minecraft.Client/Common/UI/UIControl_PageFlip.h b/Minecraft.Client/Common/UI/UIControl_PageFlip.h new file mode 100644 index 00000000..ec35b981 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIControl_PageFlip.h @@ -0,0 +1,16 @@ +#pragma once + +#include "UIControl_Base.h" + +class UIControl_PageFlip : public UIControl_Base +{ +public: + UIControl_PageFlip(); + + virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); + + void init(UIString label, int id); + //void init(const wstring &label, int id) { init(UIString::CONSTANT(label), id); } + + virtual void ReInit(); +}; \ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIController.cpp b/Minecraft.Client/Common/UI/UIController.cpp index 5f86b2df..05ade3f9 100644 --- a/Minecraft.Client/Common/UI/UIController.cpp +++ b/Minecraft.Client/Common/UI/UIController.cpp @@ -923,7 +923,7 @@ void UIController::tickInput() UIControl::eUIControlType type = ctrl->getControlType(); if (type != UIControl::eButton && type != UIControl::eTextInput && type != UIControl::eCheckBox && type != UIControl::eSlider && - type != UIControl::eButtonList && type != UIControl::eTexturePackList) + type != UIControl::eButtonList && type != UIControl::eTexturePackList && type != UIControl::ePageFlip) continue; // If the scene has an active panel (e.g. tab menus), diff --git a/Minecraft.Client/Common/UI/UIEnums.h b/Minecraft.Client/Common/UI/UIEnums.h index 45aff87d..72ebc277 100644 --- a/Minecraft.Client/Common/UI/UIEnums.h +++ b/Minecraft.Client/Common/UI/UIEnums.h @@ -98,7 +98,7 @@ enum EUIScene eUIScene_BeaconMenu, eUIScene_HorseMenu, eUIScene_FireworksMenu, - + eUIScene_BookMenu, #ifdef _XBOX // eUIScene_TransferToXboxOne, #endif diff --git a/Minecraft.Client/Common/UI/UILayer.cpp b/Minecraft.Client/Common/UI/UILayer.cpp index e1c388f5..092124aa 100644 --- a/Minecraft.Client/Common/UI/UILayer.cpp +++ b/Minecraft.Client/Common/UI/UILayer.cpp @@ -2,6 +2,8 @@ #include "UI.h" #include "UILayer.h" #include "UIScene.h" +#include "IUIScene_WritingBookMenu.h" +#include "UIScene_BookAndQuillMenu.h" UILayer::UILayer(UIGroup *parent) { @@ -266,6 +268,10 @@ bool UILayer::NavigateToScene(int iPad, EUIScene scene, void *initData) case eUIScene_HelpAndOptionsMenu: newScene = new UIScene_HelpAndOptionsMenu(iPad, initData, this); break; + // Book + case eUIScene_BookMenu: + newScene = new UIScene_BookAndQuillMenu(iPad, initData, this); + break; case eUIScene_SettingsMenu: newScene = new UIScene_SettingsMenu(iPad, initData, this); break; diff --git a/Minecraft.Client/Common/UI/UIScene.cpp b/Minecraft.Client/Common/UI/UIScene.cpp index b29a7e56..ceefcfb3 100644 --- a/Minecraft.Client/Common/UI/UIScene.cpp +++ b/Minecraft.Client/Common/UI/UIScene.cpp @@ -7,6 +7,7 @@ #include "../../LocalPlayer.h" #include "../../ItemRenderer.h" #include "../../../Minecraft.World/net.minecraft.world.item.h" +#include "UIScene_BookAndQuillMenu.h" UIScene::UIScene(int iPad, UILayer *parentLayer) { @@ -482,6 +483,17 @@ void UIScene::tick() if (result != UIControl_TextInput::eDirectEdit_Continue) onDirectEditFinished(inputs[i], result); } + //Attempt at matching input code for textinputs for labels + vector labels; + getDirectEditLabels(labels); + for (size_t i = 0; i < labels.size(); i++) + { + //app.DebugPrintf(("label; " + std::to_string(i) + "\n").c_str()); + UIControl_Label::EDirectEditResult result1 = labels[i]->tickDirectEdit(); + //app.DebugPrintf(("result; " + std::to_string(result1) + "\n").c_str()); + if (result1 != UIControl_Label::eDirectEdit_Continue) + onDirectEditLabelFinished(labels[i], result1); + } } #endif } @@ -554,7 +566,7 @@ bool UIScene::handleMouseClick(F32 x, F32 y) UIControl::eUIControlType type = ctrl->getControlType(); if (type != UIControl::eButton && type != UIControl::eTextInput && - type != UIControl::eCheckBox) + type != UIControl::eCheckBox && type != UIControl::eBook && type != UIControl::ePageFlip) continue; if (pMainPanel && ctrl->getParentPanel() != pMainPanel) diff --git a/Minecraft.Client/Common/UI/UIScene.h b/Minecraft.Client/Common/UI/UIScene.h index ca089d39..84514ff5 100644 --- a/Minecraft.Client/Common/UI/UIScene.h +++ b/Minecraft.Client/Common/UI/UIScene.h @@ -7,6 +7,7 @@ using namespace std; #include "UIEnums.h" #include "UIControl_Base.h" #include "UIControl_TextInput.h" +#include "UIControl_Label.h" class ItemRenderer; class UILayer; @@ -170,6 +171,8 @@ public: void gainFocus(); void loseFocus(); + virtual void KBMUpdate(bool bVal) {}; + virtual void updateTooltips(); virtual void updateComponents() {} virtual void handleGainFocus(bool navBack); @@ -189,7 +192,9 @@ public: // Base class handles tickDirectEdit in tick(), click-outside-to-deselect // in handleMouseClick(), and provides isDirectEditBlocking() for guards. virtual void getDirectEditInputs(vector &inputs) {} + virtual void getDirectEditLabels(vector& inputs) {} virtual void onDirectEditFinished(UIControl_TextInput *input, UIControl_TextInput::EDirectEditResult result) {} + virtual void onDirectEditLabelFinished(UIControl_Label* input, UIControl_Label::EDirectEditResult result) {} bool isDirectEditBlocking(); // Mouse click dispatch. Hit-tests C++ controls and picks the smallest-area diff --git a/Minecraft.Client/Common/UI/UIScene_BookAndQuillMenu.cpp b/Minecraft.Client/Common/UI/UIScene_BookAndQuillMenu.cpp new file mode 100644 index 00000000..acf3e92a --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_BookAndQuillMenu.cpp @@ -0,0 +1,572 @@ +#include "stdafx.h" +#include "Common\UI\UI.h" +#include "UIScene_BookAndQuillMenu.h" +#include "PlayerConnection.h" +#include "LocalPlayer.h" +#include "ClientConnection.h" +#include "..\Minecraft.Client\PlayerList.h" +#include "..\Minecraft.Client\ServerPlayer.h" +#include "..\Minecraft.Client\MultiplayerLocalPlayer.h" + +UIScene_BookAndQuillMenu::UIScene_BookAndQuillMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) +{ + iPadLocal = iPad; + // Setup all the Iggy references we need for this scene + g_KBMInput.ClearCharBuffer(); + data = static_cast(initData); + initialiseMovie(); + m_itemInstance = data->itemInstance; + + itemTag = m_itemInstance->getTag(); + if (itemTag != nullptr) { + if (itemTag->contains(L"pages")) + { + pagesTagOG = *static_cast*>(itemTag->getList(L"pages")->copy()); + } + } + else { + pagesTagOG = *new ListTag(L"pages"); + + CompoundTag* firstPageTag = new CompoundTag(L""); + firstPageTag->putString(L"text", L""); + + pagesTagOG.add(firstPageTag); + } + + //Set the book as signed in the SWF + if (m_itemInstance->id == 387) { + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS(this->getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcSign, 0, nullptr); + + signedBook = true; + } + + m_funcSetCaretIndex = registerFastName(L"SetCaretPosition"); + m_funcSetBookIsSigning = registerFastName(L"SetBookIsSigning"); + m_funcChangePage = registerFastName(L"ChangePage"); + m_funcUpdatePageVisibility = registerFastName(L"UpdatePageVisibility"); + m_funcSet = registerFastName(L"Update"); + + app.DebugPrintf(std::to_string(iRealWidth).c_str()); + + + Init(m_itemInstance); + player = data->player.get(); + + heldItem = 4; + + + m_buttonSign.init(L"Sign", eControl_Sign); + m_buttonDone.init(L"Done", eControl_Done); + m_pageText.init(L"Page 1 of ???", eControl_Page); + m_caretText.init(L"", eControl_Caret); + m_Book.init(L"", eControl_Book); + arro1.init(L"", eControl_1); + arro2.init(L"", eControl_2); + m_typeText.init(L"", eControl_Type); + ChangePage(false, true); + + + IsKBMActive(g_KBMInput.IsKBMActive()); + KBM = g_KBMInput.IsKBMActive(); + + + SetPageText(getCurrentPageText(), m_typeText); + m_typeText.m_iCursorPos = m_typeText.m_editBuffer.length(); + UpdateCaretIndex(m_typeText.m_editBuffer.length()); + m_pageText.setLabel(std::wstring(L"Page ") + L"1" + L" of " + std::to_wstring(m_totalPages)); + + + + +#ifdef _WINDOWS64 + if (signedBook == true) { + return; + } + if (!g_KBMInput.IsKBMActive()) + { + //UIKeyboardInitData kbData; + //kbData.title = L"Enter Book Text";//app.GetString(IDS_CREATE_NEW_WORLD); <- for future reference when using languages.loc + //kbData.defaultText = m_typeText.m_editBuffer.c_str(); + //kbData.maxChars = 1023; + //kbData.callback = &KeyboardCompleteCallback; + //kbData.lpParam = this; + //ui.NavigateToScene(m_iPad, eUIScene_Keyboard, &kbData, eUILayer_Fullscreen, eUIGroup_Fullscreen); + } + else if (g_KBMInput.IsKBMActive()) + { + m_typeText.beginDirectEdit(1023, false, L""); + app.DebugPrintf("starting direct edit\n"); + + } + else { + //Make it so that keyboard buffer is cleared, as to not have text come back if it shouldn't exist + g_KBMInput.ClearCharBuffer(); + } +#endif + + this->SetFocusToElement(eControl_Type); + m_typeText.m_bhasBeenSelected = true; + +} + +void UIScene_BookAndQuillMenu::SetPageText(wstring text, UIControl_Label label) { + m_typeText.setLabel(text); + m_typeText.m_editBuffer = text; + m_typeText.m_iCursorPos = m_typeText.m_editBuffer.length(); +} + + +void UIScene_BookAndQuillMenu::tick() +{ + UIScene::tick(); +} + +void UIScene_BookAndQuillMenu::KBMUpdate(bool bVal) { + if (bVal == KBM) { + return; + } + else { + KBM = bVal; + } + IsKBMActive(bVal); + + if (bVal == true) { + m_typeText.beginDirectEdit(1023, false, L""); + + this->SetFocusToElement(eControl_Type); + m_typeText.m_bhasBeenSelected = true; + UpdateCaretIndex(0); + } +} + +#ifdef _WINDOWS64 +void UIScene_BookAndQuillMenu::getDirectEditLabels(vector &labels) { + labels.push_back(&m_typeText); +} +#endif + +wstring UIScene_BookAndQuillMenu::getMoviePath() +{ + return L"BookAndQuillMenu"; +} + +void UIScene_BookAndQuillMenu::reloadMovie(bool force) +{ + // Never needs reloaded +} + +bool UIScene_BookAndQuillMenu::needsReloaded() +{ + // Never needs reloaded + return false; +} + +//Bunch of Iggy BS +void UIScene_BookAndQuillMenu::UpdateCaretIndex(int index) { + + IggyDataValue result; + IggyDataValue value[2]; + value[0].type = IGGY_DATATYPE_number; + if (!signing) { + value[0].number = m_typeText.m_iCursorPos; + } + else { + value[0].number = m_typeText.m_iCursorPos + 18; + } + value[1].type = IGGY_DATATYPE_boolean; + value[1].boolval = (m_typeText.m_iCursorPos == m_typeText.m_editBuffer.length()); + IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, m_funcSetCaretIndex, 2, value); +} + +//arrow false updates left arrow, arrow true updates right arrow +void UIScene_BookAndQuillMenu::ChangePage(bool arrow, bool updateBoth) { + IggyDataValue result; + IggyDataValue value[4]; + value[0].type = IGGY_DATATYPE_number; + value[0].number = m_currentPageIndex; + value[1].type = IGGY_DATATYPE_number; + value[1].number = m_totalPages; + value[2].type = IGGY_DATATYPE_boolean; + value[2].boolval = arrow; + value[3].type = IGGY_DATATYPE_boolean; + value[3].boolval = updateBoth; + IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, m_funcChangePage, 4, value); +} + +void UIScene_BookAndQuillMenu::IsKBMActive(bool bVal) { + + //RADEXPFUNC IggyResult RADEXPLINK IggyValueGetBooleanRS(IggyValuePath *var, IggyName sub_name, char const *sub_name_utf8, rrbool *result); + + /*IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = bVal; + IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, m_funcChangePage, 1, value);*/ + + rrbool newBool = bVal; + + rrbool out = IggyValueSetBooleanRS(m_rootPath, m_funcUpdateKBM, nullptr, newBool); +} + +void UIScene_BookAndQuillMenu::SetBookIsSigning(bool isSigning) { + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_boolean; + value[0].boolval = isSigning; + IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, m_funcSetBookIsSigning, 1, value); +} + +void UIScene_BookAndQuillMenu::SetLocalLabel(wstring m_label1) { + IggyDataValue result; + IggyDataValue value[1]; + value[0].type = IGGY_DATATYPE_string_UTF16; + IggyStringUTF16 stringVal; + + stringVal.string = (IggyUTF16*)m_label1.c_str(); + stringVal.length = m_label1.length(); + value[0].string16 = stringVal; + + IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, m_funcSetLocalLabel, 1, value); +} + +void UIScene_BookAndQuillMenu::Update() { + IggyDataValue result; + IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, m_rootPath, m_funcSet, 0, nullptr); +} + +int UIScene_BookAndQuillMenu::WarningExitBookReturned(void* pParam, int iPad, C4JStorage::EMessageResult result) +{ + UIScene_BookAndQuillMenu* pClass = static_cast(pParam); + + if (result == C4JStorage::EMessage_ResultAccept) { + //Reset the book to the previous state, should in theory do so already but it seems changes + //directly affect our itemInstance, but the changes are just ghost changes (changing item slots reverts it) + for (int i = 0; i <= pClass->pagesTagOG.size()-1; i++) { + auto t = static_cast(pClass->pagesTagOG.get(i)); + pClass->setCurrentPageText(t->getString(L"text"), i); + } + if (pClass->itemTag != nullptr) pClass->itemTag->getList(L"pages")->getList().resize(pClass->pagesTagOG.size()); + + + pClass->navigateBack(); + pClass->m_typeText.m_bhasBeenSelected = false; + return 0; + } + else { + return -1; + } +} + +void UIScene_BookAndQuillMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled) +{ + auto item = Minecraft::GetInstance()->localplayers[iPadLocal]->inventory->getSelected(); + ListTag* pagesTag = new ListTag(); + ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released); + switch(key) + { + case ACTION_MENU_CANCEL: + if(pressed) + { + if (!signing) + { + CompoundTag* itemTag = m_itemInstance->getTag(); + setCurrentPageText(m_typeText.m_editBuffer); + if (signedBook == false) { + if (!pagesTagOG.equals(m_currentPage)) { + UINT uiIDA[2]; + uiIDA[0] = IDS_CONFIRM_OK; + uiIDA[1] = IDS_CONFIRM_CANCEL; + int r = ui.RequestAlertMessage(IDS_TITLE_EXITBOOK, IDS_DESC_EXITBOOK, uiIDA, 2, m_iPad, &UIScene_BookAndQuillMenu::WarningExitBookReturned, this); + if (r == 0) + { + navigateBack(); + } + } + else { + navigateBack(); + } + } + } + else + { + SetPageText(getCurrentPageText(), m_typeText); + m_typeText.signing = false; + m_buttonSign.setLabel(L"Sign"); + m_buttonDone.setLabel(L"Done"); + m_pageText.setVisible(true); + SetBookIsSigning(false); + signing = false; + + this->SetFocusToElement(eControl_Type); + m_typeText.beginDirectEdit(1023, false, L""); + + break; + + } + if (signedBook) { + navigateBack(); + } + //m_typeText.m_bhasBeenSelected = false; + + //cachedID = eControl_Done; + //m_typeText.confirmDirectEdit(); + break; + } + break; + case ACTION_MENU_OK: + case ACTION_MENU_UP: + case ACTION_MENU_DOWN: + case ACTION_MENU_LEFT: + case ACTION_MENU_RIGHT: + sendInputToMovie(key, repeat, pressed, released); + handled = true; + break; + case ACTION_MENU_PAGEDOWN: + //If on KBM, use PGUP/PGDWN instead, as SCROLL conflicts with Q and E + if (g_KBMInput.IsKBMActive()) { + if (pressed && !repeat) + { + setCurrentPageText(m_typeText.m_editBuffer); + ScrollPageRight(); + SetPageText(getCurrentPageText(), m_typeText); + m_pageText.setLabel(L"Page " + to_wstring(m_currentPageIndex+1) + L" of " + to_wstring(m_totalPages)); + ChangePage(); + handled = true; + } + sendInputToMovie(key, repeat, pressed, released); + break; + } + break; + case ACTION_MENU_PAGEUP: + if (g_KBMInput.IsKBMActive()) { + if (pressed && !repeat) + { + setCurrentPageText(m_typeText.m_editBuffer); + ScrollPageLeft(); + SetPageText(getCurrentPageText(), m_typeText); + m_pageText.setLabel(L"Page " + to_wstring(m_currentPageIndex+1) + L" of " + to_wstring(m_totalPages)); + ChangePage(); + handled = true; + } + sendInputToMovie(key, repeat, pressed, released); + break; + } + break; + case ACTION_MENU_RIGHT_SCROLL: + //Regular keybinds + if (!g_KBMInput.IsKBMActive()) { + if (pressed && !repeat) + { + setCurrentPageText(m_typeText.m_editBuffer); + ScrollPageRight(); + SetPageText(getCurrentPageText(), m_typeText); + m_pageText.setLabel(L"Page " + to_wstring(m_currentPageIndex+1) + L" of " + to_wstring(m_totalPages)); + ChangePage(); + handled = true; + sendInputToMovie(key, repeat, pressed, released); + } + break; + } + break; + case ACTION_MENU_LEFT_SCROLL: + //Regular keybinds + if (!g_KBMInput.IsKBMActive()) { + if (pressed && !repeat) + { + setCurrentPageText(m_typeText.m_editBuffer); + ScrollPageLeft(); + SetPageText(getCurrentPageText(), m_typeText); + m_pageText.setLabel(L"Page " + to_wstring(m_currentPageIndex+1) + L" of " + to_wstring(m_totalPages)); + ChangePage(); + handled = true; + sendInputToMovie(key, repeat, pressed, released); + } + break; + } + break; + } + IUIScene_WritingBookMenu::updateTooltips(); +} + +int UIScene_BookAndQuillMenu::KeyboardCompleteCallback(LPVOID lpParam, bool bRes) +{ + if (bRes) + { + uint16_t pchText[128]; + ZeroMemory(pchText, 128 * sizeof(uint16_t)); +#ifdef _WINDOWS64 + Win64_GetKeyboardText(pchText, 128); +#else + InputManager.GetText(pchText); +#endif + UIScene_BookAndQuillMenu* pClass = static_cast(lpParam); + + if (pchText[0] != 0) + { + pClass->m_typeText.setLabel((wchar_t*)pchText); + pClass->m_typeText.m_editBuffer = (wchar_t*)pchText; + pClass->m_typeText.m_iCursorPos = wcslen((wchar_t*)pchText); + pClass->UpdateCaretIndex(0); + } + } + return 0; +} + + + +void UIScene_BookAndQuillMenu::handlePress(F64 controlId, F64 childId) +{ + //Packet + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + + //Mouse centering + S32 width, height; + m_parentLayer->getRenderDimensions(width, height); + S32 x = (static_cast(width) / m_movieWidth); + S32 y = (static_cast(height) / m_movieHeight); + HWND hwnd = GetForegroundWindow(); + WINDOWPLACEMENT wp{}; + + + switch((int)controlId) + { + case eControl_Type: +#ifdef _WINDOWS64 + if (signedBook == true) { + break; + } + + if (!InputManager.ButtonPressed(iPadLocal, ACTION_MENU_OK) && !g_KBMInput.IsKBMActive()) { + break; + } + if (!g_KBMInput.IsKBMActive()) + { + UIKeyboardInitData kbData; + kbData.title = L"Enter Book Text";//app.GetString(IDS_CREATE_NEW_WORLD); + kbData.defaultText = m_typeText.m_editBuffer.c_str(); + kbData.maxChars = 1023; + kbData.callback = &KeyboardCompleteCallback; + kbData.lpParam = this; + ui.NavigateToScene(m_iPad, eUIScene_Keyboard, &kbData, eUILayer_Fullscreen, eUIGroup_Fullscreen); + } + else if (m_typeText.hasFocus() == true) + { + //m_bIgnoreInput = false; + if (cachedID != controlId) { + m_typeText.beginDirectEdit(1023, false, L""); + app.DebugPrintf("starting direct edit\n"); + + cachedID = controlId; + } + + } + else { + //Make it so that keyboard buffer is cleared, as to not have text come back if it shouldn't exist + g_KBMInput.ClearCharBuffer(); + } +#else + InputManager.RequestKeyboard(L"Message", L"", 0, 256, &KeyboardCompleteCallback,this,C_4JInput::EKeyboardMode_Alphabet); +#endif + break; + case eControl_Book: + if (g_KBMInput.IsKBMActive()) { + //This does not work when using controller. Why? God knows... + this->SetFocusToElement(eControl_Type); + m_typeText.beginDirectEdit(1023, false, L""); + } + else { + if (signedBook == true) { + break; + } + if (!InputManager.ButtonPressed(iPadLocal, ACTION_MENU_OK) && !g_KBMInput.IsKBMActive()) { + break; + } + + UIKeyboardInitData kbData; + kbData.title = L"Enter Book Text";//app.GetString(IDS_CREATE_NEW_WORLD); + kbData.defaultText = m_typeText.m_editBuffer.c_str(); + kbData.maxChars = 1023; + kbData.callback = &KeyboardCompleteCallback; + kbData.lpParam = this; + ui.NavigateToScene(m_iPad, eUIScene_Keyboard, &kbData, eUILayer_Fullscreen, eUIGroup_Fullscreen); + } + + break; + //Left and Right Arrows + case eControl_1: + setCurrentPageText(m_typeText.m_editBuffer); + ScrollPageLeft(); + SetPageText(getCurrentPageText(), m_typeText); + m_pageText.setLabel(L"Page " + to_wstring(m_currentPageIndex + 1) + L" of " + to_wstring(m_totalPages)); + ChangePage(true, false); + break; + case eControl_2: + setCurrentPageText(m_typeText.m_editBuffer); + ScrollPageRight(); + SetPageText(getCurrentPageText(), m_typeText); + m_pageText.setLabel(L"Page " + to_wstring(m_currentPageIndex + 1) + L" of " + to_wstring(m_totalPages)); + ChangePage(false, false); + break; + case eControl_Done: + if (!signing) + { + setCurrentPageText(m_typeText.m_editBuffer); + SaveChanges(false); + navigateBack(); + } + else + { + SetPageText(getCurrentPageText(), m_typeText); + m_typeText.signing = false; + m_buttonSign.setLabel(L"Sign"); + m_buttonDone.setLabel(L"Done"); + m_pageText.setVisible(true); + SetBookIsSigning(false); + signing = false; + } + + this->SetFocusToElement(eControl_Type); + m_typeText.m_bhasBeenSelected = false; + cachedID = eControl_Done; + break; + case eControl_Sign: + S32 width, height; + m_parentLayer->getRenderDimensions(width, height); + S32 x = (static_cast(width) / m_movieWidth); + S32 y = (static_cast(height) / m_movieHeight); + HWND hwnd = GetForegroundWindow(); + WINDOWPLACEMENT wp{}; + + if (!signing) { + + setCurrentPageText(m_typeText.m_editBuffer); + //SaveChanges(false); + m_typeText.m_editBuffer = L""; + m_typeText.signing = true; + m_buttonSign.setLabel(L"Sign and Close"); + m_buttonDone.setLabel(L"Cancel"); + m_pageText.setVisible(false); + SetBookIsSigning(true); + signing = true; + } + else { + m_bookTitle = m_typeText.m_editBuffer; + if (m_bookTitle.length() != 0) { + SaveChanges(true); + navigateBack(); + } + } + m_typeText.beginDirectEdit(15, true, data->player->getDisplayName()); + + this->SetFocusToElement(eControl_Type); + m_typeText.m_bhasBeenSelected = true; + + //Center mouse position + wp.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(hwnd, &wp); + SetCursorPos(wp.rcNormalPosition.left + width / 2, wp.rcNormalPosition.top + height / 2); + cachedID = eControl_Type; + }; +} \ No newline at end of file diff --git a/Minecraft.Client/Common/UI/UIScene_BookAndQuillMenu.h b/Minecraft.Client/Common/UI/UIScene_BookAndQuillMenu.h new file mode 100644 index 00000000..b4e91787 --- /dev/null +++ b/Minecraft.Client/Common/UI/UIScene_BookAndQuillMenu.h @@ -0,0 +1,106 @@ +#pragma once +#include + +#include "Common/UI/UIScene.h" +#include "Common/UI/UIControl_Book.h" +#include "Common/UI/UIControl_PageFlip.h" +#include "Common/UI/IUIScene_AbstractContainerMenu.h" +#include "IUIScene_WritingBookMenu.h" + +class UIScene_BookAndQuillMenu : public UIScene, public IUIScene_WritingBookMenu +{ +private: + enum eControls + { + eControl_Sign, + eControl_Done, + eControl_Page, + eControl_Type, + eControl_Caret, + eControl_Book, + eControl_1, + eControl_2, + }; + + UIControl m_controlBackground; + UIControl_Book m_Book; + UIControl_PageFlip arro1, arro2; + + UIControl_Button m_buttonSign, m_buttonDone; + UIControl_Label m_pageText, m_typeText, m_caretText; + UIControl_TextInput m_test; + IggyName m_funcSetCaretIndex; + IggyName m_funcSetBookIsSigning; + IggyName m_funcChangePage; + IggyName m_funcUpdateKBM; + IggyName m_funcUpdatePageVisibility; + IggyName m_funcSet; + IggyName m_funcSetLocalLabel; + IggyName m_funcSign; + IggyName m_funcGetLabel; + UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) + UI_MAP_ELEMENT(m_buttonSign, "ButtonSign") + UI_MAP_ELEMENT(m_buttonDone, "ButtonClose") + UI_MAP_ELEMENT(m_pageText, "PageLabel") + UI_MAP_ELEMENT(m_caretText, "Caret") + UI_MAP_ELEMENT(m_Book, "Book") + UI_MAP_ELEMENT(m_typeText, "BookAndQuillLabel") + UI_MAP_ELEMENT(arro1, "BookArrowLeft") + UI_MAP_ELEMENT(arro2, "BookArrowRight") + UI_MAP_NAME(m_funcSign, L"SetBookIsSigned") + UI_MAP_NAME(m_funcGetLabel, L"gHeight") + UI_MAP_NAME(m_funcSetLocalLabel, L"setLocalLabel") + UI_MAP_NAME(m_funcUpdateKBM, L"m_OnKBM") + //UI_MAP_ELEMENT(m_test, "Text") + UI_END_MAP_ELEMENTS_AND_NAMES() + +public: + //std::shared_ptr m_itemInstance; + ListTag pagesTagOG; + CompoundTag* itemTag; + int currentPage = 1; + //int totalPages = 1; + int cachedID = -1; + int heldItem; + bool KBM; + bool wasInMessage = false; + Player* player; + std::wstring localUsername; + + WritingBookMenuParams* data; + + UIScene_BookAndQuillMenu(int iPad, void* initData, UILayer* parentLayer); + + using UIScene::reloadMovie; + virtual void reloadMovie(bool force); + virtual bool needsReloaded(); + + virtual EUIScene getSceneType() { return eUIScene_BookMenu; } + + static int KeyboardCompleteCallback(LPVOID lpParam, bool bRes); + + virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled); + + virtual void KBMUpdate(bool bVal); + + //virtual void updateTooltips(); + void UpdateCaretIndex(int index); + void ChangePage(bool arrow = true, bool updateBoth = true); + void IsKBMActive(bool bVal); + void SetBookIsSigning(bool bIsSigning); + void SetLocalLabel(wstring m_label1); + void Update(); + + static int WarningExitBookReturned(void* pParam, int iPad, C4JStorage::EMessageResult result); + + C4JStorage::EMessageResult result1; + + virtual void tick(); + + virtual void getDirectEditLabels(vector &labels); + + void UIScene_BookAndQuillMenu::SetPageText(wstring text, UIControl_Label label); +protected: + virtual wstring getMoviePath(); + virtual void handlePress(F64 controlId, F64 childId) override; +}; diff --git a/Minecraft.Client/Common/UI/UIStructs.h b/Minecraft.Client/Common/UI/UIStructs.h index 99c3d7bd..ca8e5195 100644 --- a/Minecraft.Client/Common/UI/UIStructs.h +++ b/Minecraft.Client/Common/UI/UIStructs.h @@ -91,6 +91,16 @@ typedef struct _FurnaceScreenInput bool bSplitscreen; } FurnaceScreenInput; +// Book and Quill +typedef struct _WritingBookMenuParams +{ + shared_ptr itemInstance; + shared_ptr player; + int iPad; + bool isEditable; +} +WritingBookMenuParams; + // Crafting typedef struct _CraftingPanelScreenInput { diff --git a/Minecraft.Client/LocalPlayer.cpp b/Minecraft.Client/LocalPlayer.cpp index 852b8308..33205b6e 100644 --- a/Minecraft.Client/LocalPlayer.cpp +++ b/Minecraft.Client/LocalPlayer.cpp @@ -631,6 +631,32 @@ bool LocalPlayer::openHorseInventory(shared_ptr horse, shared_ptr itemInstance, shared_ptr player) +{ + //minecraft->setScreen(new HorseInventoryScreen(inventory, container, horse)); + /*bool success = app.LoadHorseMenu(GetXboxPad(), inventory, container, horse); + if( success ) ui.PlayUISFX(eSFX_Press); + return success;*/ + int itemId = itemInstance->getItem()->id; + + if (itemId == 386) + { + ui.PlayUISFX(eSFX_Press); + app.LoadWritingBookMenu(GetXboxPad(), itemInstance, player, true); + return; + } + else if (itemId == 387) + { + ui.PlayUISFX(eSFX_Press); + app.LoadWritingBookMenu(GetXboxPad(), itemInstance, player, true); + return; + } + + + //bool success = app.LoadBookMenu(GetXboxPad(), inventory); + //return success; +} + bool LocalPlayer::startCrafting(int x, int y, int z) { bool success = app.LoadCrafting3x3Menu(GetXboxPad(), dynamic_pointer_cast( shared_from_this() ), x, y, z ); diff --git a/Minecraft.Client/LocalPlayer.h b/Minecraft.Client/LocalPlayer.h index de832c85..f34d3d36 100644 --- a/Minecraft.Client/LocalPlayer.h +++ b/Minecraft.Client/LocalPlayer.h @@ -109,6 +109,7 @@ public: virtual bool openHopper(shared_ptr container); // 4J added bool return virtual bool openHopper(shared_ptr container); // 4J added bool return virtual bool openHorseInventory(shared_ptr horse, shared_ptr container); // 4J added bool return + virtual void openItemInstanceGui(shared_ptr itemInstance, shared_ptr player); // 4J added bool return virtual bool startCrafting(int x, int y, int z); // 4J added bool return virtual bool openFireworks(int x, int y, int z); // 4J added virtual bool startEnchanting(int x, int y, int z, const wstring &name); // 4J added bool return diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index 8919f11b..85a60160 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -1528,12 +1528,15 @@ void Minecraft::run_middle() } } - for (int slot = 0; slot < 9; slot++) - { - if (g_KBMInput.IsKeyPressed('1' + slot)) + //Prevent hotbar switching in menu + if (!ui.GetMenuDisplayed(0)) { + for (int slot = 0; slot < 9; slot++) { - if (localplayers[i]->inventory) - localplayers[i]->inventory->selected = slot; + if (g_KBMInput.IsKeyPressed('1' + slot)) + { + if (localplayers[i]->inventory) + localplayers[i]->inventory->selected = slot; + } } } } @@ -2637,6 +2640,12 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) case Item::expBottle_Id: if (bUseItem) *piUse=IDS_TOOLTIPS_THROW; break; + case Item::writingBook_Id: + *piUse = IDS_TOOLTIPS_OPEN; + break; + case Item::writtenBook_Id: + *piUse = IDS_TOOLTIPS_READ; + break; } } diff --git a/Minecraft.Client/PlayerConnection.cpp b/Minecraft.Client/PlayerConnection.cpp index 7c4bb963..ebe06835 100644 --- a/Minecraft.Client/PlayerConnection.cpp +++ b/Minecraft.Client/PlayerConnection.cpp @@ -31,6 +31,7 @@ #include "../Minecraft.World/GenericStats.h" #include "../Minecraft.World/JavaMath.h" +#include "..\Minecraft.World\ListTag.h" // 4J Added #include "../Minecraft.World/net.minecraft.world.item.crafting.h" #include "Options.h" @@ -1495,131 +1496,129 @@ 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 if (player->hasPermission(eGameCommand_Effect) && player->abilities.instabuild) { ByteArrayInputStream bais(customPayloadPacket->data); DataInputStream input(&bais); - int selection = input.readInt(); + int x = input.readInt(); + int y = input.readInt(); + int z = input.readInt(); + wstring command = Packet::readUtf(&input, 256); - AbstractContainerMenu *menu = player->containerMenu; - if (dynamic_cast(menu)) + shared_ptr tileEntity = player->level->getTileEntity(x, y, z); + shared_ptr cbe = dynamic_pointer_cast(tileEntity); + if (tileEntity != nullptr && cbe != nullptr) { - static_cast(menu)->setSelectionHint(selection); + cbe->setCommand(command); + player->level->sendTileUpdated(x, y, z); + //player->sendMessage(ChatMessageComponent.forTranslation("advMode.setCommand.success", command)); } } - else if (CustomPayloadPacket::SET_ADVENTURE_COMMAND_PACKET.compare(customPayloadPacket->identifier) == 0) + else { - if (!server->isCommandBlockEnabled()) - { - app.DebugPrintf("Command blocks not enabled"); - //player->sendMessage(ChatMessageComponent.forTranslation("advMode.notEnabled")); - } - else if (player->hasPermission(eGameCommand_Effect) && player->abilities.instabuild) - { - ByteArrayInputStream bais(customPayloadPacket->data); - DataInputStream input(&bais); - int x = input.readInt(); - int y = input.readInt(); - int z = input.readInt(); - wstring command = Packet::readUtf(&input, 256); + //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(); - shared_ptr tileEntity = player->level->getTileEntity(x, y, z); - shared_ptr cbe = dynamic_pointer_cast(tileEntity); - if (tileEntity != nullptr && cbe != nullptr) - { - cbe->setCommand(command); - player->level->sendTileUpdated(x, y, z); - //player->sendMessage(ChatMessageComponent.forTranslation("advMode.setCommand.success", command)); - } + BeaconMenu *beaconMenu = static_cast(player->containerMenu); + Slot *slot = beaconMenu->getSlot(0); + if (slot->hasItem()) + { + 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 - { - //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.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index acd6e886..6b1c371c 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -1595,14 +1595,20 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, InputManager.GetJoypadStick_RX(0, false) != 0.0f || InputManager.GetJoypadStick_RY(0, false) != 0.0f; - if (controllerUsed) + if (controllerUsed) { g_KBMInput.SetKBMActive(false); - else if (g_KBMInput.HasAnyInput()) + if (ui.FindScene(eUIScene_BookMenu) != nullptr) ui.FindScene(eUIScene_BookMenu)->KBMUpdate(false); + } + else if (g_KBMInput.HasAnyInput()) { g_KBMInput.SetKBMActive(true); + if (ui.FindScene(eUIScene_BookMenu) != nullptr) ui.FindScene(eUIScene_BookMenu)->KBMUpdate(true); + } + } else { g_KBMInput.SetKBMActive(true); + if (ui.FindScene(eUIScene_BookMenu) != nullptr) ui.FindScene(eUIScene_BookMenu)->KBMUpdate(true); } if (!g_KBMInput.IsMouseGrabbed()) diff --git a/Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip1.ogg b/Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..db0722ee544438fc2c1f36912cef8ad30c237312 GIT binary patch literal 8850 zcmaiYc_5Ts)c7+DGuB2VYgxt`GWJQt*ms6u?E98AjI`Ltk|@cZCCe0L-w9Djk?gyW zvX&)^D1HyU@B4kW3?dap=?56>nEdzZ8wG)+2T-V(L+_-e@y`1re5Q@M0crYra5I_k4 zkp3*f>Lh<=B7zNL$hyFR>GSx?iqU0=;E>R@?BVlIrMQ)FSsD{QPK-@AH@f4;Z zGqMB?G9#rm4I?Sh%N)d4B7$)d9pVklM5wf2e8gw*?%_xpOl)SPmh>JQ(N#H!`R^P^ zWzED$O66`AqPj9@0VTSDiP)oD#6}cG!_O1Bq@2zGi2(38Uob9TkQ%{OMGbTV07A)# z>CH8cw+}epR&vn5>C7p>-2~tupJrU4=Dp9FNl5b~zLUOq=b1=P)k&8)5!VC&LnB(X zYfP{cIVS*sKbDIl;p0edaZ9oH;Kb+>G9U~9z^z0`sTg0@NLKw|f*Y&zn)+YeGS!*& zL>%-XV$j{Cm@-zJoR#uqA3!t07~;e`!v1w~7>hQ2K2<4tHf!OrIen&fC7Lr!v-U>P zqqs)&QkH+;+r=zY9|+}VnbT&1d`np!kIkw7LIRaH`ZI-(ao74*?6MfTK#0HeMq*|{ zEeKJRy5GyxsRSX-#v9m2I>$KwV^t@Q)y@@;EXLzuQA=a$qyA11GU!_Qn1%R{<%I9V z$>4gG5YY+t(?amUB{wd01_w5Y73JM!aVoaREX?Y_vRh&DB{*NoHLSM4Ux$+cN^tHd zCamVa4~JOpXcoVBLQfw@XbTq?<;P3(h*bBUJT84Lsiv2wMRg!lE|hj)jlHBt@gD2w zrOe10QwxvMTCBDZDH%(B;y*6X_ZUi6r$nP;%?`0bPqX}}g^T{Wlk0eE0Knio#{dK8 z|MV@64-9-pr@<~dBq2RytcD{vkEIgK>w_)FqpWv>XTZKku*au5oByBwcj;iN-~xmF z??QySSp0j@%gAKJzsm$S6!2xzIEgo{Dx}UJ^8KKQ!M2nEqk<8W+K?1(;Ec7Ate26D z^N_T)v5Ym&)XOZ@%d(CzmF7IP8$A2Jx;5-%iKhYJQWCFF5|2>Qg4{i%mXceyFrY+v zd?MpM3Eo?fOG0WT@wq3t-bgLV$Xvuf`yOA^wEojW4(eASxX3%WBMB`N`PBq&gFig)DIRPLO1w^PH1p;_<8!6arx2mnN@2@eD+X2>`-r zvD89Q$qs!&ONrQb=tT~PIP}vj$3C=RcJe#4K=#AaLL_h~w3L&uYMnnwc}|DbBNI&gQ$$ z)^A1$v%9)Ob$VkXgdrSZc9ifX!)s~}6eHkLqijLGv8eeQ-ZN)&jBtdRWNTYc?5ww~ z>}0F=<#I2_DaERCURsUT3K8omnWk2~bi&LsyUM(5wA4_I7pQM0z}hyAFypq?WN3o3 zHglfX#hLvK2922i89d8^8`}k49zBwpZND2#TBk|D)kT38ETwx{<3kpff452m5G+C2 z%HGzp%P+14L@R=4o{|Fq$aDqCqoPaTz$YlcLd;UpRgPtf1XF|K_~L^MC2zrMC$9?4K!CyzLa5vq*BT6mU@WLn&nCJtH%l4=dL?-rBTEIp*v zNTk4|gSp4rDPcCpWIjI(l^+@r@f~uV9wS_@d+S(}4Do_Q{crv?yup9QW{Q{E_M3UtDWptlM~ORU?JD|9VSgKe+Nv zL+$v|S_{i~bj&}K$JK(WJSu;J1W=WZwsakf$35wvnHJAMg2&a$#Z3PV)Z)0YhjcxQ z2RMfXsA_T45v;h#>B02CpBxUJd$Qwm59QWIQRXSfqLvD!;Hbr{yej?#a=B1&pp}kxo4N+V}^mpmJdjz2JCz}dcI#alEO^{ioD%c z9gqS~7Uu~DJbhk0e=!8Y%n1*UU~RptY9tK?Fc{zppcIHP{~0`Fa)POgvX#P_ftXb1 zS-kZzPaVOM#dPEt<7FuuZ8=7m*^RPCU#jNrl4} zIw}4LZLQ+kafgzuNJFf4X(yW_7*nGbC6%L@@?hLDdz7HZIkeqHyYT*fExUw;STN^@k79Q^v_PB_Kl_M7Zo5#iEUDWP$pKQIV39{^0}b2#KY~pe%^PYM;o$kD-~q{L}&{h^MSra zV8F*eUj7%C^dAn3{TByr)jxd6SS_#w<&XnIl|@;A6~}B}Ky~(9*h%~<0RU5nsqvj` zfH!6N0K28BXTATSOADD>ox1kDQmOFX_K9pirqb4d!FFUZO*%+Jh8fATad z|5@?#nkrsiUT$t4q!52`QFcLIKB?f*<42hf@5gJN`XEdF(u@+J1aM_9>6&g;j$VB$ z@A-ow?dV>f(Bqs-H9QSubA9=29@$9Q9LmoLz)^%N;})uz+=HJF$1ug^fF zq4yn%ldMv%e~y<)Gp!hWP?5%Uj`Ky9oB(<(xN?e7%0lmTs+% zs)D(VEl=-t5*%{Cdr4l_lIfH zw%24^TN=-I+I+Ka662C!y_=fe64h32Dc8K<(YySYYO~a8%?74*VhV~;f=o*B6bwZr+vMKc5=&M zT=?j=pexs2#$+QF#l9LHwBAmk+|a&Za!TWaG=ry(y}WIn{Ea`qkHjbpeJ;@9`<%!G z^&oTZ{mzTbl+p-+yhLLjK|nE06%};|(>|)OYo2yTcV#Wfti6rNzO4(v z1mB0porY+h6Mw70k=V9Rx%HAsJOwD6p#;vgrgaEK@53xw+Jer$c_96KE$hz5%bH;} z&Eg_5;b0Mou&_E%kn9rs`L)=|d`%XKns`m9o{3;D*&0v1oJTj`EyXlxyAcsH**()A z{?#ae&J;VZRx+WY`@=VsSm=CUq6t$b@r6*-{@Ile_k2Tz2fP;nuG#8$c45p@MzK4X zy8-Ms6J9h_5s~c|HXAJsq8lP_iJKa%X4F7-m1ItZ0gCCvlh8wm>E_EUe~x_l*Wqv( z_wjYQAk9FH}qS)p_F@m9&v-> z4;=|j)n})s`=;m9^VGfW#D7^5&8lsek>_vIqt%U!@_xOf!;{K52mq`PSqc0*&2;a} zE)0IWFy_Hm1qpI0cjGwwY$<^3Dr}Pt>H>QLzPvuB5uZ>Vk*`v4A1z+eki5r>@n2@M z7>i|nE#9t14FHAqdDdvYdTp*ovkdwp{K z0dObB276Z25CY5{4Osfz4{3H@HxI4K5o&Vvh-6vZx8S2;Y+?o&zuM6-o8}IcbBr$u z)*kH}u@OZKH!$uSGiOBHQlq_~shAZv-AT>;O8=d^lhlwadCJf-il~^u?{gB;WV+k8 zH28b&tp!8-BP7KwHbrkx^(hTR`Bn9Pra+!QZIecekGpd;r`*sMT91C8=U5&1er2T9 zH7!v}GmHXglfNJGqeAw}$1ed0Z!(~t%46;K_@%3%OQF@J&{fMnz5@-chKSzu@(#7q zFQan-rT2ci)pK23&G~XVPAjFQccE~y^!rO|2j8lSt2(wn{XoZP)SiAG?3PY+4WQp`OczQ%Dcw%HCQ# zjE}oF(;C6{LR)TIG02Dfx_Ub|kHT})vY~Xk`?O#4?4H?~m7M1?0fxAQu)8LR5E|B|6h?NYIxb(a#L0l4O6Mz6AXUTHX zk@NVNZCEDF@1HiBH4PTKx-anDk)VaLH+HQ|50Rl+M;~U-c@y5<@_p*#lbzII)Z#a_ zpDDqUkR_)W#BzIGRc~2%f7EIhH<*`HGu~^r;rmV0JVPnc_;o)uDU5Z7;%Tl!@kM_! zA3NykJK^dy0Ss^f=chsQ%ldIR!{lK>jiw=&{FB+sxAU1A(oFE94f=|4cb|y&bCR9Q zPz@+{Ig%7nZ|>cj@gxMaxa$jH)nQzcl9#4j!5BJ;5@ zPLhk3KWrSX*7h*Z_KD9A9Su)BV3`OMS>Uf$QVDiK$n0YJl`FzdjO z3Ma-AbpcsneEG(yGjg1WKywH_{twce)R*e+UV4%tw= zMZDid^#l1Sqnt-Eh}b4Kg}++Km(CmhrP!b6RjlJ8`*kIc(Sf(hO%?-v&RHBkD2pzK z3zs?S=1gzU{klwk8)D{8Lkgpn@y7z6X1vz~+Vt!QeZU3uJpnic8=sEOHXV zbCdZB)lV)u5iUj`tnpCm=%Fk2SNTO-naC?m?)w=?=_`hJ1p%T@#v;G|#oIT}hhN`X z|1I{r$hUvZED*IRUn*_O-t~??k*@nwsK%6SV6k;4GKl@wshmmG=G&+N;{yJ7y`PbmA@Z&U?g4Bo3pH6Lx58E;E) z6wgst<_!DES_8iA&VD>!%&NKUFt<6sc>HK+zq?~WE@C3?%{ZNQc_hMVxD-e<0N5hX z?|8c3o72qs$oK%?HLj{x+d2HW2n4#)x__BTxruwQrM@*o(vB~Dpdq!_^Qr$I2ca` z$Af>wLAI01O(QY$J8zRL$c&nYrl>1%|Jbv_NWe+OJ(+g`~o#?xBm4 zql?w_dfU4nL_b*F@_V7RX|<8LQ$SPHtX;xDQyC|%?`Jk)ME7Hp7U(xPe-vHC1_$%T zaAK{ZC(o*E;VCMLiJ@*gr4Qrts0SZIRKJWS%RC9*b6cle%gSO3%HFh!VJBA-ji*?) zKA>B*B?mUC=zZWojuzckwa>>>H4MH#Uk)|inNxI_lF>;Z=9J=@MRvM=-YEnCJN|w4 zgrDPg@h=rPjK(@`?x!S@k`}_K08Ybch2NBmrkG2DWLvaXY*Tkc%;l@o8zL%{gF9p+ zL`x^@DFM0LOc?dBmv4!(sClx{Zv~i_eIXeFyZ&*40K05P_KeypD4c1qrU#xP}bvcBIQ*CjXFLp^VA;u*4rj~=25N3H-_QP8$MGu z>-*aC0xo-&uFqy_F-ZNTBS&v6Ut5Z{%TvT-Ee(bDLC}Nu&nH_?*D^Q(rvX7cfMTqwX4>mthRPITioCo5pPW=+ zqx_%Yf7}L?!Lp-F!Fx1l+30;|Q_I4a>-?>Kg*^$PG8Ha~7*VwhzE6q^cUvFbJj*9( za!-Y&-3`wuzm-F4QD9FppT6d@yYn=$HOK5=)rYZw=R!bF49A7DA=H%)bn&99QdLm~ z=`s=WGNuM{XMWu`?I1oF^Z3SAY&pnoB1U(x-v}VRA%=L?3+@K@uCHG?UwH~(eAxxvPPo|~lA<}< zc`nS%ix5)R2s3>1*#?zJ89%f4Z1b76yNRGld(<5pyv-|d@<>&B2p~i2n@??%1`WSc zdfu*}%KR>+nUeosGw%%S61tN=H% zZpvNo{@~O`+zWp~-tN4VH6`(aQ8Y?ih31wVThBIVsFLkbTAAY?=Hl7tt=(dS++hFD zQ^JyEKWgt|MA+iy0?V}$D^9Oh5D1|&(e3t@g>1<+j78i8OIw|pFWkRAN4BlYf9#>N zs2(9QLN;!VmVEUNj8&+RpPNXqXF#4^CU!l(u(>NO)C_sXYb&9;S>+Q894$N~NQVLX zro-g$)+E3ft`^dCEWY!xMb4${dz5{CbT-9k;45dji#^W8ky`>zHW!@4RbrET_gi$4o5 zP0%ijpXCN+e*C-@N%y+^3O@FQNvzPTjW5t8RbQ)2hr?ah>DHH2-r-c@YHLMPPMtheA{q-LmTrOFgu1hc-8No`3Bq+2`8%Yf0g{ti*e_6fib-LwZXx~A%zGA3mvnnNPB8x!Ayj>}^eYE;J;d9>pP_z5#DOFF`9P03!(?(C;YhK*Z%~2;WWXTS9krbnh6(Be~ z87QvED2kW+L_SvQO--)h;FjF<9v7Yv%F@Xb;ixURu9pp@| zz=quS)}GgloC%wrh~@N*OBQ7@PY#pZ5~ldI9{M(It-N~i4qAYH`O`4}(}4i0mRET$ zVN^&Uc71hQ*RIhd4&T{wf6n|2zwVIF73FhsIA@0b4@|v}Ki7%w6ha`0csk3lYt*ae zG^)kW@|?5uw;co!fK94YrGO92e5J}F{yM5$NuxfUq@U`x?0$<`E-k*yUze>l(KXPg?PN?8Ey1Y7k^M>gc)*;bzi9Mb9}46)MY9yw`Dy1 z2jEcqW~P17sFqIJTMJe)^neEEN1@{DA(bFc6a2W^Xm9+c6>6jKV9v3|!tRL(xp;W} z2N?{cHN~noD8H<6I^r42iyxZ3{*T|p&J;QlX(@rjgWK2)Lq55kCz)S#i&Q6 z)s(+ x0_W-Xq literal 0 HcmV?d00001 diff --git a/Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip2.ogg b/Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..bad3e808f7e0b0d71f7d3f095913672ee2c0ba45 GIT binary patch literal 8570 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 T@DTp&iv=_S{(nCNp1l7b8hpt^ literal 0 HcmV?d00001 diff --git a/Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip3.ogg b/Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip3.ogg new file mode 100644 index 0000000000000000000000000000000000000000..34e6b0b8801844f5a57c42c2028bbe802fd05206 GIT binary patch literal 7647 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 ZdmWW0xDGt$DqGvowinvp0aa(%{{f3a5UKzG literal 0 HcmV?d00001 diff --git a/Minecraft.Client/Windows64Media/strings.h b/Minecraft.Client/Windows64Media/strings.h index 5e4fe229..8132d984 100644 --- a/Minecraft.Client/Windows64Media/strings.h +++ b/Minecraft.Client/Windows64Media/strings.h @@ -2416,4 +2416,13 @@ #define IDS_DESC_LARGE_FERN 2410 #define IDS_DESC_ROSE_BUSH 2411 #define IDS_DESC_PEONY 2412 -#define IDS_ENDERMITE 2413 \ No newline at end of file +#define IDS_ENDERMITE 2413 +#define IDS_ITEM_WRITTENBOOK 2414 +#define IDS_DESC_WRITTENBOOK 2415 +#define IDS_ITEM_WRITINGBOOK 2416 +#define IDS_DESC_WRITINGBOOK 2417 +#define IDS_TOOLTIPS_NEXTPAGE 2418 +#define IDS_TOOLTIPS_BACKPAGE 2419 +#define IDS_TOOLTIPS_ADDPAGE 2420 +#define IDS_TITLE_EXITBOOK 2421 +#define IDS_DESC_EXITBOOK 2422 \ No newline at end of file diff --git a/Minecraft.Client/cmake/sources/Common.cmake b/Minecraft.Client/cmake/sources/Common.cmake index 853e3089..5f78d3a2 100644 --- a/Minecraft.Client/cmake/sources/Common.cmake +++ b/Minecraft.Client/cmake/sources/Common.cmake @@ -315,6 +315,10 @@ set(_MINECRAFT_CLIENT_COMMON_COMMON_UI_ALL_PLATFORMS "${BASE_DIR}/UI/IUIScene_PauseMenu.h" "${BASE_DIR}/UI/IUIScene_TradingMenu.cpp" "${BASE_DIR}/UI/IUIScene_TradingMenu.h" + + "${BASE_DIR}/UI/IUIScene_WritingBookMenu.cpp" + "${BASE_DIR}/UI/IUIScene_WritingBookMenu.h" + "${BASE_DIR}/UI/UIEnums.h" "${BASE_DIR}/UI/UIStructs.h" ) diff --git a/Minecraft.Client/cmake/sources/Windows.cmake b/Minecraft.Client/cmake/sources/Windows.cmake index 7fc07abd..bb945280 100644 --- a/Minecraft.Client/cmake/sources/Windows.cmake +++ b/Minecraft.Client/cmake/sources/Windows.cmake @@ -70,6 +70,8 @@ set(_MINECRAFT_CLIENT_WINDOWS_COMMON_UI_CONTROLS "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_BitmapIcon.h" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_Button.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_Button.h" + "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_Book.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_Book.h" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_ButtonList.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_ButtonList.h" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_CheckBox.cpp" @@ -94,6 +96,8 @@ set(_MINECRAFT_CLIENT_WINDOWS_COMMON_UI_CONTROLS "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_MinecraftHorse.h" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_MinecraftPlayer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_MinecraftPlayer.h" + "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_PageFlip.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_PageFlip.h" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_PlayerList.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_PlayerList.h" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIControl_PlayerSkinPreview.cpp" @@ -237,6 +241,8 @@ set(_MINECRAFT_CLIENT_WINDOWS_COMMON_UI_SCENES_INGAME_MENU_SCREENS_CONTAINERS "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_AnvilMenu.h" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_BeaconMenu.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_BeaconMenu.h" + "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_BookAndQuillMenu.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_BookAndQuillMenu.h" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_BrewingStandMenu.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_BrewingStandMenu.h" "${CMAKE_CURRENT_SOURCE_DIR}/Common/UI/UIScene_ContainerMenu.cpp" diff --git a/Minecraft.World/Item.cpp b/Minecraft.World/Item.cpp index 7e115adc..c4713b5d 100644 --- a/Minecraft.World/Item.cpp +++ b/Minecraft.World/Item.cpp @@ -12,6 +12,8 @@ #include "net.minecraft.world.effect.h" #include "net.minecraft.stats.h" #include "MapItem.h" +#include "WrittenBook.h" +#include "WritingBookItem.h" #include "Item.h" #include "HangingEntityItem.h" #include "HtmlString.h" @@ -215,8 +217,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; @@ -482,6 +484,8 @@ void Item::staticCtor() // 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(IDS_ITEM_WRITINGBOOK)->setUseDescriptionId(IDS_DESC_WRITINGBOOK)->setMaxStackSize(1); + Item::writtenBook = (new WrittenBookItem(131))->setIconName(L"writtenBook")->setDescriptionId(IDS_ITEM_WRITTENBOOK)->setUseDescriptionId(IDS_DESC_WRITTENBOOK)->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 7581117b..3d00c925 100644 --- a/Minecraft.World/Item.h +++ b/Minecraft.World/Item.h @@ -383,8 +383,8 @@ public: static Item *frame; // TU14 - //static Item *writingBook; - //static Item *writtenBook; + static Item *writingBook; + static Item *writtenBook; static Item *emerald; @@ -606,8 +606,8 @@ public: static const int itemFrame_Id = 389; // TU14 - //static const int writingBook_Id = 386; - //static const int writtenBook_Id = 387; + static const int writingBook_Id = 386; + static const int writtenBook_Id = 387; static const int emerald_Id = 388; diff --git a/Minecraft.World/ListTag.h b/Minecraft.World/ListTag.h index f6e1c6a0..f79a28fb 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/Player.cpp b/Minecraft.World/Player.cpp index 2b40b1ea..c7099dbc 100644 --- a/Minecraft.World/Player.cpp +++ b/Minecraft.World/Player.cpp @@ -1518,8 +1518,9 @@ bool Player::openTrading(shared_ptr traderTarget, const wstring &name) * * @param itemInstance */ -void Player::openItemInstanceGui(shared_ptr itemInstance) +void Player::openItemInstanceGui(shared_ptr itemInstance, shared_ptr player) { + return; } bool Player::interact(shared_ptr entity) diff --git a/Minecraft.World/Player.h b/Minecraft.World/Player.h index 2e223a1e..d8854fa4 100644 --- a/Minecraft.World/Player.h +++ b/Minecraft.World/Player.h @@ -252,7 +252,7 @@ public: virtual bool openBrewingStand(shared_ptr brewingStand); // 4J - added bool return virtual bool openBeacon(shared_ptr beacon); virtual bool openTrading(shared_ptr traderTarget, const wstring &name); // 4J - added bool return - virtual void openItemInstanceGui(shared_ptr itemInstance); + virtual void openItemInstanceGui(shared_ptr itemInstance, shared_ptr player); virtual bool interact(shared_ptr entity); virtual shared_ptr getSelectedItem(); void removeSelectedItem(); diff --git a/Minecraft.World/Recipes.cpp b/Minecraft.World/Recipes.cpp index 6d94c5e3..514b0b47 100644 --- a/Minecraft.World/Recipes.cpp +++ b/Minecraft.World/Recipes.cpp @@ -1111,6 +1111,13 @@ Recipes::Recipes() Item::leather, L'D'); + addShapelessRecipy(new ItemInstance(Item::writingBook, 1), + L"iiig", + Item::book, + Item::feather, + ItemInstance(Item::dye_powder, 1, DyePowderItem::BLACK), + L'D'); + //addShapelessRecipy(new ItemInstance(Item.writingBook, 1), // // Item.book, new ItemInstance(Item.dye_powder, 1, DyePowderItem.BLACK), Item.feather); diff --git a/Minecraft.World/SoundTypes.h b/Minecraft.World/SoundTypes.h index 955919e5..c577eb83 100644 --- a/Minecraft.World/SoundTypes.h +++ b/Minecraft.World/SoundTypes.h @@ -232,6 +232,9 @@ enum ESoundEffect eSFX_Focus, eSFX_Press, eSFX_Scroll, + eSFX_BookTurn1, + eSFX_BookTurn2, + eSFX_BookTurn3, eSFX_MAX }; diff --git a/Minecraft.World/WritingBookItem.cpp b/Minecraft.World/WritingBookItem.cpp new file mode 100644 index 00000000..bafb5bfa --- /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, player); + + 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 00000000..281bddf8 --- /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/WrittenBook.h b/Minecraft.World/WrittenBook.h new file mode 100644 index 00000000..147d48b1 --- /dev/null +++ b/Minecraft.World/WrittenBook.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Item.h" + +class WrittenBookItem : public Item +{ +public: + + wstring authorName = L"Unknown"; + + 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); + + 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 00000000..7545ebf0 --- /dev/null +++ b/Minecraft.World/WrittenBookItem.cpp @@ -0,0 +1,48 @@ +#include "stdafx.h" +#include "HtmlString.h" +#include "WrittenBook.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, player); + + 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/cmake/sources/Common.cmake b/Minecraft.World/cmake/sources/Common.cmake index ece0ab26..01bcffb8 100644 --- a/Minecraft.World/cmake/sources/Common.cmake +++ b/Minecraft.World/cmake/sources/Common.cmake @@ -1988,6 +1988,11 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_LEVEL_TILE "${CMAKE_CURRENT_SOURCE_DIR}/DoublePlantFeature.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MutatedBiome.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/WritingBookItem.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/WritingBookItem.h" + "${CMAKE_CURRENT_SOURCE_DIR}/WrittenBookItem.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/WrittenBook.h" + ) source_group("net/minecraft/world/level/tile" FILES ${_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_LEVEL_TILE})