10 #include "../stdafx.h"
14 #include "../command_func.h"
15 #include "../company_func.h"
16 #include "../settings_type.h"
17 #include "../airport_cmd.h"
18 #include "../aircraft_cmd.h"
19 #include "../autoreplace_cmd.h"
20 #include "../company_cmd.h"
21 #include "../depot_cmd.h"
22 #include "../dock_cmd.h"
23 #include "../economy_cmd.h"
24 #include "../engine_cmd.h"
25 #include "../error_func.h"
26 #include "../goal_cmd.h"
27 #include "../group_cmd.h"
28 #include "../industry_cmd.h"
29 #include "../landscape_cmd.h"
30 #include "../league_cmd.h"
31 #include "../misc_cmd.h"
32 #include "../news_cmd.h"
33 #include "../object_cmd.h"
34 #include "../order_cmd.h"
35 #include "../rail_cmd.h"
36 #include "../road_cmd.h"
37 #include "../roadveh_cmd.h"
38 #include "../settings_cmd.h"
39 #include "../signs_cmd.h"
40 #include "../station_cmd.h"
41 #include "../story_cmd.h"
42 #include "../subsidy_cmd.h"
43 #include "../terraform_cmd.h"
44 #include "../timetable_cmd.h"
45 #include "../town_cmd.h"
46 #include "../train_cmd.h"
47 #include "../tree_cmd.h"
48 #include "../tunnelbridge_cmd.h"
49 #include "../vehicle_cmd.h"
50 #include "../viewport_cmd.h"
51 #include "../water_cmd.h"
52 #include "../waypoint_cmd.h"
53 #include "../script/script_cmd.h"
55 #include "../safeguards.h"
63 &CcPlaySound_CONSTRUCTION_WATER,
72 &CcPlaySound_EXPLOSION,
73 &CcPlaySound_CONSTRUCTION_OTHER,
74 &CcPlaySound_CONSTRUCTION_RAIL,
88 #ifdef SILENCE_GCC_FUNCTION_POINTER_CAST
98 # pragma GCC diagnostic push
99 # pragma GCC diagnostic ignored "-Wcast-function-type"
104 inline constexpr
size_t _callback_tuple_size = std::tuple_size_v<decltype(
_callback_tuple)>;
106 template <
size_t... i>
107 inline auto MakeCallbackTable(std::index_sequence<i...>) noexcept
113 static auto _callback_table = MakeCallbackTable(std::make_index_sequence<_callback_tuple_size>{});
116 template <
typename... Targs>
118 using Args = std::tuple<std::decay_t<Targs>...>;
127 using UnpackNetworkCommandProc = void (*)(
const CommandPacket &);
128 using UnpackDispatchT = std::array<UnpackNetworkCommandProc, _callback_tuple_size>;
132 UnpackDispatchT Unpack;
135 template <Commands Tcmd,
size_t Tcb>
136 constexpr UnpackNetworkCommandProc MakeUnpackNetworkCommandCallback() noexcept
139 using Tcallback = std::tuple_element_t<Tcb, decltype(
_callback_tuple)>;
140 if constexpr (std::is_same_v<Tcallback, CommandCallback * const> ||
141 std::is_same_v<Tcallback, CommandCallbackData * const> ||
144 return &UnpackNetworkCommand<Tcmd, Tcb>;
150 template <
Commands Tcmd,
size_t... i>
151 constexpr UnpackDispatchT MakeUnpackNetworkCommand(std::index_sequence<i...>) noexcept
153 return UnpackDispatchT{{ MakeUnpackNetworkCommandCallback<Tcmd, i>()...}};
156 template <
typename T, T... i,
size_t... j>
157 inline constexpr
auto MakeDispatchTable(std::integer_sequence<T, i...>, std::index_sequence<j...>) noexcept
159 return std::array<
CommandDispatch,
sizeof...(i)>{{ { &SanitizeCmdStrings<static_cast<Commands>(i)>, &NetworkReplaceCommandClientId<static_cast<Commands>(i)>, MakeUnpackNetworkCommand<static_cast<Commands>(i)>(std::make_index_sequence<_callback_tuple_size>{}) }... }};
162 static constexpr
auto _cmd_dispatch = MakeDispatchTable(std::make_integer_sequence<std::underlying_type_t<Commands>,
CMD_END>{}, std::make_index_sequence<_callback_tuple_size>{});
164 #ifdef SILENCE_GCC_FUNCTION_POINTER_CAST
165 # pragma GCC diagnostic pop
182 return static_cast<size_t>(std::distance(std::cbegin(
_callback_table), it));
185 return std::numeric_limits<size_t>::max();
251 auto cp = queue.begin();
252 for (; cp != queue.end(); cp++) {
255 if (_frame_counter < cp->frame)
break;
260 FatalError(
"[net] Trying to execute a packet in the past!");
266 assert(cb_index < _callback_tuple_size);
270 queue.erase(queue.begin(), cp);
295 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
296 if (cs->status >= NetworkClientSocket::STATUS_MAP) {
299 cp.
callback = (cs != owner) ?
nullptr : callback;
300 cp.
my_cmd = (cs == owner);
301 cs->outgoing_queue.push_back(cp);
305 cp.
callback = (
nullptr != owner) ?
nullptr : callback;
306 cp.
my_cmd = (
nullptr == owner);
317 #ifdef DEBUG_DUMP_COMMANDS
319 int to_go = UINT16_MAX;
322 if (owner ==
nullptr) {
329 for (
auto cp = queue.begin(); cp != queue.end(); ) {
337 if (--to_go < 0)
break;
341 cp = queue.erase(cp);
352 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
392 if (callback > UINT8_MAX ||
_cmd_dispatch[cp.
cmd].Unpack[callback] ==
nullptr) {
393 Debug(net, 0,
"Unknown callback for command; no callback sent (command: {})", cp.
cmd);
403 if constexpr (std::is_same_v<ClientID, T>) {
409 template<
class Ttuple,
size_t... Tindices>
415 template <Commands Tcmd>
419 auto params = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(cp.
data);
422 SetClientIds(params, client_id, std::make_index_sequence<std::tuple_size_v<decltype(params)>>{});
443 if constexpr (std::is_same_v<std::string, T>) {
449 template<
class Ttuple,
size_t... Tindices>
461 template <Commands Tcmd>
464 auto args = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(data);
475 template <Commands Tcmd,
size_t Tcb>
478 auto args = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(cp.
data);
void CcAI(Commands cmd, const CommandCost &result, const CommandDataBuffer &data, CommandDataBuffer result_data)
DoCommand callback function for all commands executed by AIs.
void CcBuildBridge(Commands, const CommandCost &result, TileIndex end_tile, TileIndex tile_start, TransportType transport_type, BridgeType, uint8_t)
Callback executed after a build Bridge CMD has been called.
static ClientNetworkGameSocketHandler * my_client
This is us!
static NetworkRecvStatus SendCommand(const CommandPacket &cp)
Send a command to the server.
Common return value for all commands.
Endian-aware buffer adapter that always writes values in little endian order.
CommandQueue incoming_queue
The command-queue awaiting handling.
const char * ReceiveCommand(Packet &p, CommandPacket &cp)
Receives a command from the network.
void SendCommand(Packet &p, const CommandPacket &cp)
Sends a command over the network.
CommandFlags GetCommandFlags(Commands cmd)
This function mask the parameter with CMD_ID_MASK and returns the flags which belongs to the given co...
bool IsCommandAllowedWhilePaused(Commands cmd)
Returns whether the command is allowed while the game is paused.
bool IsValidCommand(Commands cmd)
This function range-checks a cmd.
void CommandCallback(Commands cmd, const CommandCost &result, TileIndex tile)
Define a callback function for the client, after the command is finished.
std::vector< uint8_t > CommandDataBuffer
Storage buffer for serialized command data.
Commands
List of commands.
@ CMD_END
Must ALWAYS be on the end of this list!! (period)
CommandFlags
Command flags for the command table _command_proc_table.
@ CMD_STR_CTRL
the command's string may contain control strings
@ CMD_OFFLINE
the command cannot be executed in a multiplayer game; single-player only
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
CompanyID _current_company
Company currently doing an action.
bool IsLocalCompany()
Is the current company the local company?
Owner
Enum for all companies/owners.
static const uint NETWORK_COMPANY_NAME_LENGTH
The maximum length of the company name, in bytes including '\0'.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
void CcCloneVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id)
This is the Callback method after the cloning attempt of a vehicle.
void CcGame(Commands cmd, const CommandCost &result, const CommandDataBuffer &data, CommandDataBuffer result_data)
DoCommand callback function for all commands executed by Game Scripts.
PauseMode _pause_mode
The current pause mode.
void CcCreateGroup(Commands cmd, const CommandCost &result, GroupID new_group, VehicleType vt, GroupID parent_group)
Opens a 'Rename group' window for newly created group.
void CcAddVehicleNewGroup(Commands cmd, const CommandCost &result, GroupID new_group, GroupID, VehicleID veh_id, bool, const VehicleListIdentifier &)
Open rename window after adding a vehicle to a new group via drag and drop.
void CcBuildIndustry(Commands cmd, const CommandCost &result, TileIndex tile, IndustryType indtype, uint32_t, bool, uint32_t)
Command callback.
uint32_t _frame_counter
The current frame.
bool _network_server
network-server is active
uint32_t _frame_counter_max
To where we may go with our clients.
void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket &cp)
Distribute CommandPacket details over the admin network for logging purposes.
Server part of the admin network protocol.
Client part of the network protocol.
static void SetClientIdHelper(T &data, [[maybe_unused]] ClientID client_id)
Helper to process a single ClientID argument.
static void SanitizeStringsHelper(CommandFlags cmd_flags, Ttuple &values, std::index_sequence< Tindices... >)
Helper function to perform validation on command data strings.
static constexpr auto _callback_tuple
Typed list of all possible callbacks.
static void SanitizeSingleStringHelper([[maybe_unused]] CommandFlags cmd_flags, T &data)
Validate a single string argument coming from network.
void NetworkFreeLocalCommandQueue()
Free the local command queues.
static void SetClientIds(Ttuple &values, ClientID client_id, std::index_sequence< Tindices... >)
Set all invalid ClientID's to the proper value.
static size_t FindCallbackIndex(CommandCallback *callback)
Find the callback index of a callback pointer.
void NetworkExecuteLocalCommandQueue()
Execute all commands on the local command queue that ought to be executed this frame.
void NetworkDistributeCommands()
Distribute the commands of ourself and the clients.
static CommandQueue _local_wait_queue
Local queue of packets waiting for handling.
static CommandQueue _local_execution_queue
Local queue of packets waiting for execution.
static void DistributeCommandPacket(CommandPacket &cp, const NetworkClientSocket *owner)
"Send" a particular CommandPacket to all clients.
static auto _callback_table
Type-erased table of callbacks.
void NetworkSyncCommandQueue(NetworkClientSocket *cs)
Sync our local command queue to the command queue of the given socket.
static void NetworkReplaceCommandClientId(CommandPacket &cp, ClientID client_id)
Insert a client ID into the command data in a command packet.
static void UnpackNetworkCommand(const CommandPacket &cp)
Unpack a generic command packet into its actual typed components.
static void DistributeQueue(CommandQueue &queue, const NetworkClientSocket *owner)
"Send" a particular CommandQueue to all clients.
void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, const CommandDataBuffer &cmd_data)
Prepare a DoCommand to be send over the network.
static CommandDataBuffer SanitizeCmdStrings(const CommandDataBuffer &data)
Validate and sanitize strings in command data.
static constexpr auto _cmd_dispatch
Command dispatch table.
Server part of the network protocol.
ClientID
'Unique' identifier to be given to clients
@ PM_UNPAUSED
A normal unpaused game.
void CcBuildRailTunnel(Commands, const CommandCost &result, TileIndex tile)
Command callback for building a tunnel.
void CcRoadStop(Commands cmd, const CommandCost &result, TileIndex tile, uint8_t width, uint8_t length, RoadStopType, bool is_drive_through, DiagDirection dir, RoadType, RoadStopClassID spec_class, uint16_t spec_index, StationID, bool)
Command callback for building road stops.
void CcBuildRoadTunnel(Commands, const CommandCost &result, TileIndex start_tile)
Callback executed after a build road tunnel command has been called.
ClientSettings _settings_client
The current settings for this game.
void CcPlaceSign(Commands, const CommandCost &result, SignID new_sign)
Callback function that is called after a sign is placed.
static void StrMakeValid(T &dst, const char *str, const char *last, StringValidationSettings settings)
Copies the valid (UTF-8) characters from str up to last to the dst.
@ SVS_ALLOW_CONTROL_CODE
Allow the special control codes.
@ SVS_REPLACE_WITH_QUESTION_MARK
Replace the unknown/bad bits with question marks.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
NetworkSettings network
settings related to the network
Everything we need to know about a command to be able to execute it.
StringID err_msg
string ID of error message to use.
CommandDataBuffer data
command parameters.
CommandCallback * callback
any callback function executed upon successful completion of the command.
uint32_t frame
the frame in which this packet is executed
CompanyID company
company that is executing the command
bool my_cmd
did the command originate from "me"
Commands cmd
command being executed.
Defines the traits of a command.
uint16_t commands_per_frame
how many commands may be sent each frame_freq frames?
uint16_t commands_per_frame_server
how many commands may be sent each frame_freq frames? (server-originating commands)
Internal entity of a packet.
uint16_t Recv_uint16()
Read a 16 bits integer from the packet.
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
void Send_uint8(uint8_t data)
Package a 8 bits integer in the packet.
void Send_buffer(const std::vector< uint8_t > &data)
Copy a sized byte buffer into the packet.
std::vector< uint8_t > Recv_buffer()
Extract a sized byte buffer from the packet.
void Send_uint16(uint16_t data)
Package a 16 bits integer in the packet.
std::vector< CommandPacket > CommandQueue
A "queue" of CommandPackets.
void CcBuildWagon(Commands cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16_t, CargoArray, TileIndex tile, EngineID, bool, CargoID, ClientID)
Callback for building wagons.
void CcStartStopVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id, bool)
This is the Callback method after attempting to start/stop a vehicle.
void CcBuildPrimaryVehicle(Commands, const CommandCost &result, VehicleID new_veh_id, uint, uint16_t, CargoArray)
This is the Callback method after the construction attempt of a primary vehicle.