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,
87#ifdef SILENCE_GCC_FUNCTION_POINTER_CAST
97# pragma GCC diagnostic push
98# pragma GCC diagnostic ignored "-Wcast-function-type"
103inline constexpr size_t _callback_tuple_size = std::tuple_size_v<
decltype(
_callback_tuple)>;
105template <
size_t... i>
106inline auto MakeCallbackTable(std::index_sequence<i...>)
noexcept
112static const auto _callback_table = MakeCallbackTable(std::make_index_sequence<_callback_tuple_size>{});
115template <
typename... Targs>
117 using Args = std::tuple<std::decay_t<Targs>...>;
125template <Commands Tcmd>
static void NetworkReplaceCommandClientId(
CommandPacket &cp,
ClientID client_id);
126using UnpackNetworkCommandProc = void (*)(
const CommandPacket &);
127using UnpackDispatchT = std::array<UnpackNetworkCommandProc, _callback_tuple_size>;
131 UnpackDispatchT Unpack;
134template <Commands Tcmd,
size_t Tcb>
135constexpr UnpackNetworkCommandProc MakeUnpackNetworkCommandCallback() noexcept
138 using Tcallback = std::tuple_element_t<Tcb,
decltype(
_callback_tuple)>;
139 if constexpr (std::is_same_v<Tcallback, CommandCallback * const> ||
140 std::is_same_v<Tcallback, CommandCallbackData * const> ||
142 (!std::is_void_v<typename CommandTraits<Tcmd>::RetTypes> && std::is_same_v<typename CallbackArgsHelper<typename CommandTraits<Tcmd>::RetCallbackProc
const>::Args,
typename CallbackArgsHelper<Tcallback>::Args>)) {
143 return &UnpackNetworkCommand<Tcmd, Tcb>;
149template <
Commands Tcmd,
size_t... i>
150constexpr UnpackDispatchT MakeUnpackNetworkCommand(std::index_sequence<i...>)
noexcept
152 return UnpackDispatchT{{ MakeUnpackNetworkCommandCallback<Tcmd, i>()...}};
155template <
typename T, T... i,
size_t... j>
156inline constexpr auto MakeDispatchTable(std::integer_sequence<T, i...>, std::index_sequence<j...>)
noexcept
158 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>{}) }... }};
161static constexpr auto _cmd_dispatch = MakeDispatchTable(std::make_integer_sequence<std::underlying_type_t<Commands>,
CMD_END>{}, std::make_index_sequence<_callback_tuple_size>{});
163#ifdef SILENCE_GCC_FUNCTION_POINTER_CAST
164# pragma GCC diagnostic pop
181 return static_cast<size_t>(std::distance(std::begin(
_callback_table), it));
184 return std::numeric_limits<size_t>::max();
250 auto cp = queue.begin();
251 for (; cp != queue.end(); cp++) {
254 if (_frame_counter < cp->frame)
break;
259 FatalError(
"[net] Trying to execute a packet in the past!");
265 assert(cb_index < _callback_tuple_size);
269 queue.erase(queue.begin(), cp);
40#include "../station_cmd.h" {
…}
294 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
295 if (cs->status >= NetworkClientSocket::STATUS_MAP) {
298 cp.
callback = (cs != owner) ?
nullptr : callback;
299 cp.
my_cmd = (cs == owner);
300 cs->outgoing_queue.push_back(cp);
304 cp.
callback = (
nullptr != owner) ?
nullptr : callback;
305 cp.
my_cmd = (
nullptr == owner);
316#ifdef DEBUG_DUMP_COMMANDS
318 int to_go = UINT16_MAX;
321 if (owner ==
nullptr) {
328 for (
auto cp = queue.begin(); cp != queue.end(); ) {
336 if (--to_go < 0)
break;
340 cp = queue.erase(cp);
351 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
391 if (callback > UINT8_MAX ||
_cmd_dispatch[cp.
cmd].Unpack[callback] ==
nullptr) {
392 Debug(net, 0,
"Unknown callback for command; no callback sent (command: {})", cp.
cmd);
402 if constexpr (std::is_same_v<ClientID, T>) {
408template <
class Ttuple,
size_t... Tindices>
414template <Commands Tcmd>
418 auto params = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(cp.
data);
421 SetClientIds(params, client_id, std::make_index_sequence<std::tuple_size_v<
decltype(params)>>{});
442 if constexpr (std::is_same_v<std::string, T>) {
452template <
class Ttuple,
size_t... Tindices>
464template <Commands Tcmd>
467 auto args = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(data);
478template <Commands Tcmd,
size_t Tcb>
481 auto args = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(cp.
data);
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.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
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.
std::optional< std::string_view > ReceiveCommand(Packet &p, CommandPacket &cp)
Receives a command from the network.
CommandQueue incoming_queue
The command-queue awaiting handling.
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.
@ Offline
the command cannot be executed in a multiplayer game; single-player only
@ StrCtrl
the command's string may contain control strings
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)
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?
#define Debug(category, level, format_string,...)
Output 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.
PauseModes _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.
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 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.
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 const auto _callback_table
Type-erased table of callbacks.
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 void SetClientIdHelper(T &data, ClientID client_id)
Helper to process a single ClientID argument.
static void SanitizeSingleStringHelper(CommandFlags cmd_flags, T &data)
Validate a single string argument coming from network.
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.
void NetworkSyncCommandQueue(NetworkClientSocket *cs)
Sync our local command queue to the command queue of the given socket.
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
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.
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.
void StrMakeValidInPlace(char *str, StringValidationSettings settings)
Scans the string for invalid characters and replaces them with a question mark '?' (if not ignored).
@ ReplaceWithQuestionMark
Replace the unknown/bad bits with question marks.
@ AllowControlCode
Allow the special control codes.
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, CargoType, 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 cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16_t, CargoArray)
This is the Callback method after the construction attempt of a primary vehicle.