mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-18 02:32:50 +00:00
Live answered PlayerLoaded with PlayerReady to the player and then a second PlayerReady to the zone control object (0x3FFFFFFFFFFE), both to the loading client: 235 of 237 captured loads carry exactly that pair. DLU sent only the first. The zone control object's client-side zone scripts are what can react to it (inferred: the client's component handlers only act on the player's own PlayerReady). Check: load into Avant Gardens, Nimbus Station, a property and an instance (a survival or dragon battle): the zone plays its intro, music and UI as before and nothing is stuck waiting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
118 lines
4.9 KiB
C++
118 lines
4.9 KiB
C++
#ifndef ZONEMESSAGES_H
|
|
#define ZONEMESSAGES_H
|
|
|
|
#include "GameMessages.h"
|
|
#include "eObjectWorldState.h"
|
|
|
|
#include <string>
|
|
|
|
// Game messages for a player's zone lifecycle: loading in, zone summaries, level ups, announcements.
|
|
// Fields are listed in wire order; names follow the client (legouniverse.exe 1.10.64) where known.
|
|
namespace GameMessages {
|
|
// Client -> server. The client finished loading the zone and its player.
|
|
struct PlayerLoaded : public NetGameMsg {
|
|
PlayerLoaded() : NetGameMsg(MessageType::Game::PLAYER_LOADED) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
LWOOBJID playerID{};
|
|
};
|
|
|
|
// Client -> server. The client finished loading an object. Nothing to do.
|
|
struct ReadyForUpdates : public NetGameMsg {
|
|
ReadyForUpdates() : NetGameMsg(MessageType::Game::READY_FOR_UPDATES) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
LWOOBJID objectID{};
|
|
};
|
|
|
|
// Server -> client, to one client. No payload.
|
|
struct PlayerReady : public NetGameMsg {
|
|
PlayerReady() : NetGameMsg(MessageType::Game::PLAYER_READY) {}
|
|
};
|
|
|
|
// Answers PlayerLoaded the way live did (235 of 237 loads): PlayerReady to the player, then to the zone control
|
|
// object, whose client scripts wait for it. zoneControl is LWOOBJID_EMPTY when the zone has none.
|
|
void SendPlayerReady(LWOOBJID player, LWOOBJID zoneControl, const SystemAddress& sysAddr);
|
|
|
|
// Server -> client, to one client. No payload.
|
|
struct RestoreToPostLoadStats : public NetGameMsg {
|
|
RestoreToPostLoadStats() : NetGameMsg(MessageType::Game::RESTORE_TO_POST_LOAD_STATS) {}
|
|
};
|
|
|
|
// Server -> client, to one client. No payload.
|
|
struct ServerDoneLoadingAllObjects : public NetGameMsg {
|
|
ServerDoneLoadingAllObjects() : NetGameMsg(MessageType::Game::SERVER_DONE_LOADING_ALL_OBJECTS) {}
|
|
};
|
|
|
|
// Server -> client, to one client.
|
|
struct InvalidZoneTransferList : public NetGameMsg {
|
|
InvalidZoneTransferList() : NetGameMsg(MessageType::Game::INVALID_ZONE_TRANSFER_LIST) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
std::u16string customerFeedbackURL{};
|
|
std::u16string invalidMapTransferList{};
|
|
bool bCustomerFeedbackOnExit{};
|
|
bool bCustomerFeedbackOnInvalidMapTransfer{};
|
|
};
|
|
|
|
// Server -> client, to one client (UNASSIGNED broadcasts).
|
|
struct DisplayZoneSummary : public NetGameMsg {
|
|
DisplayZoneSummary() : NetGameMsg(MessageType::Game::DISPLAY_ZONE_SUMMARY) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
bool isPropertyMap{ false };
|
|
bool isZoneStart{ false };
|
|
LWOOBJID sender{ LWOOBJID_EMPTY }; // optional
|
|
};
|
|
|
|
// Client -> server.
|
|
struct ZoneSummaryDismissed : public NetGameMsg {
|
|
ZoneSummaryDismissed() : NetGameMsg(MessageType::Game::ZONE_SUMMARY_DISMISSED) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
|
|
LWOOBJID playerID{};
|
|
};
|
|
|
|
// Client -> server. No payload. The client finished showing a level up.
|
|
struct NotifyServerLevelProcessingComplete : public NetGameMsg {
|
|
NotifyServerLevelProcessingComplete() : NetGameMsg(MessageType::Game::NOTIFY_SERVER_LEVEL_PROCESSING_COMPLETE) {}
|
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
};
|
|
|
|
// Server -> client, to one client (UNASSIGNED broadcasts). newState is optional (a flag, then the state when it
|
|
// isn't INWORLD), as live sent it (e.g. 80 80 00 00 00 for ATTACHED).
|
|
struct ChangeObjectWorldState : public NetGameMsg {
|
|
ChangeObjectWorldState() : NetGameMsg(MessageType::Game::CHANGE_OBJECT_WORLD_STATE) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
eObjectWorldState newState{ eObjectWorldState::INWORLD }; // optional
|
|
};
|
|
|
|
// Server -> client, to one client. The client looks both strings up in its locale (falling back to the text
|
|
// itself) and shows the announcement popup. Client Deserialize: 0x00f23c50.
|
|
struct LocalizedAnnouncementServerToSingleClient : public NetGameMsg {
|
|
LocalizedAnnouncementServerToSingleClient() : NetGameMsg(MessageType::Game::LOCALIZED_ANNOUNCEMENT_SERVER_TO_SINGLE_CLIENT) {}
|
|
void Serialize(RakNet::BitStream& bitStream) const override;
|
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
|
|
// Name-value (LDF) text: u32 character count, then that many characters plus a null terminator when not empty.
|
|
std::u16string bodyParams{};
|
|
bool bForceOpenChatBox{ false };
|
|
bool bShowAnnouncement{ true };
|
|
bool bShowInChat{ true };
|
|
std::u16string body{};
|
|
std::u16string title{};
|
|
std::u16string titleParams{}; // name-value (LDF) text, as bodyParams
|
|
};
|
|
}
|
|
|
|
#endif // ZONEMESSAGES_H
|