/* 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