network_command.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifdef ENABLE_NETWORK
00013
00014 #include "../stdafx.h"
00015 #include "../debug.h"
00016 #include "network_client.h"
00017 #include "network.h"
00018 #include "../command_func.h"
00019 #include "../company_func.h"
00020
00022 static CommandCallback * const _callback_table[] = {
00023 NULL,
00024 CcBuildPrimaryVehicle,
00025 CcBuildAirport,
00026 CcBuildBridge,
00027 CcBuildCanal,
00028 CcBuildDocks,
00029 CcFoundTown,
00030 CcBuildRoadTunnel,
00031 CcBuildRailTunnel,
00032 CcBuildWagon,
00033 CcRoadDepot,
00034 CcRailDepot,
00035 CcPlaceSign,
00036 CcPlaySound10,
00037 CcPlaySound1D,
00038 CcPlaySound1E,
00039 CcStation,
00040 CcTerraform,
00041 #ifdef ENABLE_AI
00042 CcAI,
00043 #else
00044 NULL,
00045 #endif
00046 CcCloneVehicle,
00047 CcGiveMoney,
00048 CcCreateGroup,
00049 CcFoundRandomTown,
00050 };
00051
00053 static CommandPacket *_local_command_queue = NULL;
00054
00061 void NetworkAddCommandQueue(CommandPacket cp, NetworkClientSocket *cs)
00062 {
00063 CommandPacket *new_cp = MallocT<CommandPacket>(1);
00064 *new_cp = cp;
00065
00066 CommandPacket **begin = (cs == NULL ? &_local_command_queue : &cs->command_queue);
00067
00068 if (*begin == NULL) {
00069 *begin = new_cp;
00070 } else {
00071 CommandPacket *c = *begin;
00072 while (c->next != NULL) c = c->next;
00073 c->next = new_cp;
00074 }
00075 }
00076
00087 void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, CompanyID company)
00088 {
00089 assert((cmd & CMD_FLAGS_MASK) == 0);
00090
00091 CommandPacket c;
00092 c.company = company;
00093 c.next = NULL;
00094 c.tile = tile;
00095 c.p1 = p1;
00096 c.p2 = p2;
00097 c.cmd = cmd;
00098 c.callback = callback;
00099
00100 strecpy(c.text, (text != NULL) ? text : "", lastof(c.text));
00101
00102 if (_network_server) {
00103
00104
00105
00106
00107
00108
00109 c.frame = _frame_counter_max + 1;
00110 c.my_cmd = true;
00111
00112 NetworkAddCommandQueue(c);
00113
00114
00115 c.callback = 0;
00116
00117 NetworkClientSocket *cs;
00118 FOR_ALL_CLIENT_SOCKETS(cs) {
00119 if (cs->status > STATUS_MAP_WAIT) NetworkAddCommandQueue(c, cs);
00120 }
00121 return;
00122 }
00123
00124 c.frame = 0;
00125
00126
00127 SEND_COMMAND(PACKET_CLIENT_COMMAND)(&c);
00128 }
00129
00139 void NetworkSyncCommandQueue(NetworkClientSocket *cs)
00140 {
00141 for (CommandPacket *p = _local_command_queue; p != NULL; p = p->next) {
00142 CommandPacket c = *p;
00143 c.callback = 0;
00144 c.next = NULL;
00145 NetworkAddCommandQueue(c, cs);
00146 }
00147 }
00148
00152 void NetworkExecuteLocalCommandQueue()
00153 {
00154 while (_local_command_queue != NULL) {
00155
00156
00157
00158 if (_frame_counter < _local_command_queue->frame) break;
00159
00160 if (_frame_counter > _local_command_queue->frame) {
00161
00162
00163 error("[net] Trying to execute a packet in the past!");
00164 }
00165
00166 CommandPacket *cp = _local_command_queue;
00167
00168
00169 _current_company = cp->company;
00170 cp->cmd |= CMD_NETWORK_COMMAND;
00171 DoCommandP(cp, cp->my_cmd);
00172
00173 _local_command_queue = _local_command_queue->next;
00174 free(cp);
00175 }
00176 }
00177
00181 void NetworkFreeLocalCommandQueue()
00182 {
00183
00184 while (_local_command_queue != NULL) {
00185 CommandPacket *p = _local_command_queue;
00186 _local_command_queue = _local_command_queue->next;
00187 free(p);
00188 }
00189 }
00190
00197 const char *NetworkClientSocket::Recv_Command(Packet *p, CommandPacket *cp)
00198 {
00199 cp->company = (CompanyID)p->Recv_uint8();
00200 cp->cmd = p->Recv_uint32();
00201 cp->p1 = p->Recv_uint32();
00202 cp->p2 = p->Recv_uint32();
00203 cp->tile = p->Recv_uint32();
00204 p->Recv_string(cp->text, lengthof(cp->text));
00205
00206 byte callback = p->Recv_uint8();
00207
00208 if (!IsValidCommand(cp->cmd)) return "invalid command";
00209 if (GetCommandFlags(cp->cmd) & CMD_OFFLINE) return "offline only command";
00210 if ((cp->cmd & CMD_FLAGS_MASK) != 0) return "invalid command flag";
00211 if (callback > lengthof(_callback_table)) return "invalid callback";
00212
00213 cp->callback = _callback_table[callback];
00214 return NULL;
00215 }
00216
00222 void NetworkClientSocket::Send_Command(Packet *p, const CommandPacket *cp)
00223 {
00224 p->Send_uint8 (cp->company);
00225 p->Send_uint32(cp->cmd);
00226 p->Send_uint32(cp->p1);
00227 p->Send_uint32(cp->p2);
00228 p->Send_uint32(cp->tile);
00229 p->Send_string(cp->text);
00230
00231 byte callback = 0;
00232 while (callback < lengthof(_callback_table) && _callback_table[callback] != cp->callback) {
00233 callback++;
00234 }
00235
00236 if (callback == lengthof(_callback_table)) {
00237 DEBUG(net, 0, "Unknown callback. (Pointer: %p) No callback sent", cp->callback);
00238 callback = 0;
00239 }
00240 p->Send_uint8 (callback);
00241 }
00242
00243 #endif