mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-11-15 08:17:13 +00:00
fix: tell the player when the zone they go to gets no instance
The master server dropped a transfer request it started no instance for, so the world server never heard back and the player waited. It now answers the request with an empty address and the reason in place of the port: no room for another instance (max_instances), a zone that is not in the ZoneTable, or another reason. A request for a private zone that does not exist is answered the same way. The world server passes this on as a TRANSFER_TO_WORLD without an address, which the client shows as a failed map change, and leaves the character where it is. The auth server fails the login when there is no character select to send the player to. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
@@ -276,6 +276,11 @@ void AuthPackets::LoginRequest::Handle() {
|
||||
stamps.Add(eStamps::PASSPORT_AUTH_WORLD_COMMUNICATION_START);
|
||||
// The stamps go along: master adds its steps and sends them back with the world server
|
||||
ZoneInstanceManager::Instance()->RequestZoneTransfer(server, 0, 0, false, stamps, [system, server, username](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string zoneIP, uint16_t zonePort, Stamps stamps) mutable {
|
||||
// An empty address is the master server's answer when no character select runs
|
||||
if (zoneIP.empty()) {
|
||||
AuthPackets::SendLoginResponse(server, system, eLoginResponse::GENERAL_FAILED, "", "", 0, username, stamps);
|
||||
return;
|
||||
}
|
||||
AuthPackets::SendLoginResponse(server, system, eLoginResponse::SUCCESS, "", zoneIP, zonePort, username, stamps);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "WorldPackets.h"
|
||||
|
||||
#include "ClientPackets.h"
|
||||
#include "dCommonVars.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -18,6 +20,17 @@ namespace {
|
||||
}
|
||||
|
||||
namespace WorldPackets {
|
||||
bool SendIfTransferFailed(const SystemAddress& sysAddr, const std::string& serverIP, const uint32_t serverPort) {
|
||||
if (!serverIP.empty()) return false;
|
||||
|
||||
LOG("No instance to transfer %s to (reason %u)", sysAddr.ToString(), serverPort);
|
||||
// The client reads the port of a transfer without an address as the reason and tells the player
|
||||
ClientPackets::TransferToWorld transfer;
|
||||
transfer.serverPort = static_cast<uint16_t>(serverPort);
|
||||
transfer.Send(sysAddr);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Validation::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(username);
|
||||
bitStream.Write(sessionKey);
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
// Packets of ServiceType::WORLD: what a client sends to a world server. The server's answers are ClientPackets.
|
||||
// The structs only read and write bytes; the world server attaches the handlers (see WorldServer.cpp).
|
||||
namespace WorldPackets {
|
||||
/**
|
||||
* Tells a player that the zone they were to go to has no instance. The master server answers a transfer
|
||||
* request with an empty address then, and with the eTransferFailure in place of the port.
|
||||
* @return whether the transfer failed, the caller has nothing left to do for it then
|
||||
*/
|
||||
bool SendIfTransferFailed(const SystemAddress& sysAddr, const std::string& serverIP, uint32_t serverPort);
|
||||
|
||||
// Base of every world packet: the dispatcher sets sysAddr before Deserialize and Handle.
|
||||
struct WorldLUBitStream : public LUBitStream {
|
||||
SystemAddress sysAddr = UNASSIGNED_SYSTEM_ADDRESS;
|
||||
|
||||
Reference in New Issue
Block a user