aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp
diff options
context:
space:
mode:
authordaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
committerdaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
commitb691c43c44ff180d10e7d4a9afc83b98551ff586 (patch)
tree3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp
parentdef8cb415354ac390b7e89052a50605285f1aca9 (diff)
Initial commit
Diffstat (limited to 'Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp')
-rw-r--r--Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp387
1 files changed, 387 insertions, 0 deletions
diff --git a/Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp
new file mode 100644
index 00000000..658bcdfb
--- /dev/null
+++ b/Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp
@@ -0,0 +1,387 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.item.trading.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h"
+#include "..\..\..\Minecraft.World\net.minecraft.network.packet.h"
+#include "..\..\Minecraft.h"
+#include "..\..\MultiPlayerLocalPlayer.h"
+#include "..\..\ClientConnection.h"
+#include "IUIScene_TradingMenu.h"
+
+IUIScene_TradingMenu::IUIScene_TradingMenu()
+{
+ m_validOffersCount = 0;
+ m_selectedSlot = 0;
+ m_offersStartIndex = 0;
+ m_menu = NULL;
+ m_bHasUpdatedOnce = false;
+}
+
+shared_ptr<Merchant> IUIScene_TradingMenu::getMerchant()
+{
+ return m_merchant;
+}
+
+bool IUIScene_TradingMenu::handleKeyDown(int iPad, int iAction, bool bRepeat)
+{
+ bool handled = false;
+ //MerchantRecipeList *offers = m_merchant->getOffers(Minecraft::GetInstance()->localplayers[getPad()]);
+
+ bool changed = false;
+
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+
+ if( pMinecraft->localgameModes[getPad()] != NULL )
+ {
+ Tutorial *tutorial = pMinecraft->localgameModes[getPad()]->getTutorial();
+ if(tutorial != NULL)
+ {
+ tutorial->handleUIInput(iAction);
+ if(ui.IsTutorialVisible(getPad()) && !tutorial->isInputAllowed(iAction))
+ {
+ return S_OK;
+ }
+ }
+ }
+
+
+ switch(iAction)
+ {
+ case ACTION_MENU_B:
+ ui.ShowTooltip( iPad, eToolTipButtonX, false );
+ ui.ShowTooltip( iPad, eToolTipButtonB, false );
+ ui.ShowTooltip( iPad, eToolTipButtonA, false );
+ ui.ShowTooltip( iPad, eToolTipButtonRB, false );
+ // kill the crafting xui
+ //ui.PlayUISFX(eSFX_Back);
+ ui.CloseUIScenes(iPad);
+
+ handled = true;
+ break;
+ case ACTION_MENU_A:
+#ifdef __ORBIS__
+ case ACTION_MENU_TOUCHPAD_PRESS:
+#endif
+ if(!m_activeOffers.empty())
+ {
+ int selectedShopItem = (m_selectedSlot + m_offersStartIndex);
+ if( selectedShopItem < m_activeOffers.size() )
+ {
+ MerchantRecipe *activeRecipe = m_activeOffers.at(selectedShopItem).first;
+ if(!activeRecipe->isDeprecated())
+ {
+ // Do we have the ingredients?
+ shared_ptr<ItemInstance> buyAItem = activeRecipe->getBuyAItem();
+ shared_ptr<ItemInstance> buyBItem = activeRecipe->getBuyBItem();
+ shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[getPad()];
+ int buyAMatches = player->inventory->countMatches(buyAItem);
+ int buyBMatches = player->inventory->countMatches(buyBItem);
+ if( (buyAItem != NULL && buyAMatches >= buyAItem->count) && (buyBItem == NULL || buyBMatches >= buyBItem->count) )
+ {
+ m_merchant->notifyTrade(activeRecipe);
+
+ // Remove the items we are purchasing with
+ player->inventory->removeResources(buyAItem);
+ player->inventory->removeResources(buyBItem);
+
+ // Add the item we have purchased
+ shared_ptr<ItemInstance> result = activeRecipe->getSellItem()->copy();
+ if(!player->inventory->add( result ) )
+ {
+ player->drop(result);
+ }
+
+ // Send a packet to the server
+ int actualShopItem = m_activeOffers.at(selectedShopItem).second;
+ player->connection->send( shared_ptr<TradeItemPacket>( new TradeItemPacket(m_menu->containerId, actualShopItem) ) );
+
+ updateDisplay();
+ }
+ }
+ }
+ }
+ handled = true;
+ break;
+ case ACTION_MENU_LEFT:
+ handled = true;
+ if(m_selectedSlot == 0)
+ {
+ if(m_offersStartIndex > 0)
+ {
+ --m_offersStartIndex;
+ changed = true;
+ }
+ }
+ else
+ {
+ --m_selectedSlot;
+ changed = true;
+ moveSelector(false);
+ }
+ break;
+ case ACTION_MENU_RIGHT:
+ handled = true;
+ if(m_selectedSlot == (DISPLAY_TRADES_COUNT - 1))
+ {
+ if((m_offersStartIndex + DISPLAY_TRADES_COUNT) < m_activeOffers.size())
+ {
+ ++m_offersStartIndex;
+ changed = true;
+ }
+ }
+ else
+ {
+ ++m_selectedSlot;
+ changed = true;
+ moveSelector(true);
+ }
+ break;
+ }
+ if (changed)
+ {
+ updateDisplay();
+
+ int selectedShopItem = (m_selectedSlot + m_offersStartIndex);
+ if( selectedShopItem < m_activeOffers.size() )
+ {
+ int actualShopItem = m_activeOffers.at(selectedShopItem).second;
+ m_menu->setSelectionHint(actualShopItem);
+
+ ByteArrayOutputStream rawOutput;
+ DataOutputStream output(&rawOutput);
+ output.writeInt(actualShopItem);
+ Minecraft::GetInstance()->getConnection(getPad())->send(shared_ptr<CustomPayloadPacket>( new CustomPayloadPacket(CustomPayloadPacket::TRADER_SELECTION_PACKET, rawOutput.toByteArray())));
+ }
+ }
+ return handled;
+}
+
+void IUIScene_TradingMenu::handleTick()
+{
+ int offerCount = 0;
+ MerchantRecipeList *offers = m_merchant->getOffers(Minecraft::GetInstance()->localplayers[getPad()]);
+ if (offers != NULL)
+ {
+ offerCount = offers->size();
+
+ if(!m_bHasUpdatedOnce)
+ {
+ updateDisplay();
+ }
+ }
+
+ showScrollRightArrow( (m_offersStartIndex + DISPLAY_TRADES_COUNT) < m_activeOffers.size());
+ showScrollLeftArrow(m_offersStartIndex > 0);
+}
+
+void IUIScene_TradingMenu::updateDisplay()
+{
+ int iA = -1;
+
+ MerchantRecipeList *unfilteredOffers = m_merchant->getOffers(Minecraft::GetInstance()->localplayers[getPad()]);
+ if (unfilteredOffers != NULL)
+ {
+ m_activeOffers.clear();
+ int unfilteredIndex = 0;
+ int firstValidTrade = INT_MAX;
+ for(AUTO_VAR(it, unfilteredOffers->begin()); it != unfilteredOffers->end(); ++it)
+ {
+ MerchantRecipe *recipe = *it;
+ if(!recipe->isDeprecated())
+ {
+ m_activeOffers.push_back( pair<MerchantRecipe *,int>(recipe,unfilteredIndex));
+ firstValidTrade = min(firstValidTrade,unfilteredIndex);
+ }
+ ++unfilteredIndex;
+ }
+
+ if(!m_bHasUpdatedOnce)
+ {
+ if(firstValidTrade != 0 && firstValidTrade < unfilteredOffers->size())
+ {
+ m_menu->setSelectionHint(firstValidTrade);
+
+ ByteArrayOutputStream rawOutput;
+ DataOutputStream output(&rawOutput);
+ output.writeInt(firstValidTrade);
+ Minecraft::GetInstance()->getConnection(getPad())->send(shared_ptr<CustomPayloadPacket>( new CustomPayloadPacket(CustomPayloadPacket::TRADER_SELECTION_PACKET, rawOutput.toByteArray())));
+ }
+ }
+
+ if( (m_offersStartIndex + DISPLAY_TRADES_COUNT) > m_activeOffers.size())
+ {
+ m_offersStartIndex = m_activeOffers.size() - DISPLAY_TRADES_COUNT;
+ if(m_offersStartIndex < 0) m_offersStartIndex = 0;
+ }
+
+ for(unsigned int i = 0; i < DISPLAY_TRADES_COUNT; ++i)
+ {
+ int offerIndex = i + m_offersStartIndex;
+ bool showRedBox = false;
+ if(offerIndex < m_activeOffers.size())
+ {
+ showRedBox = !canMake(m_activeOffers.at(offerIndex).first);
+ setTradeItem(i, m_activeOffers.at(offerIndex).first->getSellItem() );
+ }
+ else
+ {
+ setTradeItem(i, nullptr);
+ }
+ setTradeRedBox( i, showRedBox);
+ }
+
+ int selectedShopItem = (m_selectedSlot + m_offersStartIndex);
+ if( selectedShopItem < m_activeOffers.size() )
+ {
+ MerchantRecipe *activeRecipe = m_activeOffers.at(selectedShopItem).first;
+
+ wstring wsTemp;
+
+ // 4J-PB - need to get the villager type here
+ wsTemp = app.GetString(IDS_VILLAGER_OFFERS_ITEM);
+ wsTemp = replaceAll(wsTemp,L"{*VILLAGER_TYPE*}",app.GetString(m_merchant->getDisplayName()));
+ int iPos=wsTemp.find(L"%s");
+ wsTemp.replace(iPos,2,activeRecipe->getSellItem()->getHoverName());
+
+ setTitle(wsTemp.c_str());
+
+ vector<wstring> unformattedStrings;
+ wstring offerDescription = GetItemDescription(activeRecipe->getSellItem(), unformattedStrings);
+ setOfferDescription(offerDescription, unformattedStrings);
+
+ shared_ptr<ItemInstance> buyAItem = activeRecipe->getBuyAItem();
+ shared_ptr<ItemInstance> buyBItem = activeRecipe->getBuyBItem();
+
+ setRequest1Item(buyAItem);
+ setRequest2Item(buyBItem);
+
+ if(buyAItem != NULL) setRequest1Name(buyAItem->getHoverName());
+ else setRequest1Name(L"");
+
+ if(buyBItem != NULL) setRequest2Name(buyBItem->getHoverName());
+ else setRequest2Name(L"");
+
+ bool canMake = true;
+
+ shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[getPad()];
+ int buyAMatches = player->inventory->countMatches(buyAItem);
+ if(buyAMatches > 0)
+ {
+ setRequest1RedBox(buyAMatches < buyAItem->count);
+ canMake = buyAMatches > buyAItem->count;
+ }
+ else
+ {
+ setRequest1RedBox(true);
+ canMake = false;
+ }
+
+ int buyBMatches = player->inventory->countMatches(buyBItem);
+ if(buyBMatches > 0)
+ {
+ setRequest2RedBox(buyBMatches < buyBItem->count);
+ canMake = canMake && buyBMatches > buyBItem->count;
+ }
+ else
+ {
+ if(buyBItem!=NULL)
+ {
+ setRequest2RedBox(true);
+ canMake = false;
+ }
+ else
+ {
+ setRequest2RedBox(buyBItem != NULL);
+ canMake = canMake && buyBItem == NULL;
+ }
+ }
+
+ if(canMake) iA = IDS_TOOLTIPS_TRADE;
+ }
+ else
+ {
+ setTitle(app.GetString(m_merchant->getDisplayName()));
+ setRequest1Name(L"");
+ setRequest2Name(L"");
+ setRequest1RedBox(false);
+ setRequest2RedBox(false);
+ setRequest1Item(nullptr);
+ setRequest2Item(nullptr);
+ }
+
+ m_bHasUpdatedOnce = true;
+ }
+
+ ui.SetTooltips(getPad(), iA, IDS_TOOLTIPS_EXIT);
+}
+
+bool IUIScene_TradingMenu::canMake(MerchantRecipe *recipe)
+{
+ bool canMake = false;
+ if (recipe != NULL)
+ {
+ if(recipe->isDeprecated()) return false;
+
+ shared_ptr<ItemInstance> buyAItem = recipe->getBuyAItem();
+ shared_ptr<ItemInstance> buyBItem = recipe->getBuyBItem();
+
+ shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[getPad()];
+ int buyAMatches = player->inventory->countMatches(buyAItem);
+ if(buyAMatches > 0)
+ {
+ canMake = buyAMatches >= buyAItem->count;
+ }
+ else
+ {
+ canMake = buyAItem == NULL;
+ }
+
+ int buyBMatches = player->inventory->countMatches(buyBItem);
+ if(buyBMatches > 0)
+ {
+ canMake = canMake && buyBMatches >= buyBItem->count;
+ }
+ else
+ {
+ canMake = canMake && buyBItem == NULL;
+ }
+ }
+ return canMake;
+}
+
+
+void IUIScene_TradingMenu::setRequest1Item(shared_ptr<ItemInstance> item)
+{
+}
+
+void IUIScene_TradingMenu::setRequest2Item(shared_ptr<ItemInstance> item)
+{
+}
+
+void IUIScene_TradingMenu::setTradeItem(int index, shared_ptr<ItemInstance> item)
+{
+}
+
+wstring IUIScene_TradingMenu::GetItemDescription(shared_ptr<ItemInstance> item, vector<wstring> &unformattedStrings)
+{
+ if(item == NULL) return L"";
+
+ wstring desc = L"";
+ vector<wstring> *strings = item->getHoverTextOnly(nullptr, false, unformattedStrings);
+ bool firstLine = true;
+ for(AUTO_VAR(it, strings->begin()); it != strings->end(); ++it)
+ {
+ wstring thisString = *it;
+ if(!firstLine)
+ {
+ desc.append( L"<br />" );
+ }
+ else
+ {
+ firstLine = false;
+ }
+ desc.append( thisString );
+ }
+ strings->clear();
+ delete strings;
+ return desc;
+}