fix: clients crashing on enchantment attempt, disabled quick equip until further notice, updated enchantingmenu swfs because lapis slot was missing?

This commit is contained in:
SevenToaster509 2026-04-16 20:47:14 +01:00
parent 5dd8d982bb
commit add784b259
12 changed files with 137 additions and 64 deletions

View file

@ -3997,6 +3997,36 @@ void ClientConnection::handleCustomPayload(shared_ptr<CustomPayloadPacket> custo
trader->overrideOffers(recipeList); trader->overrideOffers(recipeList);
} }
} }
else if (CustomPayloadPacket::ENCHANTMENT_LIST_PACKET.compare(customPayloadPacket->identifier) == 0) {
ByteArrayInputStream bais(customPayloadPacket->data);
DataInputStream input(&bais);
bool done = false;
int l = 0;
bool firstInGroup = true;
EnchantmentEntry temp;
//int firstAmount = input.readInt();
while (!done) {
int a = input.readInt();
if (a == -1) {
minecraft->localplayers[m_userIndex]->enchantmentEntries[l] = temp;
l++;
firstInGroup = true;
}
else if (a == -2) {
done = true;
}
else {
if (firstInGroup) {
temp.id = a;
temp.level = input.readInt();
firstInGroup = false;
}
else {
input.readInt();
}
}
}
}
} }
Connection *ClientConnection::getConnection() Connection *ClientConnection::getConnection()

View file

