mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Fix update-object spline parsing regression
This commit is contained in:
parent
17a2a1f7ef
commit
3a9bd0d4e5
1 changed files with 65 additions and 19 deletions
|
|
@ -903,53 +903,99 @@ bool UpdateObjectParser::parseMovementBlock(network::Packet& packet, UpdateBlock
|
|||
|
||||
// Spline data
|
||||
if (moveFlags & 0x08000000) { // MOVEMENTFLAG_SPLINE_ENABLED
|
||||
auto bytesAvailable = [&](size_t n) -> bool { return packet.getReadPos() + n <= packet.getSize(); };
|
||||
if (!bytesAvailable(4)) return false;
|
||||
uint32_t splineFlags = packet.readUInt32();
|
||||
LOG_DEBUG(" Spline: flags=0x", std::hex, splineFlags, std::dec);
|
||||
|
||||
if (splineFlags & 0x00010000) { // SPLINEFLAG_FINAL_POINT
|
||||
if (!bytesAvailable(12)) return false;
|
||||
/*float finalX =*/ packet.readFloat();
|
||||
/*float finalY =*/ packet.readFloat();
|
||||
/*float finalZ =*/ packet.readFloat();
|
||||
} else if (splineFlags & 0x00020000) { // SPLINEFLAG_FINAL_TARGET
|
||||
if (!bytesAvailable(8)) return false;
|
||||
/*uint64_t finalTarget =*/ packet.readUInt64();
|
||||
} else if (splineFlags & 0x00040000) { // SPLINEFLAG_FINAL_ANGLE
|
||||
if (!bytesAvailable(4)) return false;
|
||||
/*float finalAngle =*/ packet.readFloat();
|
||||
}
|
||||
|
||||
// Legacy UPDATE_OBJECT spline layout used by many servers:
|
||||
// timePassed, duration, splineId, durationMod, durationModNext,
|
||||
// verticalAccel, effectStartTime, pointCount, points, splineMode, endPoint.
|
||||
const size_t legacyStart = packet.getReadPos();
|
||||
if (!bytesAvailable(12 + 8 + 8 + 4)) return false;
|
||||
/*uint32_t timePassed =*/ packet.readUInt32();
|
||||
/*uint32_t duration =*/ packet.readUInt32();
|
||||
/*uint32_t splineId =*/ packet.readUInt32();
|
||||
|
||||
/*float durationMod =*/ packet.readFloat();
|
||||
/*float durationModNext =*/ packet.readFloat();
|
||||
|
||||
/*float verticalAccel =*/ packet.readFloat();
|
||||
/*uint32_t effectStartTime =*/ packet.readUInt32();
|
||||
|
||||
uint32_t pointCount = packet.readUInt32();
|
||||
if (pointCount > 256) {
|
||||
|
||||
const size_t remainingAfterCount = packet.getSize() - packet.getReadPos();
|
||||
const bool legacyCountLooksValid = (pointCount <= 256);
|
||||
const size_t legacyPointsBytes = static_cast<size_t>(pointCount) * 12ull;
|
||||
const bool legacyPayloadFits = (legacyPointsBytes + 13ull) <= remainingAfterCount;
|
||||
|
||||
if (legacyCountLooksValid && legacyPayloadFits) {
|
||||
for (uint32_t i = 0; i < pointCount; i++) {
|
||||
/*float px =*/ packet.readFloat();
|
||||
/*float py =*/ packet.readFloat();
|
||||
/*float pz =*/ packet.readFloat();
|
||||
}
|
||||
/*uint8_t splineMode =*/ packet.readUInt8();
|
||||
/*float endPointX =*/ packet.readFloat();
|
||||
/*float endPointY =*/ packet.readFloat();
|
||||
/*float endPointZ =*/ packet.readFloat();
|
||||
LOG_DEBUG(" Spline pointCount=", pointCount);
|
||||
}
|
||||
|
||||
// Legacy pointCount looks invalid; try compact WotLK layout as recovery.
|
||||
// This keeps malformed/variant packets from desyncing the whole update block.
|
||||
packet.setReadPos(legacyStart);
|
||||
const size_t afterFinalFacingPos = packet.getReadPos();
|
||||
if (splineFlags & 0x00400000) { // Animation
|
||||
if (!bytesAvailable(5)) return false;
|
||||
/*uint8_t animType =*/ packet.readUInt8();
|
||||
/*uint32_t animStart =*/ packet.readUInt32();
|
||||
}
|
||||
if (!bytesAvailable(4)) return false;
|
||||
/*uint32_t duration =*/ packet.readUInt32();
|
||||
if (splineFlags & 0x00000800) { // Parabolic
|
||||
if (!bytesAvailable(8)) return false;
|
||||
/*float verticalAccel =*/ packet.readFloat();
|
||||
/*uint32_t effectStartTime =*/ packet.readUInt32();
|
||||
}
|
||||
if (!bytesAvailable(4)) return false;
|
||||
const uint32_t compactPointCount = packet.readUInt32();
|
||||
if (compactPointCount > 16384) {
|
||||
static uint32_t badSplineCount = 0;
|
||||
++badSplineCount;
|
||||
if (badSplineCount <= 5 || (badSplineCount % 100) == 0) {
|
||||
LOG_WARNING(" Spline pointCount=", pointCount,
|
||||
" exceeds maximum, capping at 0 (readPos=",
|
||||
packet.getReadPos(), "/", packet.getSize(),
|
||||
", occurrence=", badSplineCount, ")");
|
||||
" invalid (legacy+compact) at readPos=",
|
||||
afterFinalFacingPos, "/", packet.getSize(),
|
||||
", occurrence=", badSplineCount);
|
||||
}
|
||||
pointCount = 0;
|
||||
} else {
|
||||
LOG_DEBUG(" Spline pointCount=", pointCount);
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < pointCount; i++) {
|
||||
/*float px =*/ packet.readFloat();
|
||||
/*float py =*/ packet.readFloat();
|
||||
/*float pz =*/ packet.readFloat();
|
||||
const bool uncompressed = (splineFlags & (0x00080000 | 0x00002000)) != 0;
|
||||
size_t compactPayloadBytes = 0;
|
||||
if (compactPointCount > 0) {
|
||||
if (uncompressed) {
|
||||
compactPayloadBytes = static_cast<size_t>(compactPointCount) * 12ull;
|
||||
} else {
|
||||
compactPayloadBytes = 12ull;
|
||||
if (compactPointCount > 1) {
|
||||
compactPayloadBytes += static_cast<size_t>(compactPointCount - 1) * 4ull;
|
||||
}
|
||||
}
|
||||
if (!bytesAvailable(compactPayloadBytes)) return false;
|
||||
packet.setReadPos(packet.getReadPos() + compactPayloadBytes);
|
||||
}
|
||||
|
||||
/*uint8_t splineMode =*/ packet.readUInt8();
|
||||
/*float endPointX =*/ packet.readFloat();
|
||||
/*float endPointY =*/ packet.readFloat();
|
||||
/*float endPointZ =*/ packet.readFloat();
|
||||
}
|
||||
}
|
||||
else if (updateFlags & UPDATEFLAG_POSITION) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue