fix: mail money uint64, other-player cape textures, zone toast dedup, TCP_NODELAY

Mail: change money/COD fields from uint32 to uint64 in CMSG_SEND_MAIL and
SMSG_MAIL_LIST_RESULT for WotLK 3.3.5a. Classic keeps uint32 on the wire.
Fixes money truncation and packet misalignment causing mail failures.

Other-player capes: add cape texture loading to setOnlinePlayerEquipment().
The cape geoset was enabled but no texture was loaded, leaving capes blank.
Now mirrors the local-player path: looks up ItemDisplayInfo.dbc, finds cape
texture candidates, applies via setGroupTextureOverride/setTextureSlotOverride.

Zone toasts: suppress duplicate zone toast when the zone text overlay is
already showing the same zone name. Fixes double "Entering: Stormwind City".

Network: enable TCP_NODELAY on both auth and world sockets after connect(),
disabling Nagle's algorithm to eliminate up to 200ms buffering delay on
small packets (movement, spell casts, chat).

Rendering: track material and bone descriptor sets in M2 renderer to skip
redundant vkCmdBindDescriptorSets calls between batches sharing same textures.
This commit is contained in:
Kelsi 2026-03-27 17:20:31 -07:00
parent 6b1c728377
commit 50a3eb7f07
12 changed files with 141 additions and 28 deletions

View file

@ -2290,6 +2290,8 @@ void M2Renderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet, const
// State tracking
VkPipeline currentPipeline = VK_NULL_HANDLE;
VkDescriptorSet currentMaterialSet = VK_NULL_HANDLE;
VkDescriptorSet currentBoneSet = VK_NULL_HANDLE;
uint32_t frameIndex = vkCtx_->getCurrentFrame();
// Push constants struct matching m2.vert.glsl push_constant block
@ -2397,10 +2399,11 @@ void M2Renderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet, const
instance.bonesDirty[frameIndex] = false;
}
// Bind bone descriptor set (set 2)
if (instance.boneSet[frameIndex]) {
// Bind bone descriptor set (set 2) — skip if already bound
if (instance.boneSet[frameIndex] && instance.boneSet[frameIndex] != currentBoneSet) {
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout_, 2, 1, &instance.boneSet[frameIndex], 0, nullptr);
currentBoneSet = instance.boneSet[frameIndex];
}
}
@ -2568,8 +2571,11 @@ void M2Renderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet, const
// Bind material descriptor set (set 1) — skip batch if missing
// to avoid inheriting a stale descriptor set from a prior renderer
if (!batch.materialSet) continue;
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout_, 1, 1, &batch.materialSet, 0, nullptr);
if (batch.materialSet != currentMaterialSet) {
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout_, 1, 1, &batch.materialSet, 0, nullptr);
currentMaterialSet = batch.materialSet;
}
// Push constants
M2PushConstants pc;
@ -2598,8 +2604,10 @@ void M2Renderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet, const
currentModelId = UINT32_MAX;
currentModel = nullptr;
currentModelValid = false;
// Reset pipeline to opaque so the first transparent bind always sets explicitly
// Reset state so the first transparent bind always sets explicitly
currentPipeline = opaquePipeline_;
currentMaterialSet = VK_NULL_HANDLE;
currentBoneSet = VK_NULL_HANDLE;
for (const auto& entry : sortedVisible_) {
if (entry.index >= instances.size()) continue;
@ -2647,9 +2655,10 @@ void M2Renderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet, const
bool needsBones = modelNeedsAnimation && !instance.boneMatrices.empty();
if (needsBones && (!instance.boneBuffer[frameIndex] || !instance.boneSet[frameIndex])) continue;
bool useBones = needsBones;
if (useBones && instance.boneSet[frameIndex]) {
if (useBones && instance.boneSet[frameIndex] && instance.boneSet[frameIndex] != currentBoneSet) {
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout_, 2, 1, &instance.boneSet[frameIndex], 0, nullptr);
currentBoneSet = instance.boneSet[frameIndex];
}
uint16_t desiredLOD = 0;
@ -2740,8 +2749,11 @@ void M2Renderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet, const
}
if (!batch.materialSet) continue;
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout_, 1, 1, &batch.materialSet, 0, nullptr);
if (batch.materialSet != currentMaterialSet) {
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout_, 1, 1, &batch.materialSet, 0, nullptr);
currentMaterialSet = batch.materialSet;
}
M2PushConstants pc;
pc.model = instance.modelMatrix;