@ -14,7 +14,9 @@
#include "../../PlayerList.h" #include "../../PlayerList.h"
#include "../../Minecraft.h" #include "../../Minecraft.h"
#include "../../Options.h" #include "../../Options.h"
#include "../../Minecraft.World/Level.h"
#include "../../MultiplayerLevel.h"
#include "../../../Minecraft.World/Enchantment.h"
#ifdef __ORBIS__ #ifdef __ORBIS__
#include <pad.h> #include <pad.h>
#endif #endif
@ -270,45 +272,45 @@ void IUIScene_AbstractContainerMenu::UpdateTooltips()
} }
void IUIScene_AbstractContainerMenu::handleEnchantButton(int slot, int iPad) { void IUIScene_AbstractContainerMenu::handleEnchantButton(int slot, int iPad) {
UIScene* t = ui.FindScene(eUIScene_EnchantingMenu); EnchantmentMenu* menu = new EnchantmentMenu(Minecraft::GetInstance()->player->inventory, dynamic_cast<Level*>(Minecraft::GetInstance()->level), 0, 0, 0);
MinecraftServer* aMinecraft = MinecraftServer::getInstance(); if (0 == 0) { //uhh don't worry that is temporary
EnchantmentMenu* menu = dynamic_cast<EnchantmentMenu*>(aMinecraft->getPlayers()->players[iPad]->containerMenu); int lapisCost = slot + 1; // slot 0 = 1 lapis, slot 1 = 2, slot 2 = 3
if (menu->en == false && menu->cachedEnchantments[slot] != nullptr) { Minecraft* pMinecraft = Minecraft::GetInstance();
EnchantmentInstance* a = menu->cachedEnchantments[slot]->at(0); auto player = pMinecraft->player;
if (a != nullptr) { EnchantmentMenu* menu = dynamic_cast<EnchantmentMenu*>(player->containerMenu);
int lapisCost = slot + 1; // slot 0 = 1 lapis, slot 1 = 2, slot 2 = 3 HtmlString title = HtmlString(
wstring(app.GetString(Enchantment::enchantments[player->enchantmentEntries[slot].id]->getDescriptionId())) +
L" " +
Enchantment::enchantments[player->enchantmentEntries[slot].id]->getLevelString(player->enchantmentEntries[slot].level) +
L"...?",
eHTMLColor_White
);
HtmlString title = HtmlString( bool costEnough = Minecraft::GetInstance()->player->experienceLevel >= menu->costs[slot];
wstring(app.GetString(a->enchantment->enchantments[a->enchantment->id]->getDescriptionId())) + bool enough = menu->getLapisCount() >= lapisCost;
L" " + eMinecraftColour col = enough ? eHTMLColor_7 : eHTMLColor_c;
a->enchantment->enchantments[a->enchantment->id]->getLevelString(a->level) + eMinecraftColour colCost = costEnough ? eHTMLColor_7 : eHTMLColor_c;
L"...?",
eHTMLColor_White
);
bool costEnough = aMinecraft->getPlayers()->players[iPad]->experienceLevel >= menu->costs[slot]; std::wstring message = costEnough
bool enough = menu->getLapisCount() >= lapisCost; ? std::to_wstring(slot + 1) + (slot == 0 ? L" Enchantment Level" : L" Enchantment Levels")
eMinecraftColour col = enough ? eHTMLColor_7 : eHTMLColor_c; : L"Level Requirement: " + std::to_wstring(menu->costs[slot]);
eMinecraftColour colCost = costEnough ? eHTMLColor_7 : eHTMLColor_c;
std::wstring message = costEnough vector<HtmlString>* lines = new vector<HtmlString>();
? std::to_wstring(slot + 1) + (slot == 0 ? L" Enchantment Level" : L" Enchantment Levels") lines->push_back(title);
: L"Level Requirement: " + std::to_wstring(menu->costs[slot]);
vector<HtmlString>* lines = new vector<HtmlString>(); if (!Minecraft::GetInstance()->player->abilities.instabuild) {
lines->push_back(title); lines->push_back(HtmlString(L"")); // title1 blank line
if (!aMinecraft->getPlayers()->players[iPad]->abilities.instabuild) { if (costEnough) {
lines->push_back(HtmlString(L"")); // title1 blank line lines->push_back(HtmlString(std::to_wstring(lapisCost) + L" Lapis Lazuli", col));
if (costEnough) {
lines->push_back(HtmlString(std::to_wstring(lapisCost) + L" Lapis Lazuli", col));
}
lines->push_back(HtmlString(message, colCost));
} }
SetPointerText(lines, false); lines->push_back(HtmlString(message, colCost));
} }
SetPointerText(lines, false);
return;
} }
}; };
void IUIScene_AbstractContainerMenu::onMouseTick() void IUIScene_AbstractContainerMenu::onMouseTick()
{ {

View file

@ -143,10 +143,9 @@ void IUIScene_EnchantingMenu::handleOtherClicked(int iPad, ESceneSection eSectio
break; break;
}; };
Minecraft *pMinecraft = Minecraft::GetInstance(); Minecraft *pMinecraft = Minecraft::GetInstance();
MinecraftServer *aMinecraft = MinecraftServer::getInstance(); if (index >= 0 && m_menu->clickMenuButton(dynamic_pointer_cast<Player>(pMinecraft->localplayers[iPad]), index))
if (index >= 0 && dynamic_cast<EnchantmentMenu*>(aMinecraft->getPlayers()->players[iPad]->containerMenu)->clickMenuButton(dynamic_pointer_cast<Player>(aMinecraft->getPlayers()->players[iPad]), index))
{ {
pMinecraft->localgameModes[iPad]->handleInventoryButtonClick(dynamic_cast<EnchantmentMenu*>(aMinecraft->getPlayers()->players[iPad]->containerMenu)->containerId, index); pMinecraft->localgameModes[iPad]->handleInventoryButtonClick(m_menu->containerId, index);
} }
} }

View file

