/*
Copyright (c) 2013 yvt
based on code of pysnip (c) Mathias Kaerlev 2011-2012.
This file is part of OpenSpades.
OpenSpades 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 3 of the License, or
(at your option) any later version.
OpenSpades 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 OpenSpades. If not, see .
*/
#pragma once
#include
#include
#include
#include
#include
#include
#include "PhysicsConstants.h"
#include "Player.h"
#include
#include
#include
#include
#include
#include
struct _ENetHost;
struct _ENetPeer;
typedef _ENetHost ENetHost;
typedef _ENetPeer ENetPeer;
namespace spades {
namespace client {
class Client;
class Player;
enum NetClientStatus {
NetClientStatusNotConnected = 0,
NetClientStatusConnecting,
NetClientStatusReceivingMap,
NetClientStatusConnected
};
enum NetExtensionType {
ExtensionType128Player = 192,
ExtensionTypeMessageTypes = 193,
ExtensionTypeKickReason = 194,
};
class World;
class NetPacketReader;
struct PlayerInput;
struct WeaponInput;
class Grenade;
struct GameProperties;
class GameMapLoader;
class NetClient {
Client *client;
NetClientStatus status;
ENetHost *host;
ENetPeer *peer;
std::string statusString;
class MapDownloadMonitor {
Stopwatch sw;
unsigned int numBytesDownloaded;
GameMapLoader &mapLoader;
bool receivedFirstByte;
public:
MapDownloadMonitor(GameMapLoader &);
void AccumulateBytes(unsigned int);
std::string GetDisplayedText();
};
/** Only valid in the `NetClientStatusReceivingMap` state */
std::unique_ptr mapLoader;
/** Only valid in the `NetClientStatusReceivingMap` state */
std::unique_ptr mapLoadMonitor;
std::shared_ptr properties;
int protocolVersion;
/** Extensions supported by both client and server (map of extension id → version) */
std::unordered_map extensions;
/** Extensions implemented in this client (map of extension id → version) */
std::unordered_map implementedExtensions{
{ExtensionType128Player, 1},
};
class BandwidthMonitor {
ENetHost *host;
Stopwatch sw;
double lastDown;
double lastUp;
public:
BandwidthMonitor(ENetHost *);
double GetDownlinkBps() { return lastDown * 8.; }
double GetUplinkBps() { return lastUp * 8.; }
void Update();
};
std::unique_ptr bandwidthMonitor;
std::vector savedPlayerPos;
std::vector savedPlayerFront;
std::vector savedPlayerTeam;
std::vector> savedPackets;
int timeToTryMapLoad;
bool tryMapLoadOnPacketType;
unsigned int lastPlayerInput;
unsigned int lastWeaponInput;
// used for some scripts including Arena by Yourself
IntVector3 temporaryPlayerBlockColor;
bool HandleHandshakePackets(NetPacketReader &);
void HandleExtensionPacket(NetPacketReader &);
void HandleGamePacket(NetPacketReader &);
stmp::optional GetWorld();
Player &GetPlayer(int);
stmp::optional GetPlayerOrNull(int);
Player &GetLocalPlayer();
stmp::optional GetLocalPlayerOrNull();
std::string DisconnectReasonString(uint32_t);
void MapLoaded();
void SendVersion();
void SendVersionEnhanced(const std::set &propertyIds);
void SendSupportedExtensions();
public:
NetClient(Client *);
~NetClient();
NetClientStatus GetStatus() { return status; }
std::string GetStatusString();
/**
* Gets how much portion of the map has completed loading.
* `GetStatus()` must be `NetClientStatusReceivingMap`.
*
* @return A value in range `[0, 1]`.
*/
float GetMapReceivingProgress();
/**
* Return a non-null reference to `GameProperties` for this connection.
* Must be the connected state.
*/
std::shared_ptr &GetGameProperties() {
SPAssert(properties);
return properties;
}
void Connect(const ServerAddress &hostname);
void Disconnect();
int GetPing();
void DoEvents(int timeout = 0);
void SendJoin(int team, WeaponType, std::string name, int kills);
void SendPosition();
void SendOrientation(Vector3);
void SendPlayerInput(PlayerInput);
void SendWeaponInput(WeaponInput);
void SendBlockAction(IntVector3, BlockActionType);
void SendBlockLine(IntVector3 v1, IntVector3 v2);
void SendReload();
void SendTool();
void SendGrenade(const Grenade &);
void SendHeldBlockColor();
void SendHit(int targetPlayerId, HitType type);
void SendChat(std::string, bool global);
void SendWeaponChange(WeaponType);
void SendTeamChange(int team);
void SendHandShakeValid(int challenge);
double GetDownlinkBps() { return bandwidthMonitor->GetDownlinkBps(); }
double GetUplinkBps() { return bandwidthMonitor->GetUplinkBps(); }
};
} // namespace client
} // namespace spades