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: 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 70c6ec67..4fa07d73 100644 Binary files a/Minecraft.Client/Common/Media/MediaWindows64.arc and b/Minecraft.Client/Common/Media/MediaWindows64.arc differ 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 00000000..db0722ee Binary files /dev/null and b/Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip1.ogg differ 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 00000000..bad3e808 Binary files /dev/null and b/Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip2.ogg differ 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 00000000..34e6b0b8 Binary files /dev/null and b/Minecraft.Client/Windows64Media/Sound/Minecraft/UI/open_flip3.ogg differ 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})