|
|
|
@ -55,16 +55,19 @@ static CommandCallback * const _callback_table[] = {
|
|
|
|
|
/**
|
|
|
|
|
* Append a CommandPacket at the end of the queue.
|
|
|
|
|
* @param p The packet to append to the queue.
|
|
|
|
|
* @note A new instance of the CommandPacket will be made.
|
|
|
|
|
*/
|
|
|
|
|
void CommandQueue::Append(CommandPacket *p)
|
|
|
|
|
{
|
|
|
|
|
assert(p != NULL);
|
|
|
|
|
CommandPacket *add = MallocT<CommandPacket>(1);
|
|
|
|
|
*add = *p;
|
|
|
|
|
add->next = NULL;
|
|
|
|
|
if (this->first == NULL) {
|
|
|
|
|
this->first = p;
|
|
|
|
|
this->first = add;
|
|
|
|
|
} else {
|
|
|
|
|
this->last->next = p;
|
|
|
|
|
this->last->next = add;
|
|
|
|
|
}
|
|
|
|
|
this->last = p;
|
|
|
|
|
this->last = add;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -96,23 +99,11 @@ void CommandQueue::Free()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Local queue of packets waiting for handling. */
|
|
|
|
|
static CommandQueue _local_wait_queue;
|
|
|
|
|
/** Local queue of packets waiting for execution. */
|
|
|
|
|
static CommandQueue _local_execution_queue;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add a command to the local or client socket command queue,
|
|
|
|
|
* based on the socket.
|
|
|
|
|
* @param cp the command packet to add
|
|
|
|
|
* @param cs the socket to send to (NULL = locally)
|
|
|
|
|
*/
|
|
|
|
|
void NetworkAddCommandQueue(CommandPacket cp, NetworkClientSocket *cs)
|
|
|
|
|
{
|
|
|
|
|
CommandPacket *new_cp = MallocT<CommandPacket>(1);
|
|
|
|
|
*new_cp = cp;
|
|
|
|
|
(cs == NULL ? _local_execution_queue : cs->outgoing_queue).Append(new_cp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Prepare a DoCommand to be send over the network
|
|
|
|
|
* @param tile The tile to perform a command on (see #CommandProc)
|
|
|
|
@ -129,7 +120,6 @@ void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comma
|
|
|
|
|
|
|
|
|
|
CommandPacket c;
|
|
|
|
|
c.company = company;
|
|
|
|
|
c.next = NULL;
|
|
|
|
|
c.tile = tile;
|
|
|
|
|
c.p1 = p1;
|
|
|
|
|
c.p2 = p2;
|
|
|
|
@ -148,15 +138,7 @@ void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comma
|
|
|
|
|
c.frame = _frame_counter_max + 1;
|
|
|
|
|
c.my_cmd = true;
|
|
|
|
|
|
|
|
|
|
NetworkAddCommandQueue(c);
|
|
|
|
|
|
|
|
|
|
/* Only the local client (in this case, the server) gets the callback */
|
|
|
|
|
c.callback = 0;
|
|
|
|
|
/* And we queue it for delivery to the clients */
|
|
|
|
|
NetworkClientSocket *cs;
|
|
|
|
|
FOR_ALL_CLIENT_SOCKETS(cs) {
|
|
|
|
|
if (cs->status > STATUS_MAP_WAIT) NetworkAddCommandQueue(c, cs);
|
|
|
|
|
}
|
|
|
|
|
_local_wait_queue.Append(&c);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -180,8 +162,7 @@ void NetworkSyncCommandQueue(NetworkClientSocket *cs)
|
|
|
|
|
for (CommandPacket *p = _local_execution_queue.Peek(); p != NULL; p = p->next) {
|
|
|
|
|
CommandPacket c = *p;
|
|
|
|
|
c.callback = 0;
|
|
|
|
|
c.next = NULL;
|
|
|
|
|
NetworkAddCommandQueue(c, cs);
|
|
|
|
|
cs->outgoing_queue.Append(&c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -192,8 +173,10 @@ void NetworkExecuteLocalCommandQueue()
|
|
|
|
|
{
|
|
|
|
|
assert(IsLocalCompany());
|
|
|
|
|
|
|
|
|
|
CommandQueue &queue = (_network_server ? _local_execution_queue : NetworkClientSocket::Get(0)->incoming_queue);
|
|
|
|
|
|
|
|
|
|
CommandPacket *cp;
|
|
|
|
|
while ((cp = _local_execution_queue.Peek()) != NULL) {
|
|
|
|
|
while ((cp = queue.Peek()) != NULL) {
|
|
|
|
|
/* The queue is always in order, which means
|
|
|
|
|
* that the first element will be executed first. */
|
|
|
|
|
if (_frame_counter < cp->frame) break;
|
|
|
|
@ -209,7 +192,7 @@ void NetworkExecuteLocalCommandQueue()
|
|
|
|
|
cp->cmd |= CMD_NETWORK_COMMAND;
|
|
|
|
|
DoCommandP(cp, cp->my_cmd);
|
|
|
|
|
|
|
|
|
|
_local_execution_queue.Pop();
|
|
|
|
|
queue.Pop();
|
|
|
|
|
free(cp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -225,6 +208,58 @@ void NetworkFreeLocalCommandQueue()
|
|
|
|
|
_local_execution_queue.Free();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* "Send" a particular CommandPacket to all clients.
|
|
|
|
|
* @param cp The command that has to be distributed.
|
|
|
|
|
* @param owner The client that owns the command,
|
|
|
|
|
*/
|
|
|
|
|
static void DistributeCommandPacket(CommandPacket cp, const NetworkClientSocket *owner)
|
|
|
|
|
{
|
|
|
|
|
CommandCallback *callback = cp.callback;
|
|
|
|
|
cp.frame = _frame_counter_max + 1;
|
|
|
|
|
|
|
|
|
|
NetworkClientSocket *cs;
|
|
|
|
|
FOR_ALL_CLIENT_SOCKETS(cs) {
|
|
|
|
|
if (cs->status >= STATUS_MAP) {
|
|
|
|
|
/* Callbacks are only send back to the client who sent them in the
|
|
|
|
|
* first place. This filters that out. */
|
|
|
|
|
cp.callback = (cs != owner) ? NULL : callback;
|
|
|
|
|
cp.my_cmd = (cs == owner);
|
|
|
|
|
cs->outgoing_queue.Append(&cp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cp.callback = (cs != owner) ? NULL : callback;
|
|
|
|
|
cp.my_cmd = (cs == owner);
|
|
|
|
|
_local_execution_queue.Append(&cp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* "Send" a particular CommandQueue to all clients.
|
|
|
|
|
* @param queue The queue of commands that has to be distributed.
|
|
|
|
|
* @param owner The client that owns the commands,
|
|
|
|
|
*/
|
|
|
|
|
static void DistributeQueue(CommandQueue *queue, const NetworkClientSocket *owner)
|
|
|
|
|
{
|
|
|
|
|
CommandPacket *cp;
|
|
|
|
|
while ((cp = queue->Pop()) != NULL) {
|
|
|
|
|
DistributeCommandPacket(*cp, owner);
|
|
|
|
|
free(cp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetworkDistributeCommands()
|
|
|
|
|
{
|
|
|
|
|
/* First send the server's commands. */
|
|
|
|
|
DistributeQueue(&_local_wait_queue, NULL);
|
|
|
|
|
|
|
|
|
|
/* Then send the queues of the others. */
|
|
|
|
|
NetworkClientSocket *cs;
|
|
|
|
|
FOR_ALL_CLIENT_SOCKETS(cs) {
|
|
|
|
|
DistributeQueue(&cs->incoming_queue, cs);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Receives a command from the network.
|
|
|
|
|
* @param p the packet to read from.
|
|
|
|
|