@ -130,33 +130,33 @@ ArmorItem::ArmorItem(int id, const ArmorMaterial *armorType, int icon, int slot)
} }
shared_ptr<ItemInstance> ArmorItem::use(shared_ptr<ItemInstance> instance, Level* level, shared_ptr<Player> player) { shared_ptr<ItemInstance> ArmorItem::use(shared_ptr<ItemInstance> instance, Level* level, shared_ptr<Player> player) {
int slot = Mob::getEquipmentSlotForItem(instance) - 1; //int slot = Mob::getEquipmentSlotForItem(instance) - 1;
// If player is in survival mode (not creative) //// If player is in survival mode (not creative)
if (!player->abilities.instabuild) { // //if (!player->abilities.instabuild) { //
// Equip the armor to the appropriate slot // // Equip the armor to the appropriate slot
ItemInstance copy = *instance->copy_not_shared(); // ItemInstance copy = *instance->copy_not_shared();
if (player->inventory->armor[slot] == nullptr) { // if (player->inventory->armor[slot] == nullptr) {
player->inventory->armor[slot] = make_shared<ItemInstance>(copy); // player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
player->inventory->removeItemNoUpdate(player->inventory->selected); // player->inventory->removeItemNoUpdate(player->inventory->selected);
// Remove the item from hand (set count to 0) // // Remove the item from hand (set count to 0)
instance->count = 0; // instance->count = 0;
} // }
else { // else {
player->inventory->setItem(player->inventory->selected, player->inventory->armor[slot]); // player->inventory->setItem(player->inventory->selected, player->inventory->armor[slot]);
player->inventory->armor[slot] = make_shared<ItemInstance>(copy); // player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
} // }
} //}
else { //else {
ItemInstance copy = *instance->copy_not_shared(); // ItemInstance copy = *instance->copy_not_shared();
if (player->inventory->armor[slot] == nullptr) { // if (player->inventory->armor[slot] == nullptr) {
player->inventory->armor[slot] = make_shared<ItemInstance>(copy); // player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
} // }
else { // else {
player->inventory->setItem(player->inventory->selected, player->inventory->armor[slot]); // player->inventory->setItem(player->inventory->selected, player->inventory->armor[slot]);
player->inventory->armor[slot] = make_shared<ItemInstance>(copy); // player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
} // }
} //}
int material = Item::items[instance->id]->getMaterial(); int material = Item::items[instance->id]->getMaterial();
int lo, hi; int lo, hi;

View file

@ -25,6 +25,11 @@ const wstring CustomPayloadPacket::IDENTITY_TOKEN_RESPONSE = L"MC|CTResponse";
const wstring CustomPayloadPacket::FORK_HELLO_CHANNEL = L"MC|ForkHello"; const wstring CustomPayloadPacket::FORK_HELLO_CHANNEL = L"MC|ForkHello";
const wstring CustomPayloadPacket::FORK_PLAYER_LEAVE_CHANNEL = L"MC|ForkPLeave"; const wstring CustomPayloadPacket::FORK_PLAYER_LEAVE_CHANNEL = L"MC|ForkPLeave";
const wstring CustomPayloadPacket::QUICK_EQUIP_PACKET = L"MC|QEquip";
const wstring CustomPayloadPacket::QUICK_EQUIP_SERVER_PACKET = L"MC|QEquipServer";
const wstring CustomPayloadPacket::ENCHANTMENT_LIST_PACKET = L"MC|EnchList";
CustomPayloadPacket::CustomPayloadPacket() CustomPayloadPacket::CustomPayloadPacket()
: length(0) : length(0)
{ {

View file

@ -31,6 +31,12 @@ public:
static const wstring FORK_HELLO_CHANNEL; // server->client: identifies fork server (empty payload) static const wstring FORK_HELLO_CHANNEL; // server->client: identifies fork server (empty payload)
static const wstring FORK_PLAYER_LEAVE_CHANNEL; // server->client: player disconnected (payload: UTF gamertag) static const wstring FORK_PLAYER_LEAVE_CHANNEL; // server->client: player disconnected (payload: UTF gamertag)
// Fixes for MP related crashes
static const wstring QUICK_EQUIP_PACKET;
static const wstring QUICK_EQUIP_SERVER_PACKET;
static const wstring ENCHANTMENT_LIST_PACKET;
wstring identifier; wstring identifier;
int length; int length;
byteArray data; byteArray data;

View file

@ -9,6 +9,10 @@
#include "../../../Minecraft.Client/ServerPlayer.h" #include "../../../Minecraft.Client/ServerPlayer.h"
#include "../../../Minecraft.Client/MinecraftServer.h" #include "../../../Minecraft.Client/MinecraftServer.h"
#include "../../../Minecraft.Client/PlayerList.h" #include "../../../Minecraft.Client/PlayerList.h"
#include "../../../Minecraft.Client/MultiPlayerLocalPlayer.h"
#include "../../../Minecraft.Client/PlayerConnection.h"
#include "../../../Minecraft.World/CustomPayloadPacket.h"
#include "../../../Minecraft.Client/Minecraft.h"
EnchantmentMenu::EnchantmentMenu(shared_ptr<Inventory> inventory, Level *level, int xt, int yt, int zt) EnchantmentMenu::EnchantmentMenu(shared_ptr<Inventory> inventory, Level *level, int xt, int yt, int zt)
{ {
@ -169,7 +173,28 @@ void EnchantmentMenu::slotsChanged(int a) // 4J used to take a shared_ptr<Contai
//delete cachedEnchantments[i]; // clean up old one first <- doing it elsewhere //delete cachedEnchantments[i]; // clean up old one first <- doing it elsewhere
cachedEnchantments[i] = EnchantmentHelper::selectEnchantment(&random, item, costs[i]); cachedEnchantments[i] = EnchantmentHelper::selectEnchantment(&random, item, costs[i]);
} }
ByteArrayOutputStream baos;
DataOutputStream dos(&baos);
//dos.writeInt(playerT->enchantmentSeed);
int b = 0;
for (int a = 0; a < 3; a++) {
vector<EnchantmentInstance*>* newEnchantment = cachedEnchantments[a];
for (int index = 0; index < newEnchantment->size(); index++)
{
EnchantmentInstance* e = newEnchantment->at(index);
dos.writeInt(e->enchantment->id);
dos.writeInt(e->level);
//delete e;
}
dos.writeInt(-1);
}
dos.writeInt(-2);
//MinecraftServer::getInstance()->getPlayers()->players[0]->connection->send(std::make_shared<CustomPayloadPacket>(CustomPayloadPacket::ENCHANTMENT_LIST_PACKET, baos.toByteArray()));
PlayerList* playerList = MinecraftServer::getInstance()->getPlayers();
playerList->broadcastAll(std::make_shared<CustomPayloadPacket>(CustomPayloadPacket::ENCHANTMENT_LIST_PACKET, baos.toByteArray()));
} }
alreadyRan = true; alreadyRan = true;
@ -228,7 +253,7 @@ bool EnchantmentMenu::clickMenuButton(shared_ptr<Player> player, int i)
return false; return false;
} }
EnchantmentInstance* EnchantmentMenu::predictEnchantment(shared_ptr<Player> player, int i) EnchantmentInstance* EnchantmentMenu::predictEnchantment(Player* player, int i)
{ {
shared_ptr<ItemInstance> item = enchantSlots->getItem(0); shared_ptr<ItemInstance> item = enchantSlots->getItem(0);
if (costs[i] > 0 && item != nullptr && (player->experienceLevel >= costs[i] || player->abilities.instabuild)) if (costs[i] > 0 && item != nullptr && (player->experienceLevel >= costs[i] || player->abilities.instabuild))

View file

@ -51,7 +51,7 @@ public:
virtual void setData(int id, int value); virtual void setData(int id, int value);
virtual void slotsChanged(int a);// 4J used to take a shared_ptr<Container> container but wasn't using it, so removed to simplify things virtual void slotsChanged(int a);// 4J used to take a shared_ptr<Container> container but wasn't using it, so removed to simplify things
virtual bool clickMenuButton(shared_ptr<Player> player, int i); virtual bool clickMenuButton(shared_ptr<Player> player, int i);
virtual EnchantmentInstance* predictEnchantment(shared_ptr<Player> player, int i); virtual EnchantmentInstance* predictEnchantment(Player* player, int i);
void removed(shared_ptr<Player> player); void removed(shared_ptr<Player> player);
virtual bool stillValid(shared_ptr<Player> player); virtual bool stillValid(shared_ptr<Player> player);
virtual shared_ptr<ItemInstance> quickMoveStack(shared_ptr<Player> player, int slotIndex); virtual shared_ptr<ItemInstance> quickMoveStack(shared_ptr<Player> player, int slotIndex);

View file

@ -32,6 +32,11 @@ class Merchant;
class PlayerEnderChestContainer; class PlayerEnderChestContainer;
class GameType; class GameType;
class Scoreboard; class Scoreboard;
struct EnchantmentEntry {
int level;
int id;
};
class Player : public LivingEntity, public CommandSender, public ScoreHolder class Player : public LivingEntity, public CommandSender, public ScoreHolder
{ {
@ -67,6 +72,7 @@ public:
AbstractContainerMenu *inventoryMenu; AbstractContainerMenu *inventoryMenu;
AbstractContainerMenu *containerMenu; AbstractContainerMenu *containerMenu;
int enchantmentSeed = 0; int enchantmentSeed = 0;
vector<EnchantmentEntry> enchantmentEntries = vector<EnchantmentEntry>(3);
protected: protected:
FoodData foodData; FoodData foodData;