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);
}
}
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()

View file

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

View file

@ -143,10 +143,9 @@ void IUIScene_EnchantingMenu::handleOtherClicked(int iPad, ESceneSection eSectio
break;
};
Minecraft *pMinecraft = Minecraft::GetInstance();
MinecraftServer *aMinecraft = MinecraftServer::getInstance();
if (index >= 0 && dynamic_cast<EnchantmentMenu*>(aMinecraft->getPlayers()->players[iPad]->containerMenu)->clickMenuButton(dynamic_pointer_cast<Player>(aMinecraft->getPlayers()->players[iPad]), index))
if (index >= 0 && m_menu->clickMenuButton(dynamic_pointer_cast<Player>(pMinecraft->localplayers[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) {
int slot = Mob::getEquipmentSlotForItem(instance) - 1;
//int slot = Mob::getEquipmentSlotForItem(instance) - 1;
// If player is in survival mode (not creative)
if (!player->abilities.instabuild) { //
// Equip the armor to the appropriate slot
ItemInstance copy = *instance->copy_not_shared();
if (player->inventory->armor[slot] == nullptr) {
player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
player->inventory->removeItemNoUpdate(player->inventory->selected);
// Remove the item from hand (set count to 0)
instance->count = 0;
}
else {
player->inventory->setItem(player->inventory->selected, player->inventory->armor[slot]);
player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
}
}
else {
ItemInstance copy = *instance->copy_not_shared();
if (player->inventory->armor[slot] == nullptr) {
player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
}
else {
player->inventory->setItem(player->inventory->selected, player->inventory->armor[slot]);
player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
}
}
//// If player is in survival mode (not creative)
//if (!player->abilities.instabuild) { //
// // Equip the armor to the appropriate slot
// ItemInstance copy = *instance->copy_not_shared();
// if (player->inventory->armor[slot] == nullptr) {
// player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
// player->inventory->removeItemNoUpdate(player->inventory->selected);
// // Remove the item from hand (set count to 0)
// instance->count = 0;
// }
// else {
// player->inventory->setItem(player->inventory->selected, player->inventory->armor[slot]);
// player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
// }
//}
//else {
// ItemInstance copy = *instance->copy_not_shared();
// if (player->inventory->armor[slot] == nullptr) {
// player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
// }
// else {
// player->inventory->setItem(player->inventory->selected, player->inventory->armor[slot]);
// player->inventory->armor[slot] = make_shared<ItemInstance>(copy);
// }
//}
int material = Item::items[instance->id]->getMaterial();
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_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()
: 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_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;
int length;
byteArray data;

View file

@ -9,6 +9,10 @@
#include "../../../Minecraft.Client/ServerPlayer.h"
#include "../../../Minecraft.Client/MinecraftServer.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)
{
@ -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
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;
@ -228,7 +253,7 @@ bool EnchantmentMenu::clickMenuButton(shared_ptr<Player> player, int i)
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);
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 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 EnchantmentInstance* predictEnchantment(shared_ptr<Player> player, int i);
virtual EnchantmentInstance* predictEnchantment(Player* player, int i);
void removed(shared_ptr<Player> player);
virtual bool stillValid(shared_ptr<Player> player);
virtual shared_ptr<ItemInstance> quickMoveStack(shared_ptr<Player> player, int slotIndex);

View file

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