mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 02:43:44 +00:00
feat(net): MATCH_REQUEST and MATCH_TRANSFER chat packets and the chat server's MatchUpdate
MATCH_TRANSFER is appended after GUILD_DISBAND (71); the chat ids from CREATE_TEAM on are pinned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -648,3 +648,63 @@ bool ChatPackets::GuildStatus::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(guildName));
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChatPackets::MatchRequest::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(playerID);
|
||||
bitStream.Write(type);
|
||||
bitStream.Write(value);
|
||||
bitStream.Write(activityID);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, playerName);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, playerChoices);
|
||||
bitStream.Write(instanceMapID);
|
||||
bitStream.Write(minTeams);
|
||||
bitStream.Write(maxTeams);
|
||||
bitStream.Write(minTeamSize);
|
||||
bitStream.Write(maxTeamSize);
|
||||
bitStream.Write(waitTime);
|
||||
bitStream.Write(startDelay);
|
||||
}
|
||||
|
||||
bool ChatPackets::MatchRequest::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(playerID));
|
||||
VALIDATE_READ(bitStream.Read(type));
|
||||
if (type != eMatchRequestType::JOIN && type != eMatchRequestType::READY && type != eMatchRequestType::LEAVE) return false;
|
||||
VALIDATE_READ(bitStream.Read(value));
|
||||
VALIDATE_READ(bitStream.Read(activityID));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, playerName, LoginSessionNotify::MAX_NAME_LENGTH));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, playerChoices, 4096));
|
||||
VALIDATE_READ(bitStream.Read(instanceMapID));
|
||||
VALIDATE_READ(bitStream.Read(minTeams));
|
||||
VALIDATE_READ(bitStream.Read(maxTeams));
|
||||
VALIDATE_READ(bitStream.Read(minTeamSize));
|
||||
VALIDATE_READ(bitStream.Read(maxTeamSize));
|
||||
VALIDATE_READ(bitStream.Read(waitTime));
|
||||
VALIDATE_READ(bitStream.Read(startDelay));
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChatPackets::MatchTransfer::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(activityID);
|
||||
WriteZone(bitStream, zoneID);
|
||||
BitStreamUtils::WriteLengthPrefixed<uint32_t>(bitStream, serverIP);
|
||||
bitStream.Write(serverPort);
|
||||
bitStream.Write<uint8_t>(mythranShift);
|
||||
bitStream.Write<uint32_t>(players.size());
|
||||
for (const auto player : players) bitStream.Write(player);
|
||||
}
|
||||
|
||||
bool ChatPackets::MatchTransfer::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(activityID));
|
||||
VALIDATE_READ(ReadZone(bitStream, zoneID));
|
||||
VALIDATE_READ(BitStreamUtils::ReadLengthPrefixed<uint32_t>(bitStream, serverIP, 255));
|
||||
VALIDATE_READ(bitStream.Read(serverPort));
|
||||
uint8_t shift{};
|
||||
VALIDATE_READ(bitStream.Read(shift));
|
||||
mythranShift = shift != 0;
|
||||
uint32_t count{};
|
||||
VALIDATE_READ(bitStream.Read(count));
|
||||
if (count > MAX_PLAYERS) return false;
|
||||
players.resize(count);
|
||||
for (auto& player : players) VALIDATE_READ(bitStream.Read(player));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -473,6 +473,55 @@ namespace ChatPackets {
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Activity matchmaking (docs/Matchmaking.md). The chat server keeps the lobbies of every world, so players on
|
||||
* different instances of a zone are matched into the same activity instance.
|
||||
*/
|
||||
enum class eMatchRequestType : int32_t {
|
||||
JOIN = 0, // the client's MatchRequest type 0
|
||||
READY = 1, // the client's MatchRequest type 1 (value: ready or not)
|
||||
LEAVE = 2, // DLU: the player left the lobby (LobbyExit) or can't stay in it
|
||||
};
|
||||
|
||||
// World -> chat: a player joins, readies in or leaves an activity lobby. On a join the world sends what it read
|
||||
// from the activity (CDClient Activities, with its own overrides such as solo racing), so chat needs no CDClient.
|
||||
struct MatchRequest : public LUBitStream {
|
||||
LWOOBJID playerID{};
|
||||
eMatchRequestType type{};
|
||||
int32_t value{}; // READY: 1 ready, 0 not ready
|
||||
int32_t activityID{};
|
||||
std::string playerName; // u32 length, then 1 byte per character
|
||||
std::string playerChoices; // the client's name-value text (like "droppedItem=13:<id>"), u32 length then bytes
|
||||
uint32_t instanceMapID{};
|
||||
int32_t minTeams{};
|
||||
int32_t maxTeams{};
|
||||
int32_t minTeamSize{};
|
||||
int32_t maxTeamSize{};
|
||||
int32_t waitTime{}; // milliseconds
|
||||
int32_t startDelay{}; // milliseconds
|
||||
|
||||
MatchRequest() : LUBitStream(ServiceType::CHAT, MessageType::Chat::MATCH_REQUEST) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
};
|
||||
|
||||
// Chat -> world (DLU): a lobby's match has its instance; send these players (the ones in this world) there
|
||||
struct MatchTransfer : public LUBitStream {
|
||||
// More players than this in one packet is a bad packet
|
||||
static constexpr uint32_t MAX_PLAYERS = 64;
|
||||
|
||||
int32_t activityID{};
|
||||
LWOZONEID zoneID{}; // map, instance and clone of the activity instance
|
||||
std::string serverIP; // u32 length, then 1 byte per character
|
||||
uint16_t serverPort{};
|
||||
bool mythranShift{};
|
||||
std::vector<LWOOBJID> players; // u32 count
|
||||
|
||||
MatchTransfer() : LUBitStream(ServiceType::CHAT, MessageType::Chat::MATCH_TRANSFER) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Chat-service packets the client receives, from the chat server (routed through the player's world) or from its world.
|
||||
*/
|
||||
|
||||
@@ -912,6 +912,21 @@ namespace ClientPackets {
|
||||
VALIDATE_READ(ReadZone(bitStream, zoneID));
|
||||
return true;
|
||||
}
|
||||
|
||||
void MatchUpdate::Serialize(RakNet::BitStream& bitStream) const {
|
||||
TeamGameMsg::Serialize(bitStream);
|
||||
BitStreamUtils::WriteNameValueText(bitStream, std::u16string(data.begin(), data.end()));
|
||||
bitStream.Write(type);
|
||||
}
|
||||
|
||||
bool MatchUpdate::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(TeamGameMsg::Deserialize(bitStream));
|
||||
std::u16string wide;
|
||||
VALIDATE_READ(BitStreamUtils::ReadNameValueText(bitStream, wide));
|
||||
data.assign(wide.begin(), wide.end());
|
||||
VALIDATE_READ(bitStream.Read(type));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ClientPackets {
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "eGuildCreateResponse.h"
|
||||
#include "eGuildInviteResponse.h"
|
||||
#include "eGuildRank.h"
|
||||
#include "eMatchUpdate.h"
|
||||
#include "eUgcResourceType.h"
|
||||
#include "MessageType/Client.h"
|
||||
#include "MessageType/Game.h"
|
||||
@@ -553,6 +554,17 @@ namespace ClientPackets {
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
};
|
||||
|
||||
// The activity lobby's MatchUpdate, written by the chat server's matchmaking (docs/Matchmaking.md). Byte for byte
|
||||
// GameMessages::MatchUpdate: name-value text (widened to UTF-16), then the eMatchUpdate type.
|
||||
struct MatchUpdate : public TeamGameMsg {
|
||||
std::string data; // name-value text, one byte per character here
|
||||
eMatchUpdate type{};
|
||||
|
||||
MatchUpdate() : TeamGameMsg(MessageType::Game::MATCH_UPDATE) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Guild packets (docs/Guilds.md), written by the chat server and routed through the player's world. The client
|
||||
* copies them into packed structs: every string is a fixed-size UTF-16 buffer it reads up to the first NUL, so
|
||||
|
||||
Reference in New Issue
Block a user