|
OpenTTD Source
13.0-beta2
|
Go to the documentation of this file.
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 "../goal_cmd.h"
26 #include "../group_cmd.h"
27 #include "../industry_cmd.h"
28 #include "../landscape_cmd.h"
29 #include "../league_cmd.h"
30 #include "../misc_cmd.h"
31 #include "../news_cmd.h"
32 #include "../object_cmd.h"
33 #include "../order_cmd.h"
34 #include "../rail_cmd.h"
35 #include "../road_cmd.h"
36 #include "../roadveh_cmd.h"
37 #include "../settings_cmd.h"
38 #include "../signs_cmd.h"
39 #include "../station_cmd.h"
40 #include "../story_cmd.h"
41 #include "../subsidy_cmd.h"
42 #include "../terraform_cmd.h"
43 #include "../timetable_cmd.h"
44 #include "../town_cmd.h"
45 #include "../train_cmd.h"
46 #include "../tree_cmd.h"
47 #include "../tunnelbridge_cmd.h"
48 #include "../vehicle_cmd.h"
49 #include "../viewport_cmd.h"
50 #include "../water_cmd.h"
51 #include "../waypoint_cmd.h"
52 #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
179 if (this->
first ==
nullptr) {
205 if (ret !=
nullptr) {
206 if (ret == this->
last) this->
last = prev_item;
232 while ((cp = this->
Pop()) !=
nullptr) {
235 assert(this->
count == 0);
252 return static_cast<size_t>(std::distance(std::cbegin(
_callback_table), it));
255 return std::numeric_limits<size_t>::max();
311 cs->outgoing_queue.Append(&c);
325 while ((cp = queue.
Peek()) !=
nullptr) {
328 if (_frame_counter < cp->frame)
break;
333 error(
"[net] Trying to execute a packet in the past!");
339 assert(cb_index < _callback_tuple_size);
370 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
371 if (cs->status >= NetworkClientSocket::STATUS_MAP) {
374 cp.
callback = (cs != owner) ?
nullptr : callback;
375 cp.
my_cmd = (cs == owner);
376 cs->outgoing_queue.Append(&cp);
380 cp.
callback = (
nullptr != owner) ?
nullptr : callback;
381 cp.
my_cmd = (
nullptr == owner);
392 #ifdef DEBUG_DUMP_COMMANDS
394 int to_go = UINT16_MAX;
400 while (--to_go >= 0 && (cp = queue->
Pop(
true)) !=
nullptr) {
414 for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
456 if (callback > UINT8_MAX ||
_cmd_dispatch[cp->
cmd].Unpack[callback] ==
nullptr) {
457 Debug(net, 0,
"Unknown callback for command; no callback sent (command: {})", cp->
cmd);
467 if constexpr (std::is_same_v<ClientID, T>) {
473 template<
class Ttuple,
size_t... Tindices>
479 template <Commands Tcmd>
483 auto params = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(cp.
data);
486 SetClientIds(params, client_id, std::make_index_sequence<std::tuple_size_v<decltype(params)>>{});
507 if constexpr (std::is_same_v<std::string, T>) {
513 template<
class Ttuple,
size_t... Tindices>
525 template <Commands Tcmd>
528 auto args = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(data);
539 template <Commands Tcmd,
size_t Tcb>
542 auto args = EndianBufferReader::ToValue<typename CommandTraits<Tcmd>::Args>(cp->
data);
CommandPacket * last
The last packet in the queue; only valid when first != nullptr.
static void SetClientIdHelper(T &data, [[maybe_unused]] ClientID client_id)
Helper to process a single ClientID argument.
uint32 _frame_counter
The current frame.
static CommandQueue _local_wait_queue
Local queue of packets waiting for handling.
static constexpr auto _cmd_dispatch
Command dispatch table.
Commands
List of commands.
static void SanitizeStringsHelper(CommandFlags cmd_flags, Ttuple &values, std::index_sequence< Tindices... >)
Helper function to perform validation on command data strings.
std::vector< byte > CommandDataBuffer
Storage buffer for serialized command data.
TileIndex tile
location of the command (for e.g. error message or effect display).
@ CMD_OFFLINE
the command cannot be executed in a multiplayer game; single-player only
CommandFlags GetCommandFlags(Commands cmd)
bool _network_server
network-server is active
void CcRoadStop(Commands cmd, const CommandCost &result, TileIndex tile, uint8 width, uint8 length, RoadStopType, bool is_drive_through, DiagDirection dir, RoadType, StationID, bool)
Command callback for building road stops.
uint32 frame
the frame in which this packet is executed
static CommandQueue _local_execution_queue
Local queue of packets waiting for execution.
void NetworkSendCommand(Commands cmd, StringID err_message, CommandCallback *callback, CompanyID company, TileIndex location, 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 void SanitizeSingleStringHelper([[maybe_unused]] CommandFlags cmd_flags, T &data)
Validate a single string argument coming from network.
StringID err_msg
string ID of error message to use.
static void UnpackNetworkCommand(const CommandPacket *cp)
Unpack a generic command packet into its actual typed components.
ClientSettings _settings_client
The current settings for this game.
void NetworkSyncCommandQueue(NetworkClientSocket *cs)
Sync our local command queue to the command queue of the given socket.
void CommandCallback(Commands cmd, const CommandCost &result, TileIndex tile)
Define a callback function for the client, after the command is finished.
static ClientNetworkGameSocketHandler * my_client
This is us!
CommandPacket * next
the next command packet (if in queue)
static void DistributeCommandPacket(CommandPacket &cp, const NetworkClientSocket *owner)
"Send" a particular CommandPacket to all clients.
Owner
Enum for all companies/owners.
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
static auto _callback_table
Type-erased table of callbacks.
static bool IsLocalCompany()
Is the current company the local company?
Defines the traits of a command.
uint32 _frame_counter_max
To where we may go with our clients.
static void NetworkReplaceCommandClientId(CommandPacket &cp, ClientID client_id)
Insert a client ID into the command data in a command packet.
@ CMD_END
Must ALWAYS be on the end of this list!! (period)
void Send_uint32(uint32 data)
Package a 32 bits integer in the packet.
@ PM_UNPAUSED
A normal unpaused game.
void Append(CommandPacket *p)
Append a CommandPacket at the end of the queue.
CompanyID company
company that is executing the command
@ SVS_ALLOW_CONTROL_CODE
Allow the special control codes.
CommandFlags
Command flags for the command table _command_proc_table.
uint32 Recv_uint32()
Read a 32 bits integer from the packet.
Common return value for all commands.
Everything we need to know about a command to be able to execute it.
void CcStartStopVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id, bool)
This is the Callback method after attempting to start/stop a vehicle.
ClientID
'Unique' identifier to be given to clients
void Send_buffer(const std::vector< byte > &data)
Copy a sized byte buffer into the packet.
PauseMode _pause_mode
The current pause mode.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
void Send_uint16(uint16 data)
Package a 16 bits integer in the packet.
A queue of CommandPackets.
static size_t FindCallbackIndex(CommandCallback *callback)
Find the callback index of a callback pointer.
bool my_cmd
did the command originate from "me"
std::vector< byte > Recv_buffer()
Extract a sized byte buffer from the packet.
Internal entity of a packet.
const char * ReceiveCommand(Packet *p, CommandPacket *cp)
Receives a command from the network.
CommandPacket * first
The first packet in the queue.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
CompanyID _current_company
Company currently doing an action.
std::string StrMakeValid(const std::string &str, StringValidationSettings settings)
Scans the string for invalid characters and replaces then with a question mark '?' (if not ignored).
bool IsValidCommand(Commands cmd)
static NetworkRecvStatus SendCommand(const CommandPacket *cp)
Send a command to the server.
void Free()
Free everything that is in the queue.
CommandDataBuffer data
command parameters.
void CcAI(Commands cmd, const CommandCost &result, TileIndex tile, const CommandDataBuffer &data, CommandDataBuffer result_data)
DoCommand callback function for all commands executed by AIs.
void CcBuildPrimaryVehicle(Commands cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16)
This is the Callback method after the construction attempt of a primary vehicle.
uint count
The number of items in the queue.
void CcCloneVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id)
This is the Callback method after the cloning attempt of a vehicle.
bool IsCommandAllowedWhilePaused(Commands cmd)
Returns whether the command is allowed while the game is paused.
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
void CcBuildRoadTunnel(Commands cmd, const CommandCost &result, TileIndex start_tile)
Callback executed after a build road tunnel command has been called.
CommandQueue incoming_queue
The command-queue awaiting handling.
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
uint16 commands_per_frame
how many commands may be sent each frame_freq frames?
CommandPacket * Peek(bool ignore_paused=false)
Return the first item in the queue, but don't remove it.
void CcBuildIndustry(Commands cmd, const CommandCost &result, TileIndex tile, IndustryType indtype, uint32, bool, uint32)
Command callback.
void CcBuildBridge(Commands cmd, const CommandCost &result, TileIndex end_tile, TileIndex tile_start, TransportType transport_type, BridgeType, byte)
Callback executed after a build Bridge CMD has been called.
void CcAddVehicleNewGroup(Commands cmd, const CommandCost &result, GroupID new_group, GroupID, VehicleID veh_id, bool)
Open rename window after adding a vehicle to a new group via drag and drop.
#define Debug(name, level, format_string,...)
Ouptut a line of debugging information.
NetworkSettings network
settings related to the network
void CcGame(Commands cmd, const CommandCost &result, TileIndex tile, const CommandDataBuffer &data, CommandDataBuffer result_data)
DoCommand callback function for all commands executed by Game Scripts.
Endian-aware buffer adapter that always writes values in little endian order.
void SendCommand(Packet *p, const CommandPacket *cp)
Sends a command over the network.
void CcBuildWagon(Commands cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16, TileIndex tile, EngineID, bool, CargoID, ClientID)
Callback for building wagons.
void NetworkExecuteLocalCommandQueue()
Execute all commands on the local command queue that ought to be executed this frame.
void CcBuildRailTunnel(Commands cmd, const CommandCost &result, TileIndex tile)
Command callback for building a tunnel.
static constexpr auto _callback_tuple
Typed list of all possible callbacks.
void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket *cp)
Distribute CommandPacket details over the admin network for logging purposes.
@ CMD_STR_CTRL
the command's string may contain control strings
CommandCallback * callback
any callback function executed upon successful completion of the command.
void NetworkFreeLocalCommandQueue()
Free the local command queues.
@ SVS_REPLACE_WITH_QUESTION_MARK
Replace the unknown/bad bits with question marks.
static void SetClientIds(Ttuple &values, ClientID client_id, std::index_sequence< Tindices... >)
Set all invalid ClientID's to the proper value.
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 CcPlaceSign(Commands cmd, const CommandCost &result, SignID new_sign)
Callback function that is called after a sign is placed.
uint16 Recv_uint16()
Read a 16 bits integer from the packet.
void NetworkDistributeCommands()
Distribute the commands of ourself and the clients.
static void DistributeQueue(CommandQueue *queue, const NetworkClientSocket *owner)
"Send" a particular CommandQueue to all clients.
static const uint NETWORK_COMPANY_NAME_LENGTH
The maximum length of the company name, in bytes including '\0'.
CommandPacket * Pop(bool ignore_paused=false)
Return the first item in the queue and remove it from the queue.
Commands cmd
command being executed.