1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
|
/*
This file is part of Warzone 2100.
Copyright (C) 1999-2004 Eidos Interactive
Copyright (C) 2005-2024 Warzone 2100 Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Netplay.h
*
* Alex Lee sep97.
*/
#ifndef _netplay_h
#define _netplay_h
#include "lib/framework/crc.h"
#include "src/factionid.h"
#include "nettypes.h"
#include "wzfile.h"
#include "netlog.h"
#include "sync_debug.h"
#include "port_mapping_manager.h"
#include <physfs.h>
#include <vector>
#include <functional>
#include <memory>
// Lobby Connection errors
enum LOBBY_ERROR_TYPES
{
ERROR_NOERROR,
ERROR_CONNECTION,
ERROR_FULL,
ERROR_INVALID,
ERROR_KICKED,
ERROR_WRONGVERSION,
ERROR_WRONGPASSWORD,
ERROR_HOSTDROPPED,
ERROR_WRONGDATA,
ERROR_UNKNOWNFILEISSUE,
ERROR_REDIRECT
};
enum CONNECTION_STATUS
{
CONNECTIONSTATUS_PLAYER_DROPPED,
CONNECTIONSTATUS_PLAYER_LEAVING,
CONNECTIONSTATUS_DESYNC,
CONNECTIONSTATUS_WAITING_FOR_PLAYER,
CONNECTIONSTATUS_NORMAL
};
enum MESSAGE_TYPES
{
// Net-related messages.
NET_MIN_TYPE = 33, ///< Minimum-1 valid NET_ type, *MUST* be first.
NET_PING, ///< ping players.
NET_PLAYER_STATS, ///< player stats
NET_TEXTMSG, ///< A simple text message between machines.
NET_PLAYERRESPONDING, ///< computer that sent this is now playing warzone!
NET_OPTIONS, ///< welcome a player to a game.
NET_KICK, ///< kick a player .
NET_FIREUP, ///< campaign game has started, we can go too.. Shortcut message, not to be used in dmatch.
NET_COLOURREQUEST, ///< player requests a colour change.
NET_FACTIONREQUEST, ///< player requests a colour change.
NET_AITEXTMSG, ///< chat between AIs
NET_BEACONMSG, ///< place beacon
NET_TEAMREQUEST, ///< request team membership
NET_JOIN, ///< join a game
NET_ACCEPTED, ///< accepted into game
NET_PLAYER_INFO, ///< basic player info
NET_PLAYER_JOINED, ///< notice about player joining
NET_PLAYER_LEAVING, ///< A player is leaving, (nicely)
NET_PLAYER_DROPPED, ///< notice about player dropped / disconnected
NET_GAME_FLAGS, ///< game flags
NET_READY_REQUEST, ///< player ready to start an mp game
NET_REJECTED, ///< nope, you can't join
NET_POSITIONREQUEST, ///< position in GUI player list
NET_DATA_CHECK, ///< Data integrity check
NET_HOST_DROPPED, ///< Host has dropped
NET_SEND_TO_PLAYER, ///< Non-host clients aren't directly connected to each other, so they talk via the host using these messages.
NET_SHARE_GAME_QUEUE, ///< Message contains a game message, which should be inserted into a queue.
NET_FILE_REQUESTED, ///< Player has requested a file (map/mod/?)
NET_FILE_CANCELLED, ///< Player cancelled a file request
NET_FILE_PAYLOAD, ///< sending file to the player that needs it
NET_DEBUG_SYNC, ///< Synch error messages, so people don't have to use pastebin.
NET_VOTE, ///< player vote
NET_VOTE_REQUEST, ///< Setup a vote popup
NET_SPECTEXTMSG, ///< chat between spectators
NET_PLAYERNAME_CHANGEREQUEST, ///< non-host human player is changing their name.
NET_PLAYER_SLOTTYPE_REQUEST, ///< non-host human player is requesting a slot type change, or a host is asking a spectator if they want to play
NET_PLAYER_SWAP_INDEX, ///< a host-only message to move a player to another index
NET_PLAYER_SWAP_INDEX_ACK, ///< an acknowledgement message from a player whose index is being swapped
NET_DATA_CHECK2, ///< Data2 integrity check
NET_SECURED_NET_MESSAGE, ///< A secured (+ authenticated) net message between two players
NET_TEAM_STRATEGY, ///< Player is sending an updated strategy notice to team members
NET_QUICK_CHAT_MSG, ///< Quick chat message
NET_HOST_CONFIG, ///< Host configuration sent both before the game has started (in lobby), and after the game has started
NET_MAX_TYPE, ///< Maximum+1 valid NET_ type, *MUST* be last.
// Game-state-related messages, must be processed by all clients at the same game time.
GAME_MIN_TYPE = 111, ///< Minimum-1 valid GAME_ type, *MUST* be first.
GAME_DROIDINFO, ///< update a droid order.
GAME_STRUCTUREINFO, ///< Structure state.
GAME_RESEARCHSTATUS, ///< research state.
GAME_TEMPLATE, ///< a new template
GAME_TEMPLATEDEST, ///< remove template
GAME_ALLIANCE, ///< alliance data.
GAME_GIFT, ///< a luvly gift between players.
GAME_LASSAT, ///< lassat firing.
GAME_GAME_TIME, ///< Game time. Used for synchronising, so that all messages are executed at the same gameTime on all clients.
GAME_PLAYER_LEFT, ///< Player has left or dropped.
GAME_DROIDDISEMBARK, ///< droid disembarked from a Transporter
GAME_SYNC_REQUEST, ///< Game event generated from scripts that is meant to be synced
// The following messages are used for debug mode.
GAME_DEBUG_MODE, ///< Request enable/disable debug mode.
GAME_DEBUG_ADD_DROID, ///< Add droid.
GAME_DEBUG_ADD_STRUCTURE, ///< Add structure.
GAME_DEBUG_ADD_FEATURE, ///< Add feature.
GAME_DEBUG_REMOVE_DROID, ///< Remove droid.
GAME_DEBUG_REMOVE_STRUCTURE, ///< Remove structure.
GAME_DEBUG_REMOVE_FEATURE, ///< Remove feature.
GAME_DEBUG_FINISH_RESEARCH, ///< Research has been completed.
// End of debug messages.
GAME_SYNC_OPT_CHANGE, ///< Change synchronized options for a player (ex formation options)
GAME_MAX_TYPE, ///< Maximum+1 valid GAME_ type, *MUST* be last.
// The following messages are used for playing back replays.
REPLAY_ENDED = 255 ///< A special message for signifying the end of the replay
// End of replay messages.
};
enum SYNC_OPT_TYPES
{
SYNC_OPT_FORMATION_SPEED_LIMITING = 1
};
#define SYNC_FLAG 0x10000000 //special flag used for logging. (Not sure what this is. Was added in trunk, NUM_GAME_PACKETS not in newnet.)
#define WZ_SERVER_DISCONNECT 0
#define WZ_SERVER_CONNECT 1
#define WZ_SERVER_UPDATE 3
// Constants
// @NOTE / FIXME: We need a way to detect what should happen if the msg buffer exceeds this.
#define MaxMsgSize 32768 // max size of a message in bytes.
#define StringSize 64 // size of strings used.
#define extra_string_size 157 // extra 199 char for future use
#define map_string_size 40
#define hostname_string_size 40
#define modlist_string_size 255 // For a concatenated list of mods
#define password_string_size 64 // longer passwords slow down the join code
#define MAX_NET_TRANSFERRABLE_FILE_SIZE 0x8000000
static_assert(MaxMsgSize <= UINT16_MAX, "NetMessage/NetMessageBuilder encodes message length as a uint16_t");
struct SESSIONDESC //Available game storage... JUST FOR REFERENCE!
{
int32_t dwSize;
uint8_t alliances;
uint8_t techLevel;
uint8_t powerLevel;
uint8_t basesLevel;
char host[40]; // host's ip address (can fit a full IPv4 and IPv6 address + terminating NUL)
int32_t dwMaxPlayers;
int32_t dwCurrentPlayers;
uint32_t dwUserFlags[4]; // {game.type, openSpectatorSlots, blindMode, unused)
};
/**
* @note when changing this structure, NETsendGAMESTRUCT, NETrecvGAMESTRUCT and
* the lobby server should be changed accordingly.
*/
struct GAMESTRUCT
{
/* Version of this structure and thus the binary lobby protocol.
* @NOTE: <em>MUST</em> be the first item of this struct.
*/
uint32_t GAMESTRUCT_VERSION;
char name[StringSize];
SESSIONDESC desc;
// END of old GAMESTRUCT format
// NOTE: do NOT save the following items in game.c--it will break savegames.
char secondaryHosts[2][40];
char extra[extra_string_size]; // extra string (future use)
uint16_t hostPort; // server port
char mapname[map_string_size]; // map server is hosting
char hostname[hostname_string_size]; // ...
char versionstring[StringSize]; //
char modlist[modlist_string_size]; // ???
uint32_t game_version_major; //
uint32_t game_version_minor; //
uint32_t privateGame; // if true, it is a private game
uint32_t pureMap; // If this map has mods in it.
uint32_t Mods; // number of concatenated mods?
// Game ID, used on the lobby server to link games with multiple address families to eachother
uint32_t gameId;
uint32_t limits; // holds limits bitmask (NO_VTOL|NO_TANKS|NO_BORGS)
uint32_t future3; // for future use
uint32_t future4; // for future use
};
// ////////////////////////////////////////////////////////////////////////
// Message information. ie. the packets sent between machines.
// For NET_JOIN messages
enum NET_JOIN_PLAYERTYPE : uint8_t {
NET_JOIN_PLAYER = 0,
NET_JOIN_SPECTATOR = 1,
};
#define NET_ALL_PLAYERS 255
#define NET_HOST_ONLY 0
// the following structure is going to be used to track if we sync or not
struct SYNC_COUNTER
{
uint16_t kicks;
uint16_t joins;
uint16_t left;
uint16_t drops;
uint16_t cantjoin;
uint16_t banned;
uint16_t rejected;
};
enum class AIDifficulty : int8_t
{
SUPEREASY,
EASY,
MEDIUM,
HARD,
INSANE,
DEFAULT = MEDIUM,
DISABLED = -1,
HUMAN = -2,
};
enum class NET_LOBBY_OPT_FIELD
{
INVALID,
GNAME,
MAPNAME,
HOSTNAME,
MAX
};
// ////////////////////////////////////////////////////////////////////////
// Player information. Filled when players join, never re-ordered. selectedPlayer global points to
// currently controlled player.
struct PLAYER
{
char name[StringSize] = {}; ///< Player name
int32_t position; ///< Map starting position
int32_t colour; ///< Which colour slot this player is using
bool allocated; ///< Allocated as a human player
uint32_t heartattacktime; ///< Time cardiac arrest started
bool heartbeat; ///< If connection is still alive or not
int32_t team; ///< Which team we are on (int32_t::max for spectator team)
bool ready; ///< player ready to start?
int8_t ai; ///< index into sorted list of AIs, zero is always default AI
AIDifficulty difficulty; ///< difficulty level of AI
bool autoGame; ///< if we are running a autogame (AI controls us)
FactionID faction; ///< which faction the player has
bool isSpectator; ///< whether this slot is a spectator slot
bool isAdmin; ///< whether this slot has admin privs
// used on host-ONLY (not transmitted to other clients):
std::shared_ptr<std::vector<WZFile>> wzFiles = std::make_shared<std::vector<WZFile>>(); ///< for each player, we keep track of map/mod download progress
char IPtextAddress[40]; ///< IP of this player
bool fileSendInProgress() const
{
ASSERT_OR_RETURN(false, wzFiles != nullptr, "Null wzFiles");
return !wzFiles->empty();
}
void resetAll()
{
name[0] = '\0';
position = -1;
colour = 0;
allocated = false;
heartattacktime = 0;
heartbeat = false;
team = -1;
ready = false;
ai = 0;
difficulty = AIDifficulty::DISABLED;
autoGame = false;
IPtextAddress[0] = '\0';
faction = FACTION_NORMAL;
isSpectator = false;
isAdmin = false;
}
};
struct PlayerReference;
// ////////////////////////////////////////////////////////////////////////
// all the luvly Netplay info....
struct NETPLAY
{
std::vector<PLAYER> players; ///< The array of players.
uint32_t playercount; ///< Number of players in game.
uint32_t hostPlayer; ///< Index of host in player array
bool bComms; ///< Actually do the comms?
bool isHost; ///< True if we are hosting the game
bool isPortMappingEnabled; // if we want the automatic Port mapping setup routines to run
bool isHostAlive; /// if the host is still alive
char gamePassword[password_string_size]; //
bool GamePassworded; // if we have a password or not.
bool ShowedMOTD; // only want to show this once
bool HaveUpgrade; // game updates available
std::string MOTD;
std::vector<std::unordered_map<std::string, std::string>> scriptSetPlayerDataStrings;
std::vector<std::shared_ptr<PlayerReference>> playerReferences;
NETPLAY();
};
// ////////////////////////////////////////////////////////////////////////
// variables
extern NETPLAY NetPlay;
extern SYNC_COUNTER sync_counter;
// update flags
extern bool netPlayersUpdated;
extern char iptoconnect[PATH_MAX]; // holds IP/hostname from command line
extern bool cliConnectToIpAsSpectator; // = false; (for cli option)
extern bool netGameserverPortOverride; // = false; (for cli override)
extern PortMappingAsyncRequestHandle ipv4MappingRequest;
#define ASSERT_HOST_ONLY(failAction) \
if (!NetPlay.isHost) \
{ \
ASSERT(false, "Host only routine detected for client!"); \
failAction; \
}
enum class ConnectionProviderType : uint8_t;
// ////////////////////////////////////////////////////////////////////////
// functions available to you.
int NETinit(ConnectionProviderType pt);
bool NETsend(NETQUEUE queue, NetMessage const& message); ///< send to player, or broadcast if player == NET_ALL_PLAYERS.
void NETsendProcessDelayedActions();
WZ_DECL_NONNULL(1, 2) bool NETrecvNet(NETQUEUE *queue, uint8_t *type); ///< recv a message from the net queues if possible.
WZ_DECL_NONNULL(1, 2) bool NETrecvGame(NETQUEUE *queue, uint8_t *type); ///< recv a message from the game queues which is sceduled to execute by time, if possible.
void NETflush(); ///< Flushes any data stuck in compression buffers.
int NETsendFile(WZFile &file, unsigned player); ///< Send file chunk. Returns 100 when done.
int NETrecvFile(NETQUEUE queue); ///< Receive file chunk. Returns 100 when done.
unsigned NETgetDownloadProgress(unsigned player); ///< Returns 100 when done.
int NETclose(); // close current game
int NETshutdown(); // leave the game in play.
bool netplayShutDown();
void NETaddRedirects();
void NETremRedirects();
/// Initializes the port mapping infrastructure and spawns a background thread,
/// which will automatically add a port mapping rule and signal the main thread
/// (NETrecvNet, in particular) when the operation is complete.
void NETinitPortMapping();
enum NetStatisticType {NetStatisticRawBytes, NetStatisticUncompressedBytes, NetStatisticPackets};
size_t NETgetStatistic(NetStatisticType type, bool sent, bool isTotal = false); // Return some statistic. Call regularly for good results.
void NETplayerKicked(UDWORD index, bool quiet = false); // Cleanup after player has been kicked
bool NETplayerHasConnection(uint32_t index);
bool NETcanOpenNewSpectatorSlot();
bool NETopenNewSpectatorSlot();
bool NETmovePlayerToSpectatorOnlySlot(uint32_t playerIdx, bool hostOverride = false);
enum class SpectatorToPlayerMoveResult
{
SUCCESS,
NEEDS_SLOT_SELECTION,
FAILED
};
SpectatorToPlayerMoveResult NETmoveSpectatorToPlayerSlot(uint32_t playerIdx, optional<uint32_t> newPlayerIdx, bool hostOverride = false);
struct SpectatorInfo
{
uint16_t spectatorsJoined = 0;
uint16_t totalSpectatorSlots = 0;
inline uint16_t availableSpectatorSlots() const
{
if (spectatorsJoined > totalSpectatorSlots)
{
return 0;
}
return totalSpectatorSlots - spectatorsJoined;
}
static inline SpectatorInfo fromUint32(uint32_t data)
{
SpectatorInfo info;
info.spectatorsJoined = static_cast<uint16_t>(data >> 16);
info.totalSpectatorSlots = static_cast<uint16_t>(data & 0xFFFF);
return info;
}
static SpectatorInfo currentNetPlayState();
inline uint32_t toUint32() const
{
return static_cast<uint32_t>(spectatorsJoined << 16) | static_cast<uint32_t>(totalSpectatorSlots);
}
inline bool operator==(const SpectatorInfo& other)
{
return totalSpectatorSlots == other.totalSpectatorSlots
&& spectatorsJoined == other.spectatorsJoined;
}
inline bool operator!=(const SpectatorInfo& other)
{
return !(*this == other);
}
};
SpectatorInfo NETGameGetSpectatorInfo();
// from netjoin.c
SDWORD NETgetGameFlags(UDWORD flag); // return one of the four flags(dword) about the game.
uint32_t NETgetGameUserFlagsUnjoined(const GAMESTRUCT& game, unsigned int flag); // return one of the four flags(dword) about the game.
bool NETsetGameFlags(UDWORD flag, SDWORD value); // set game flag(1-4) to value.
bool NEThaltJoining(); // stop new players joining this game
class WzConnectionProvider;
std::shared_ptr<WzConnectionProvider> NET_getLobbyConnectionProvider();
bool NETenumerateGames(const std::shared_ptr<WzConnectionProvider>& connProvider, const std::function<bool (const GAMESTRUCT& game)>& handleEnumerateGameFunc, const std::function<void(std::string&& lobbyMOTD)>& lobbyMotdFunc = nullptr);
bool NETfindGames(std::vector<GAMESTRUCT>& results, std::string& lobbyMOTD, size_t startingIndex, size_t resultsLimit, bool onlyMatchingLocalVersion = false);
bool NETfindGame(uint32_t gameId, GAMESTRUCT& output);
class IClientConnection;
class IConnectionPollGroup;
bool NETpromoteJoinAttemptToEstablishedConnectionToHost(uint32_t hostPlayer, uint8_t index, const char* playername, NETQUEUE joiningQUEUEInfo, IClientConnection** client_joining_socket, IConnectionPollGroup** client_joining_socket_set);
bool NEThostGame(const char *SessionName, const char *PlayerName, bool spectatorHost, // host a game
uint32_t gameType, uint32_t two, uint32_t three, uint32_t four, UDWORD plyrs,
uint8_t alliancesType, uint8_t techLevel, uint8_t powerLevel, uint8_t basesLevel);
bool NETchangePlayerName(UDWORD player, char *newName);// change a players name.
void NETfixDuplicatePlayerNames(); // Change a player's name automatically, if there are duplicates.
void NETsetMasterserverName(const char *hostname);
const char *NETgetMasterserverName();
void NETsetMasterserverPort(unsigned int port);
unsigned int NETgetMasterserverPort();
void NETsetGameserverPort(unsigned int port);
unsigned int NETgetGameserverPort();
void NETsetJoinPreferenceIPv6(bool bTryIPv6First);
bool NETgetJoinPreferenceIPv6();
void NETsetDefaultMPHostFreeChatPreference(bool enabled);
bool NETgetDefaultMPHostFreeChatPreference();
void NETsetEnableTCPNoDelay(bool enabled);
bool NETgetEnableTCPNoDelay();
uint32_t NETgetJoinConnectionNETPINGChallengeFromHostSize();
uint32_t NETgetJoinConnectionNETPINGChallengeFromClientSize();
void NETsetGamePassword(const char *password);
void NETBroadcastPlayerInfo(uint32_t index);
void NETBroadcastTwoPlayerInfo(uint32_t index1, uint32_t index2);
void NETSendAllPlayerInfoTo(unsigned to);
bool NETisCorrectVersion(uint32_t game_version_major, uint32_t game_version_minor);
bool NETisGreaterVersion(uint32_t game_version_major, uint32_t game_version_minor);
uint32_t NETGetMajorVersion();
uint32_t NETGetMinorVersion();
void NET_InitPlayer(uint32_t i, bool initPosition, bool initTeams = false, bool initSpectator = false);
void NET_InitPlayers(bool initTeams = false, bool initSpectator = false);
uint8_t NET_numHumanPlayers(void);
void NETsetLobbyOptField(const char *Value, const NET_LOBBY_OPT_FIELD Field);
void NETsetLobbyConfigFlagsFields(uint8_t alliancesType, uint8_t techLevel, uint8_t powerLevel, uint8_t basesLevel);
std::vector<uint8_t> NET_getHumanPlayers(void);
const std::vector<WZFile>& NET_getDownloadingWzFiles();
void NET_addDownloadingWZFile(WZFile&& newFile);
void NET_clearDownloadingWZFiles();
bool NET_getLobbyDisabled();
const std::string& NET_getLobbyDisabledInfoLinkURL();
void NET_setLobbyDisabled(const std::string& infoLinkURL);
uint32_t NET_getCurrentHostedLobbyGameId();
// If a client, retrieve the current host's address
optional<std::string> NET_getCurrentHostTextAddress();
bool NETGameIsLocked();
void NETGameLocked(bool flag);
void NETresetGamePassword();
bool NETregisterServer(int state);
void NETsetPlayerConnectionStatus(CONNECTION_STATUS status, unsigned player); ///< Cumulative, except that CONNECTIONSTATUS_NORMAL resets.
bool NETcheckPlayerConnectionStatus(CONNECTION_STATUS status, unsigned player); ///< True iff connection status icon hasn't expired for this player. CONNECTIONSTATUS_NORMAL means any status, NET_ALL_PLAYERS means all players.
void NETsetAsyncJoinApprovalRequired(bool enabled);
bool NETgetAsyncJoinApprovalRequired();
enum class AsyncJoinApprovalAction
{
Approve,
ApproveSpectators,
Reject
};
// NOTE: *MUST* be called from the main thread!
bool NETsetAsyncJoinApprovalResult(const std::string& uniqueJoinID, AsyncJoinApprovalAction action, optional<uint8_t> explicitPlayerIdx, LOBBY_ERROR_TYPES rejectedReason = ERROR_NOERROR, optional<std::string> customRejectionMessage = nullopt);
const char *messageTypeToString(unsigned messageType);
/**
* This structure provides read-only access to a player, and can be used to identify players uniquely.
*
* It holds the player data after the player has disconnected, and it is released automatically by reference counting.
**/
struct PlayerReference
{
PlayerReference(uint32_t index): index(index)
{
}
void disconnect()
{
detached = std::make_unique<PLAYER>(NetPlay.players[index]);
detached->wzFiles = std::make_shared<std::vector<WZFile>>();
}
PLAYER const *operator ->() const
{
return detached? detached.get(): &NetPlay.players[index];
}
bool isHost() const
{
return index == NetPlay.hostPlayer;
}
bool isDetached() const
{
return detached != nullptr;
}
// Generally prefer to use the -> operator!
// (This is only safe if isDetached() == false !!)
uint32_t originalIndex() const
{
return index;
}
private:
std::unique_ptr<PLAYER> detached = nullptr;
uint32_t index;
};
void NETacceptIncomingConnections();
/// <summary>
/// Increase the connected timeout for all player connection objects when transitioning
/// from the lobby room to the main game loop.
///
/// Currently, this will set timeout value to 60 seconds, so that automatic lag-kick mechanism
/// would be able to close stalled connections.
/// </summary>
void NETadjustConnectedTimeoutForClients();
#endif
|