mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-22 12:42:49 +00:00
feat(transfer): rocket launches send TransferToZone before TRANSFER_TO_WORLD
Live sent, right before TRANSFER_TO_WORLD on every rocket launch (131 captured): NotifyClientFlagChange(32, true), TransferToZone (check_transfer_allowed, the target map, the landing spawn point, the clone only for properties, no position or rotation), TransferToZoneCheckedIM (no queue) and NotifyClientFlagChange(32, false). DLU went straight to TRANSFER_TO_WORLD. In the client TransferToZone runs the civilian INVALIDMAPTRANSFERLIST check, and TransferToZoneCheckedIM pauses the player's controls, starts the target zone's loading screen and leaves the gameplay state (LWOCharacterComponent, cases TransferToZone and TransferToZoneCheckedIM). They are sent from the transfer callback, so a failed zone request never leaves the client paused. Instance exits through a message box used TransferToLastNonInstance in live instead and are not changed here. Check: launch rockets to Nimbus Station, Gnarled Forest and your property: controls lock and the destination's loading screen shows as the rocket leaves, and you land at the usual spawn point. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "ZoneMessages.h"
|
||||
#include "MovementMessages.h"
|
||||
#include "MissionMessages.h"
|
||||
|
||||
#include "BitStreamUtils.h"
|
||||
#include "CDClientManager.h"
|
||||
@@ -175,6 +176,84 @@ namespace GameMessages {
|
||||
return bitStream.Read(objectID);
|
||||
}
|
||||
|
||||
namespace {
|
||||
template<typename Msg>
|
||||
void WriteTransfer(RakNet::BitStream& bitStream, const Msg& msg, const bool first) {
|
||||
bitStream.Write(first);
|
||||
BitStreamUtils::WriteOptional<LWOCLONEID>(bitStream, msg.cloneID, 0);
|
||||
BitStreamUtils::WriteOptional(bitStream, msg.posX, std::numeric_limits<float>::max());
|
||||
BitStreamUtils::WriteOptional(bitStream, msg.posY, std::numeric_limits<float>::max());
|
||||
BitStreamUtils::WriteOptional(bitStream, msg.posZ, std::numeric_limits<float>::max());
|
||||
BitStreamUtils::WriteOptional(bitStream, msg.rotW, 1.0f);
|
||||
BitStreamUtils::WriteOptional(bitStream, msg.rotX, 0.0f);
|
||||
BitStreamUtils::WriteOptional(bitStream, msg.rotY, 0.0f);
|
||||
BitStreamUtils::WriteOptional(bitStream, msg.rotZ, 0.0f);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, msg.spawnPoint);
|
||||
bitStream.Write(msg.ucInstanceType);
|
||||
BitStreamUtils::WriteOptional<LWOMAPID>(bitStream, msg.zoneID, 0);
|
||||
}
|
||||
|
||||
template<typename Msg>
|
||||
bool ReadTransfer(RakNet::BitStream& bitStream, Msg& msg, bool& first) {
|
||||
VALIDATE_READ(bitStream.Read(first));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional<LWOCLONEID>(bitStream, msg.cloneID, 0));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, msg.posX, std::numeric_limits<float>::max()));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, msg.posY, std::numeric_limits<float>::max()));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, msg.posZ, std::numeric_limits<float>::max()));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, msg.rotW, 1.0f));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, msg.rotX, 0.0f));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, msg.rotY, 0.0f));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional(bitStream, msg.rotZ, 0.0f));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, msg.spawnPoint));
|
||||
VALIDATE_READ(bitStream.Read(msg.ucInstanceType));
|
||||
VALIDATE_READ(BitStreamUtils::ReadOptional<LWOMAPID>(bitStream, msg.zoneID, 0));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void TransferToZone::Serialize(RakNet::BitStream& bitStream) const {
|
||||
WriteTransfer(bitStream, *this, bCheckTransferAllowed);
|
||||
}
|
||||
|
||||
bool TransferToZone::Deserialize(RakNet::BitStream& bitStream) {
|
||||
return ReadTransfer(bitStream, *this, bCheckTransferAllowed);
|
||||
}
|
||||
|
||||
void TransferToZoneCheckedIM::Serialize(RakNet::BitStream& bitStream) const {
|
||||
WriteTransfer(bitStream, *this, bIsThereaQueue);
|
||||
}
|
||||
|
||||
bool TransferToZoneCheckedIM::Deserialize(RakNet::BitStream& bitStream) {
|
||||
return ReadTransfer(bitStream, *this, bIsThereaQueue);
|
||||
}
|
||||
|
||||
void SendZoneTransferNotice(const LWOOBJID player, const LWOMAPID zoneID, const LWOCLONEID cloneID, const std::u16string& spawnPoint, const SystemAddress& sysAddr) {
|
||||
NotifyClientFlagChange flag;
|
||||
flag.target = player;
|
||||
flag.iFlagID = static_cast<uint32_t>(ePlayerFlag::BEGINNING_ZONE_SUMMARY_DISPLAYED);
|
||||
flag.bFlag = true;
|
||||
flag.SendToClient(sysAddr);
|
||||
|
||||
TransferToZone transfer;
|
||||
transfer.target = player;
|
||||
transfer.bCheckTransferAllowed = true;
|
||||
transfer.cloneID = cloneID;
|
||||
transfer.spawnPoint = spawnPoint;
|
||||
transfer.zoneID = zoneID;
|
||||
transfer.SendToClient(sysAddr);
|
||||
|
||||
TransferToZoneCheckedIM checked;
|
||||
checked.target = player;
|
||||
checked.bIsThereaQueue = false;
|
||||
checked.cloneID = cloneID;
|
||||
checked.spawnPoint = spawnPoint;
|
||||
checked.zoneID = zoneID;
|
||||
checked.SendToClient(sysAddr);
|
||||
|
||||
flag.bFlag = false;
|
||||
flag.SendToClient(sysAddr);
|
||||
}
|
||||
|
||||
void InvalidZoneTransferList::Serialize(RakNet::BitStream& bitStream) const {
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, customerFeedbackURL);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, invalidMapTransferList);
|
||||
|
||||
Reference in New Issue
Block a user