Files
2026-02-02 04:50:13 +01:00

591 lines
16 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef SCUMM_HE_NET_MAIN_H
#define SCUMM_HE_NET_MAIN_H
#include "backends/networking/enet/enet.h"
#include "backends/networking/enet/host.h"
#include "backends/networking/enet/socket.h"
#include "common/formats/json.h"
namespace Scumm {
class ScummEngine_v90he;
class Net {
public:
Net(ScummEngine_v90he *vm);
~Net();
private:
/**
* An address structure which stores the host and port.
*/
struct Address {
Common::String host;
int port;
bool operator==(const Address &other) {
return host == other.host && port == other.port;
};
};
/**
* Structure for session storage.
*/
struct Session {
bool local = false; ///< Indicates if session is found over LAN.
int id = -1;
Common::String host;
int port = 0;
Common::String name;
int players = 0;
uint32 timestamp = 0;
// For Moonbase map generation:
uint8 mapGenerator = 0;
int mapSeed = 0;
int mapSize = 0;
int mapTileset = 0;
int mapEnergy = 0;
int mapTerrain = 0;
int mapWater = 0;
Common::String encodedMap;
// Used to query map data over LAN.
bool getGeneratedMap = false;
};
/**
* Converts a formatted string into an Address object.
*
* @param address A proper formatted string e.g. "127.0.0.1:9120", it may or may not contain a port number.
* @return Address
*/
Address getAddressFromString(Common::String address);
/**
* Converts an Address object into a formatted string.
*
* @param address An address object.
* @return Common::String
*/
Common::String getStringFromAddress(Address address);
public:
/**
* Creates a session and add ourselves as a user.
*
* @param sessionName Name if a session.
* @param userName User name to add.
* @retval 1 on success.
* @retval 0 on falure.
*/
int hostGame(char *sessionName, char *userName);
/**
* Joins a session with the speicified IP address and user name.
* This gets called when attempting to join a Moonbase Commander
* game with the --join-game command line param.
*
* @param IP IP Address to join
* @param userName Username to use.
* @retval 1 on success.
* @retval 0 on failure.
*/
int joinGame(Common::String IP, char *userName);
/**
* Adds a user to the session and assigns a user id.
*
* @param shortName Short username
* @param longName Long username.
* @retval 1 on success.
* @retval 0 on failure.
*/
int addUser(char *shortName, char *longName);
/**
* Remove ourselves if we have a user id for this session.
*
* @retval Always returns 1.
* @see destroyPlayer
*
*/
int removeUser();
/**
* Gets the user id who sent the previously received packet.
*
* @retval Last sent user id.
*/
int whoSentThis();
/**
* Gets our assigned user id.
*
* @retval Our user id.
*/
int whoAmI();
/**
* @brief Creates and host a network game session.
*
* @param name Session name
* @retval 1 on success.
* @retval 0 on failure.
*/
int createSession(char *name);
/**
* Join a session by their given index.
*
* @param sessionIndex Index of a session to join.
* @retval 1 on success.
* @retval 0 on falure.
*
* @note Use the QuerySessions methods to get sessions.
*/
int joinSession(int sessionIndex);
/**
* Join a session by their given id instead of index.
*
* @param sessionId ID of session to join
* @retval 1 on success.
* @retval 0 on falure.
*
* @note Use the QuerySessions methods to get sessions.
*/
int joinSessionById(int sessionId);
/**
* Checks if the queried session id exist.
*
* @param sessionId Session ID to search for.
* @retval 1 if found.
* @retval 0 if not found.
*/
int ifSessionExist(int sessionId);
/**
* Ends and closes an active game session.
*
* @retval Always returns 1
*/
int endSession();
/**
* Force a session server address to connect to when creating and joining sessions,
* overriding an existing configuration if any.
*
* @param sessionServer Address to a session server address.
* @note This will disable LAN hosting.
*/
void setSessionServer(Common::String sessionServer);
/**
* Disallows anymore players from joining our session.
*/
void disableSessionJoining();
/**
* Allows more players to join our session.
* @note Currently stubbed.
*
*/
void enableSessionJoining();
/**
* @brief Set AI Player count.
*
* @param botsCount Number of AI players currently created.
*/
void setBotsCount(int botsCount);
/**
* @brief Set and initializes the provider given by their name.
*
* @param parameter1 SCUMM string array providing the name of the provider.
* @param parameter2 SCUMM string array providing the optional paramater
*
* @retval 1 if successful
* @retval 0 on failure.
*
* @note Currently this will only initialize the ENet provider, regardless of name given.
*/
int32 setProviderByName(int32 parameter1, int32 parameter2);
/**
* @brief Sets the fake latency.
*
* @param time Fake latency time in milliseconds.
*/
void setFakeLatency(int time);
/**
* Destroys and remove an existing player.
*
* @param userId ID of player to remove.
* @retval true on removed
* @retval false on failure.
*/
bool destroyPlayer(int32 userId);
/**
* Setup and begin to query for active game sessions
*
* @param connectToSessionServer Indicates that it should connect to the session server for Internet-wide connections
* @retval 1 if ready
* @retval 0 if not.
* @see updateQuerySessions()
* @see stopQuerySessions()
*/
int32 startQuerySessions(bool connectToSessionServer = true);
/**
* Make a session query request and updates the session list.
*
* @return Number of sessions found.
*/
int32 updateQuerySessions();
/**
* Stops and shuts down querying for sessions.
* @note This will clear the sessions list.
*/
void stopQuerySessions();
/**
* Shortcut for querying sessions, calls startQuerySessions and returns updateQuerySessions.
*
* @return Number of sessions found.
*/
int querySessions();
/**
* Query aviliable providers.
*
* @return Always 1 currently.
*/
int queryProviders();
/**
* @brief Set the provider by the index.
*
* @param providerIndex index of a provider
* @retval 1 if successful
* @retval 0 on failure
*
* @note Currently stubbed.
*/
int setProvider(int providerIndex);
/**
* Close and shutsdown an active provider.
*
* @return Always returns 1.
*/
int closeProvider();
/**
* Initializes the provider, session, and adds user all at once.
*
* @retval true on success.
* @retval false on failure.
*
* @note Currently stubbed.
*/
bool initAll();
/**
* Initializes the ENet provider.
*
* @return true on success.
* @return false on failure.
*/
bool initProvider();
/**
* Initializes the session.
*
* @return true on success.
* @return false on failure.
*
* @note Currently stubbed.
*/
bool initSession();
/**
* Initializes the user.
*
* @return true on success.
* @return false on failure.
*
* @note Currently stubbed.
*/
bool initUser();
/**
* Sends a packet to a remote peer(s) which will call VAR_REMOTE_START_SCRIPT.
*
* @param typeOfSend A type of send this packet goes to, can be an indiviual peer, a group, host, or everybody.
* @param sendTypeParam A parameter for this type of send, e.g. for an indiviual send, this can be a user id of a peer to send to.
* @param priority Tells the provider to ensure that this packet has been sent and received.
* @param argsCount Number of args it should contain for the VAR_REMOTE_START_SCRIPT call.
* @param args The arguments themselves.
*/
void remoteStartScript(int typeOfSend, int sendTypeParam, int priority, int argsCount, int32 *args);
/**
* Sends an SCUMM array to a remote peer(s), calling VAR_NETWORK_RECEIVE_ARRAY_SCRIPT there.
*
* @param typeOfSend A type of send this packet goes to, can be an indiviual peer, a group, host, or everybody.
* @param sendTypeParam A parameter for this type of send, e.g. for an indiviual send, this can be a user id of a peer to send to.
* @param priority Tells the provider to ensure that this packet has been sent and received.
* @param arrayIndex An index pointing to an SCUMM array to pack and send with.
*/
void remoteSendArray(int typeOfSend, int sendTypeParam, int priority, int arrayIndex);
/**
* Sends a packet to a peer calling VAR_NETWORK_RECEIVE_ARRAY_SCRIPT, and it'll return its return value back to us.
*
* @param typeOfSend A type of send this packet goes to, can be an indiviual peer, a group, host, or everybody.
* @param sendTypeParam A parameter for this type of send, e.g. for an indiviual send, this can be a user id of a peer to send to.
* @param priority Tells the provider to ensure that this packet has been sent and received.
* @param defaultReturnValue The default return value to return in case of a time out.
* @param argsCount Number of args it should contain for the VAR_REMOTE_START_SCRIPT call.
* @param args The arguments themselves.
* @retval A peer's return value.
* @retval defaultReturnValue if timed out.
*
* @note This has been stubbed, as no game seems to use this.
*/
int remoteStartScriptFunction(int typeOfSend, int sendTypeParam, int priority, int defaultReturnValue, int argsCount, int32 *args);
/**
* A method that should be called once at the beginning of a game loop to send/receive network data.
*
* @param msecs milliseconds to service networks for.
*/
void doNetworkOnceAFrame(int msecs);
private:
/**
* Attempt to connect to a game session with its address and port.
*
* @param address Address of a session to connect to.
* @param port Port number of a session to connect to.
* @param queryGeneratedMap Querys generated map data for Moonbase Commander (currently only used for LAN connections).
* @retval true on success
* @retval false on failure.
*
* @see joinGame
* @see doJoinSession
*/
bool connectToSession(Common::String address, int port, bool queryGeneratedMap);
/**
* Method that actually attemps to join a session.
*
* @param session Session structure to join to.
* @retval 1 on success
* @retval 0 on failure.
*
* @see joinSession
* @see joinSessionById
*/
int doJoinSession(Session session);
/**
* Generates a Moonbase Commander map based on the provided
* Session's configurations.
*
* @param session Session structure containing map data.
*/
void generateMoonbaseMap(Session session);
/**
* Sends remote data to peer(s).
*
* @param typeOfSend A type of send this packet goes to, can be an indiviual peer, a group, host, or everybody.
* @param sendTypeParam A parameter for this type of send, e.g. for an indiviual send, this can be a user id of a peer to send to.
* @param type Type of packet.
* @param data Data of contain in the packet.
* @param priority Tells the provider to ensure that this packet has been sent and received.
* @param defaultRes Default return value (0 by default)
* @param wait Wait for return value (Not currently being used).
* @param callid Call ID of this packet send. (Not currently being used).
* @return Always the default return value currently.
*/
int remoteSendData(int typeOfSend, int sendTypeParam, int type, Common::String data, int priority, int defaultRes = 0, bool wait = false, int callid = 0);
/**
* Services the broadcast (LAN) socket.
*
* @return true
* @return false
*/
bool serviceBroadcast();
/**
* Handles the data received from the broadcast (LAN) socket.
*
* @param data Data received.
* @param host Host name who sent the data.
* @param port Port number who sent the data.
*/
void handleBroadcastData(Common::String data, Common::String host, int port);
/**
* Servies the connection to the session server.
*/
void serviceSessionServer();
/**
* Handles data received from the session server.
*
* @param data Data received.
*/
void handleSessionServerData(Common::String data);
/**
* Service sesssion host.
*/
void remoteReceiveData();
/**
* Handle game data received from session host.
*
* @param json JSON object containing game data.
* @param peerIndex Index of a peer who sent this data.
*/
void handleGameData(Common::JSONValue *json, int peerIndex);
/**
* Handle game data received and transfer to peers if needed.
*
* @param json JSON object containing game data.
* @param peerIndex Index of a peer who sent this data.
*
* @see handleGameData
*/
void handleGameDataHost(Common::JSONValue *json, int peerIndex);
public:
// getters
/**
* Gets the host name of the local machine.
*
* @param hostname Pointer to store the host name to.
* @param length The length of the pointer.
* @retval true on successful .
* @retval false on failure.
*
* @note This is currently subbed.
*/
bool getHostName(char *hostname, int length);
/**
* Gets the IP address of the given local host name.
*
* @param ip Pointer to store the address to.
* @param ipLength The length of the pointer.
* @param nameBuffer the Host name itself.
* @retval true on successful .
* @retval false on failure..
*
* @note This is currently subbed.
*/
bool getIPfromName(char *ip, int ipLength, char *nameBuffer);
/**
* Get the session name from the session index.
*
* @param sessionNumber The session's index.
* @param buffer A buffer to store the name to.
* @param length Maximum length of the buffer.
*/
void getSessionName(int sessionNumber, char *buffer, int length);
/**
* Get the session's player count.
*
* @param sessionNumber The session's index.
* @return Player count.
*/
int getSessionPlayerCount(int sessionNumber);
/**
* @brief Get the name of a provider of the given index.
*
* @param providerIndex The provider's index.
* @param buffer A buffer to store the name to.
* @param length Maximum length of the buffer.
*/
void getProviderName(int providerIndex, char *buffer, int length);
private:
// mostly getters
/**
* @brief Get total players joined in the session, including AI players.
*
* @return Player count.
*/
int getTotalPlayers();
public:
// fields
int _latencyTime; // ms
bool _fakeLatency;
bool _isHost; // true = hosting game, false = joined game.
int _myUserId;
int _fromUserId;
int _sessionId; // Session ID received from the session server.
private:
ScummEngine_v90he *_vm;
Common::String _gameName;
Common::String _gameVersion;
Networking::ENet::ENet *_enet;
byte *_tmpbuffer;
int _numUsers;
int _numBots;
int _maxPlayers;
int _userIdCounter;
Common::HashMap<int, Common::String> _userIdToName;
Common::HashMap<int, int> _userIdToPeerIndex;
Common::HashMap<int, Common::String> _userIdToAddress;
Common::HashMap<Common::String, int> _addressToUserId;
Common::String _sessionName;
Networking::ENet::Host *_sessionHost;
// For Moonbase map generation:
uint8 _mapGenerator;
int _mapSeed;
int _mapSize;
int _mapTileset;
int _mapEnergy;
int _mapTerrain;
int _mapWater;
Common::String _encodedMap;
bool _isShuttingDown;
Common::Queue<Common::JSONValue *> _hostDataQueue;
Common::Queue<int> _peerIndexQueue;
Common::Array<Session> _sessions;
int _hostPort;
// For broadcasting our game session over LAN.
Networking::ENet::Socket *_broadcastSocket;
// For creating/joining sessions over the Internet.
Networking::ENet::Host *_sessionServerHost;
Address _sessionServerAddress;
bool _forcedAddress;
bool _gotSessions;
int _sessionServerPeer;
bool _isRelayingGame; ///< If we're relaying in-game data over the session server or not.
};
} // End of namespace Scumm
#endif