mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 06:15:04 +00:00
(svn r20933) -Codechange: move some more client related methods and such to network_client.cpp
This commit is contained in:
parent
780f120c32
commit
f555e6d72e
@ -214,4 +214,31 @@ bool NetworkTCPSocketHandler::IsPacketQueueEmpty()
|
||||
return this->packet_queue == NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this socket can send or receive something.
|
||||
* @return \c true when there is something to receive.
|
||||
* @note Sets #writeable if more data can be sent.
|
||||
*/
|
||||
bool NetworkTCPSocketHandler::CanSendReceive()
|
||||
{
|
||||
fd_set read_fd, write_fd;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&read_fd);
|
||||
FD_ZERO(&write_fd);
|
||||
|
||||
FD_SET(this->sock, &read_fd);
|
||||
FD_SET(this->sock, &write_fd);
|
||||
|
||||
tv.tv_sec = tv.tv_usec = 0; // don't block at all.
|
||||
#if !defined(__MORPHOS__) && !defined(__AMIGA__)
|
||||
select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv);
|
||||
#else
|
||||
WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL);
|
||||
#endif
|
||||
|
||||
this->writable = !!FD_ISSET(this->sock, &write_fd);
|
||||
return FD_ISSET(this->sock, &read_fd);
|
||||
}
|
||||
|
||||
#endif /* ENABLE_NETWORK */
|
||||
|
@ -41,6 +41,8 @@ public:
|
||||
|
||||
Packet *Recv_Packet();
|
||||
|
||||
bool CanSendReceive();
|
||||
|
||||
NetworkTCPSocketHandler(SOCKET s = INVALID_SOCKET);
|
||||
~NetworkTCPSocketHandler();
|
||||
};
|
||||
|
@ -240,7 +240,7 @@ uint NetworkCalculateLag(const NetworkClientSocket *cs)
|
||||
|
||||
/* There was a non-recoverable error, drop back to the main menu with a nice
|
||||
* error */
|
||||
static void NetworkError(StringID error_string)
|
||||
void NetworkError(StringID error_string)
|
||||
{
|
||||
_switch_mode = SM_MENU;
|
||||
extern StringID _switch_mode_errorstr;
|
||||
@ -253,40 +253,6 @@ static void ServerStartError(const char *error)
|
||||
NetworkError(STR_NETWORK_ERROR_SERVER_START);
|
||||
}
|
||||
|
||||
static void NetworkClientError(NetworkRecvStatus res, NetworkClientSocket *cs)
|
||||
{
|
||||
/* First, send a CLIENT_ERROR to the server, so he knows we are
|
||||
* disconnection (and why!) */
|
||||
NetworkErrorCode errorno;
|
||||
|
||||
/* We just want to close the connection.. */
|
||||
if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) {
|
||||
cs->NetworkSocketHandler::CloseConnection();
|
||||
cs->CloseConnection(res);
|
||||
_networking = false;
|
||||
|
||||
DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (res) {
|
||||
case NETWORK_RECV_STATUS_DESYNC: errorno = NETWORK_ERROR_DESYNC; break;
|
||||
case NETWORK_RECV_STATUS_SAVEGAME: errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
|
||||
case NETWORK_RECV_STATUS_NEWGRF_MISMATCH: errorno = NETWORK_ERROR_NEWGRF_MISMATCH; break;
|
||||
default: errorno = NETWORK_ERROR_GENERAL; break;
|
||||
}
|
||||
|
||||
/* This means we fucked up and the server closed the connection */
|
||||
if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL &&
|
||||
res != NETWORK_RECV_STATUS_SERVER_BANNED) {
|
||||
MyClient::SendError(errorno);
|
||||
}
|
||||
|
||||
_switch_mode = SM_MENU;
|
||||
cs->CloseConnection(res);
|
||||
_networking = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the string id of an internal error number
|
||||
* @param err NetworkErrorCode
|
||||
@ -838,6 +804,9 @@ void NetworkDisconnect(bool blocking)
|
||||
*/
|
||||
static bool NetworkReceive()
|
||||
{
|
||||
if (!_network_server) {
|
||||
return ClientNetworkGameSocketHandler::Receive();
|
||||
}
|
||||
NetworkClientSocket *cs;
|
||||
fd_set read_fd, write_fd;
|
||||
struct timeval tv;
|
||||
@ -872,22 +841,7 @@ static bool NetworkReceive()
|
||||
FOR_ALL_CLIENT_SOCKETS(cs) {
|
||||
cs->writable = !!FD_ISSET(cs->sock, &write_fd);
|
||||
if (FD_ISSET(cs->sock, &read_fd)) {
|
||||
if (_network_server) {
|
||||
cs->Recv_Packets();
|
||||
} else {
|
||||
NetworkRecvStatus res;
|
||||
|
||||
/* The client already was quiting! */
|
||||
if (cs->HasClientQuit()) return false;
|
||||
|
||||
res = cs->Recv_Packets();
|
||||
if (res != NETWORK_RECV_STATUS_OKAY) {
|
||||
/* The client made an error of which we can not recover
|
||||
* close the client and drop back to main menu */
|
||||
NetworkClientError(res, cs);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
cs->Recv_Packets();
|
||||
}
|
||||
}
|
||||
return _networking;
|
||||
@ -896,6 +850,11 @@ static bool NetworkReceive()
|
||||
/* This sends all buffered commands (if possible) */
|
||||
static void NetworkSend()
|
||||
{
|
||||
if (!_network_server) {
|
||||
ClientNetworkGameSocketHandler::Send();
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkClientSocket *cs;
|
||||
FOR_ALL_CLIENT_SOCKETS(cs) {
|
||||
if (cs->writable) {
|
||||
@ -909,47 +868,6 @@ static void NetworkSend()
|
||||
}
|
||||
}
|
||||
|
||||
static bool NetworkDoClientLoop()
|
||||
{
|
||||
_frame_counter++;
|
||||
|
||||
NetworkExecuteLocalCommandQueue();
|
||||
|
||||
StateGameLoop();
|
||||
|
||||
/* Check if we are in sync! */
|
||||
if (_sync_frame != 0) {
|
||||
if (_sync_frame == _frame_counter) {
|
||||
#ifdef NETWORK_SEND_DOUBLE_SEED
|
||||
if (_sync_seed_1 != _random.state[0] || _sync_seed_2 != _random.state[1]) {
|
||||
#else
|
||||
if (_sync_seed_1 != _random.state[0]) {
|
||||
#endif
|
||||
NetworkError(STR_NETWORK_ERROR_DESYNC);
|
||||
DEBUG(desync, 1, "sync_err: %08x; %02x", _date, _date_fract);
|
||||
DEBUG(net, 0, "Sync error detected!");
|
||||
NetworkClientError(NETWORK_RECV_STATUS_DESYNC, NetworkClientSocket::Get(0));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If this is the first time we have a sync-frame, we
|
||||
* need to let the server know that we are ready and at the same
|
||||
* frame as he is.. so we can start playing! */
|
||||
if (_network_first_time) {
|
||||
_network_first_time = false;
|
||||
MyClient::SendAck();
|
||||
}
|
||||
|
||||
_sync_frame = 0;
|
||||
} else if (_sync_frame < _frame_counter) {
|
||||
DEBUG(net, 1, "Missed frame for sync-test (%d / %d)", _sync_frame, _frame_counter);
|
||||
_sync_frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We have to do some UDP checking */
|
||||
void NetworkUDPGameLoop()
|
||||
{
|
||||
@ -1107,11 +1025,11 @@ void NetworkGameLoop()
|
||||
/* Make sure we are at the frame were the server is (quick-frames) */
|
||||
if (_frame_counter_server > _frame_counter) {
|
||||
while (_frame_counter_server > _frame_counter) {
|
||||
if (!NetworkDoClientLoop()) break;
|
||||
if (!ClientNetworkGameSocketHandler::GameLoop()) break;
|
||||
}
|
||||
} else {
|
||||
/* Else, keep on going till _frame_counter_max */
|
||||
if (_frame_counter_max > _frame_counter) NetworkDoClientLoop();
|
||||
if (_frame_counter_max > _frame_counter) ClientNetworkGameSocketHandler::GameLoop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "../company_func.h"
|
||||
#include "../company_base.h"
|
||||
#include "../company_gui.h"
|
||||
#include "../core/random_func.hpp"
|
||||
#include "../date_func.h"
|
||||
#include "../rev.h"
|
||||
#include "network.h"
|
||||
#include "network_base.h"
|
||||
@ -73,6 +75,117 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::CloseConnection(NetworkRecvSta
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an error coming from the client side.
|
||||
* @param res The "error" that happened.
|
||||
*/
|
||||
void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res)
|
||||
{
|
||||
/* First, send a CLIENT_ERROR to the server, so he knows we are
|
||||
* disconnection (and why!) */
|
||||
NetworkErrorCode errorno;
|
||||
|
||||
/* We just want to close the connection.. */
|
||||
if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) {
|
||||
this->NetworkSocketHandler::CloseConnection();
|
||||
this->CloseConnection(res);
|
||||
_networking = false;
|
||||
|
||||
DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (res) {
|
||||
case NETWORK_RECV_STATUS_DESYNC: errorno = NETWORK_ERROR_DESYNC; break;
|
||||
case NETWORK_RECV_STATUS_SAVEGAME: errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
|
||||
case NETWORK_RECV_STATUS_NEWGRF_MISMATCH: errorno = NETWORK_ERROR_NEWGRF_MISMATCH; break;
|
||||
default: errorno = NETWORK_ERROR_GENERAL; break;
|
||||
}
|
||||
|
||||
/* This means we fucked up and the server closed the connection */
|
||||
if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL &&
|
||||
res != NETWORK_RECV_STATUS_SERVER_BANNED) {
|
||||
SendError(errorno);
|
||||
}
|
||||
|
||||
_switch_mode = SM_MENU;
|
||||
this->CloseConnection(res);
|
||||
_networking = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether we received/can send some data from/to the server and
|
||||
* when that's the case handle it appropriately.
|
||||
* @return true when everything went okay.
|
||||
*/
|
||||
/*static */ bool ClientNetworkGameSocketHandler::Receive()
|
||||
{
|
||||
if (my_client->CanSendReceive()) {
|
||||
NetworkRecvStatus res = my_client->Recv_Packets();
|
||||
if (res != NETWORK_RECV_STATUS_OKAY) {
|
||||
/* The client made an error of which we can not recover
|
||||
* close the client and drop back to main menu */
|
||||
my_client->ClientError(res);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return _networking;
|
||||
}
|
||||
|
||||
/** Send the packets of this socket handler. */
|
||||
/*static */ void ClientNetworkGameSocketHandler::Send()
|
||||
{
|
||||
my_client->Send_Packets();
|
||||
}
|
||||
|
||||
/**
|
||||
* Actual game loop for the client.
|
||||
* @return Whether everything went okay, or not.
|
||||
*/
|
||||
/* static */ bool ClientNetworkGameSocketHandler::GameLoop()
|
||||
{
|
||||
_frame_counter++;
|
||||
|
||||
NetworkExecuteLocalCommandQueue();
|
||||
|
||||
extern void StateGameLoop();
|
||||
StateGameLoop();
|
||||
|
||||
/* Check if we are in sync! */
|
||||
if (_sync_frame != 0) {
|
||||
if (_sync_frame == _frame_counter) {
|
||||
#ifdef NETWORK_SEND_DOUBLE_SEED
|
||||
if (_sync_seed_1 != _random.state[0] || _sync_seed_2 != _random.state[1]) {
|
||||
#else
|
||||
if (_sync_seed_1 != _random.state[0]) {
|
||||
#endif
|
||||
NetworkError(STR_NETWORK_ERROR_DESYNC);
|
||||
DEBUG(desync, 1, "sync_err: %08x; %02x", _date, _date_fract);
|
||||
DEBUG(net, 0, "Sync error detected!");
|
||||
my_client->ClientError(NETWORK_RECV_STATUS_DESYNC);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If this is the first time we have a sync-frame, we
|
||||
* need to let the server know that we are ready and at the same
|
||||
* frame as he is.. so we can start playing! */
|
||||
if (_network_first_time) {
|
||||
_network_first_time = false;
|
||||
SendAck();
|
||||
}
|
||||
|
||||
_sync_frame = 0;
|
||||
} else if (_sync_frame < _frame_counter) {
|
||||
DEBUG(net, 1, "Missed frame for sync-test (%d / %d)", _sync_frame, _frame_counter);
|
||||
_sync_frame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/** Our client's connection. */
|
||||
ClientNetworkGameSocketHandler * ClientNetworkGameSocketHandler::my_client = NULL;
|
||||
|
||||
|
@ -54,6 +54,7 @@ public:
|
||||
~ClientNetworkGameSocketHandler();
|
||||
|
||||
NetworkRecvStatus CloseConnection(NetworkRecvStatus status);
|
||||
void ClientError(NetworkRecvStatus res);
|
||||
|
||||
static NetworkRecvStatus SendCompanyInformationQuery();
|
||||
|
||||
@ -71,6 +72,10 @@ public:
|
||||
static NetworkRecvStatus SendSetName(const char *name);
|
||||
static NetworkRecvStatus SendRCon(const char *password, const char *command);
|
||||
static NetworkRecvStatus SendMove(CompanyID company, const char *password);
|
||||
|
||||
static void Send();
|
||||
static bool Receive();
|
||||
static bool GameLoop();
|
||||
};
|
||||
|
||||
typedef ClientNetworkGameSocketHandler MyClient;
|
||||
|
@ -737,27 +737,11 @@ void ClientNetworkContentSocketHandler::SendReceive()
|
||||
return;
|
||||
}
|
||||
|
||||
fd_set read_fd, write_fd;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&read_fd);
|
||||
FD_ZERO(&write_fd);
|
||||
|
||||
FD_SET(this->sock, &read_fd);
|
||||
FD_SET(this->sock, &write_fd);
|
||||
|
||||
tv.tv_sec = tv.tv_usec = 0; // don't block at all.
|
||||
#if !defined(__MORPHOS__) && !defined(__AMIGA__)
|
||||
select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv);
|
||||
#else
|
||||
WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL);
|
||||
#endif
|
||||
if (FD_ISSET(this->sock, &read_fd)) {
|
||||
if (this->CanSendReceive()) {
|
||||
this->Recv_Packets();
|
||||
this->lastActivity = _realtime_tick;
|
||||
}
|
||||
|
||||
this->writable = !!FD_ISSET(this->sock, &write_fd);
|
||||
this->Send_Packets();
|
||||
}
|
||||
|
||||
|
@ -166,6 +166,7 @@ void NetworkFreeLocalCommandQueue();
|
||||
void NetworkSyncCommandQueue(NetworkClientSocket *cs);
|
||||
|
||||
/* from network.c */
|
||||
void NetworkError(StringID error_string);
|
||||
void NetworkTextMessage(NetworkAction action, ConsoleColour colour, bool self_send, const char *name, const char *str = "", int64 data = 0);
|
||||
void NetworkGetClientName(char *clientname, size_t size, const NetworkClientSocket *cs);
|
||||
uint NetworkCalculateLag(const NetworkClientSocket *cs);
|
||||
|
Loading…
Reference in New Issue
Block a user