From 17ed3d2b9a82634a8bdddf8431c600cea3a15308 Mon Sep 17 00:00:00 2001 From: itsRevela Date: Thu, 26 Mar 2026 22:25:14 -0500 Subject: [PATCH] Fix Ender Dragon damage, End portal transition, and End Poem crash Dragon melee damage: reassign sub-entity IDs to be sequential from the parent entity ID in ServerLevel::entityAdded(), so the client's offset-based ID calculation matches the server. Previously the server's smallId pool allocated non-sequential IDs, causing melee attacks to target entity IDs the server didn't recognize. End portal transition: ensure the player entity is always added to the new level when transitioning from The End, not just for non-End dimensions. The addEntity call was previously gated behind a lastDimension != 1 check that also excluded it from End exits. End Poem crash: bounds-check the WIN_GAME event's player index before accessing localplayers[], with a fallback to prevent null dereference when the server sends an out-of-range index. --- Minecraft.Client/Common/UI/UIScene_EndPoem.cpp | 11 ++++++++--- Minecraft.Client/PlayerConnection.cpp | 4 +--- Minecraft.Client/PlayerList.cpp | 15 ++++++++------- Minecraft.Client/ServerLevel.cpp | 5 +++++ Minecraft.World/EnderDragon.cpp | 9 --------- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Minecraft.Client/Common/UI/UIScene_EndPoem.cpp b/Minecraft.Client/Common/UI/UIScene_EndPoem.cpp index 5b10e8cfeb..ead86c3dd7 100644 --- a/Minecraft.Client/Common/UI/UIScene_EndPoem.cpp +++ b/Minecraft.Client/Common/UI/UIScene_EndPoem.cpp @@ -50,14 +50,19 @@ UIScene_EndPoem::UIScene_EndPoem(int iPad, void *initData, UILayer *parentLayer) Minecraft *pMinecraft = Minecraft::GetInstance(); wstring playerName = L""; - if(pMinecraft->localplayers[ui.GetWinUserIndex()] != nullptr) + unsigned int winIdx = ui.GetWinUserIndex(); + if(winIdx < XUSER_MAX_COUNT && pMinecraft->localplayers[winIdx] != nullptr) { - playerName = escapeXML( pMinecraft->localplayers[ui.GetWinUserIndex()]->getDisplayName() ); + playerName = escapeXML( pMinecraft->localplayers[winIdx]->getDisplayName() ); } - else + else if(pMinecraft->localplayers[ProfileManager.GetPrimaryPad()] != nullptr) { playerName = escapeXML( pMinecraft->localplayers[ProfileManager.GetPrimaryPad()]->getDisplayName() ); } + else + { + playerName = L"Player"; + } noNoiseString = replaceAll(noNoiseString,L"{*PLAYER*}",playerName); Random random(8124371); diff --git a/Minecraft.Client/PlayerConnection.cpp b/Minecraft.Client/PlayerConnection.cpp index 1fb7c39888..b5fc5321bc 100644 --- a/Minecraft.Client/PlayerConnection.cpp +++ b/Minecraft.Client/PlayerConnection.cpp @@ -816,9 +816,7 @@ void PlayerConnection::handleInteract(shared_ptr packet) { if ((target->GetType() == eTYPE_ITEMENTITY) || (target->GetType() == eTYPE_EXPERIENCEORB) || (target->GetType() == eTYPE_ARROW) || target == player) { - //disconnect("Attempting to attack an invalid entity"); - //server.warn("Player " + player.getName() + " tried to attack an invalid entity"); - return; + return; } player->attack(target); } diff --git a/Minecraft.Client/PlayerList.cpp b/Minecraft.Client/PlayerList.cpp index ba82ec6acd..7a252b7320 100644 --- a/Minecraft.Client/PlayerList.cpp +++ b/Minecraft.Client/PlayerList.cpp @@ -951,15 +951,16 @@ void PlayerList::repositionAcrossDimension(shared_ptr entity, int lastDi addPlayerToReceiving(player); } - if (lastDimension != 1) + xt = static_cast(Mth::clamp(static_cast(xt), -Level::MAX_LEVEL_SIZE + 128, Level::MAX_LEVEL_SIZE - 128)); + zt = static_cast(Mth::clamp(static_cast(zt), -Level::MAX_LEVEL_SIZE + 128, Level::MAX_LEVEL_SIZE - 128)); + if (entity->isAlive()) { - xt = static_cast(Mth::clamp(static_cast(xt), -Level::MAX_LEVEL_SIZE + 128, Level::MAX_LEVEL_SIZE - 128)); - zt = static_cast(Mth::clamp(static_cast(zt), -Level::MAX_LEVEL_SIZE + 128, Level::MAX_LEVEL_SIZE - 128)); - if (entity->isAlive()) + newLevel->addEntity(entity); + entity->moveTo(xt, entity->y, zt, entity->yRot, entity->xRot); + newLevel->tick(entity, false); + // Portal forcing only for non-End exits (End exits go to spawn, not a portal) + if (lastDimension != 1) { - newLevel->addEntity(entity); - entity->moveTo(xt, entity->y, zt, entity->yRot, entity->xRot); - newLevel->tick(entity, false); newLevel->cache->autoCreate = true; newLevel->getPortalForcer()->force(entity, xOriginal, yOriginal, zOriginal, yRotOriginal); newLevel->cache->autoCreate = false; diff --git a/Minecraft.Client/ServerLevel.cpp b/Minecraft.Client/ServerLevel.cpp index 9d5ec9089d..80a12c996a 100644 --- a/Minecraft.Client/ServerLevel.cpp +++ b/Minecraft.Client/ServerLevel.cpp @@ -1052,9 +1052,14 @@ void ServerLevel::entityAdded(shared_ptr e) vector > *es = e->getSubEntities(); if (es) { + // Reassign sub-entity IDs to be sequential from the parent's ID. + // The client assumes this layout when it applies an offset in handleAddMob. + int offset = 1; for(auto& i : *es) { + i->entityId = e->entityId + offset; entitiesById.emplace(i->entityId, i); + offset++; } } entityAddedExtra(e); // 4J added diff --git a/Minecraft.World/EnderDragon.cpp b/Minecraft.World/EnderDragon.cpp index f8e4871f52..bc4cd969c0 100644 --- a/Minecraft.World/EnderDragon.cpp +++ b/Minecraft.World/EnderDragon.cpp @@ -1118,15 +1118,6 @@ bool EnderDragon::hurt(shared_ptr MultiEntityMobPart, Damage damage = damage / 4 + 1; } - //float rot1 = yRot * PI / 180; - //float ss1 = sin(rot1); - //float cc1 = cos(rot1); - - //xTarget = x + ss1 * 5 + (random->nextFloat() - 0.5f) * 2; - //yTarget = y + random->nextFloat() * 3 + 1; - //zTarget = z - cc1 * 5 + (random->nextFloat() - 0.5f) * 2; - //attackTarget = nullptr; - if ( source->getEntity() != nullptr && source->getEntity()->instanceof(eTYPE_PLAYER) || source->isExplosion() ) { int healthBefore = getHealth();