1
0
Fork 0

(svn r25599) [1.3] -Backport from trunk:

- Fix: [Admin] End-of-rcon data could not be determined reliably for any rcon command [FS#5643] (r25598, r25588, r25587)
- Fix: [Content] When the server closed the connection, the client would for eternity try to read a packet and never timeout making it impossible to reconnect [FS#5635] (r25597)
- Fix: [Script] Changing the script difficulty level in-game would also change the settings using the default even though they were not allowed to change in-game [FS#5644] (r25592)
- Fix: [Admin] Ensure that sent and received length of json strings are the same [FS#5646] (r25590, r25589)
- Fix: [Squirrel] Stack overflow did not show an error, due to the stack to throw the error already being full [FS#5320] (r25585)
release/1.3
rubidium 2013-07-13 10:13:55 +00:00
parent 8f6204546e
commit 7a081330e4
23 changed files with 156 additions and 44 deletions

View File

@ -31,7 +31,7 @@ description.hu_HU = Zenei alapcsomag zene nélkül.
description.id_ID = Paket musik tanpa musik sungguhan.
description.is_IS = Tónlistarpakki sem er í raun án tónlistar.
description.it_IT = Un pacchetto musicale non contenente alcuna musica.
description.ja_JP = 音楽が無いミュージックパック
description.ja_JP = 空の音楽パック
description.ko_KR = 실제 음악이 없는 음악 목록입니다.
description.lt_LT = Muzikos pakas be muzikos.
description.nb_NO = En musikkpakke uten noe musikk.

View File

@ -31,7 +31,7 @@ description.hu_HU = Hang alapcsomag hangok nélkül.
description.id_ID = Paket efek suara tanpa suara apapun.
description.is_IS = Hljóðpakki án hljóðs.
description.it_IT = Un pacchetto sonoro non contenente alcun suono.
description.ja_JP = 音楽が無いミュージックパック
description.ja_JP = 空の効果音パック
description.ko_KR = 아무런 효과음도 없는 효과음 팩입니다.
description.lt_LT = Garsų pakas be jokių garsų.
description.nb_NO = En lydpakke uten noen lyder.

View File

@ -32,7 +32,7 @@ description.hu_HU = Az eredeti Transport Tycoon Deluxe DOS verziójának grafik
description.id_ID = Grafik orisinil Transport Tycoon Deluxe versi DOS.
description.is_IS = Upprunalega grafíkin úr Transport Tycoon Deluxe DOS útgáfunni.
description.it_IT = Grafica originale di Transport Tycoon Deluxe, edizione DOS.
description.ja_JP = オリジナルDOS『トランスポートタイクンデラックス』版画像
description.ja_JP = Transport Tycoon Deluxe オリジナル版 グラフィック (DOS)
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 도스 에디션의 그래픽입니다.
description.lt_LT = Originali Transport Tycoon Deluxe DOS leidimo grafika.
description.nb_NO = Original grafikk fra Transport Tycoon Deluxe for DOS.

View File

@ -31,7 +31,7 @@ description.hu_HU = Az eredeti Transport Tycoon Deluxe DOS verziójának hangjai
description.id_ID = Efek suara orisinil Transport Tycoon Deluxe versi DOS.
description.is_IS = Upprunalega hljóðið úr Transport Tycoon Deluxe DOS útgáfunni.
description.it_IT = Suoni originali di Transport Tycoon Deluxe, edizione DOS.
description.ja_JP = オリジナル DOS 『トランスポートタイクンデラックス』版音楽
description.ja_JP = Transport Tycoon Deluxe オリジナル版 効果音 (DOS)
description.ko_KR = 오리지널 트랜스포트 타이쿤 도스 에디션의 효과음입니다.
description.lt_LT = Originalūs Transport Tycoon Deluxe DOS leidimo garsai.
description.nb_NO = Originale lyder fra Transport Tycoon Deluxe for DOS.

View File

@ -32,7 +32,7 @@ description.hu_HU = Az eredeti Transport Tycoon Deluxe DOS (német) verziójána
description.id_ID = Grafik orisinil Transport Tycoon Deluxe versi DOS (Jerman).
description.is_IS = Upprunalega grafíkin úr Transport Tycoon Deluxe DOS (þýsku) útgáfunni.
description.it_IT = Grafica originale di Transport Tycoon Deluxe (tedesco), edizione DOS.
description.ja_JP = オリジナルDOS『トランスポートタイクンデラックス』ドイツ語版 画像
description.ja_JP = Transport Tycoon Deluxe オリジナル版 グラフィック (DOS・ドイツ版)
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 도스 에디션(독일)의 그래픽입니다.
description.lt_LT = Originali Transport Tycoon Deluxe DOS (Vokiečių) leidimo grafika.
description.nb_NO = Original grafikk fra Transport Tycoon Deluxe for DOS (tysk).

View File

@ -32,7 +32,7 @@ description.hu_HU = Az eredeti Transport Tycoon Deluxe Windows verziójának gra
description.id_ID = Grafik orisinil Transport Tycoon Deluxe versi Windows.
description.is_IS = Upprunalega grafíkin úr Transport Tycoon Deluxe Windows útgáfunni.
description.it_IT = Grafica originale di Transport Tycoon Deluxe, edizione Windows.
description.ja_JP = オリジナルウィンドーズ『トランスポートタイクンデラックス』版 画像
description.ja_JP = Transport Tycoon Deluxe オリジナル版 グラフィック (Windows)
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 윈도우 에디션의 그래픽입니다.
description.lt_LT = Originali Transport Tycoon Deluxe Windows leidimo grafika.
description.nb_NO = Original grafikk fra Transport Tycoon Deluxe for Windows.

View File

@ -31,7 +31,7 @@ description.hu_HU = Az eredeti Transport Tycoon Deluxe Windows verziójának zen
description.id_ID = Musik pengiring orisinil Transport Tycoon Deluxe versi Windows.
description.is_IS = Upprunalega tónlistin úr Transport Tycoon Deluxe Windows útgáfunni.
description.it_IT = Musica originale di Transport Tycoon Deluxe, edizione Windows.
description.ja_JP = オリジナルウィンドーズ『トランスポートタイクンデラックス』版音楽
description.ja_JP = Transport Tycoon Deluxe オリジナル版 音楽 (Windows)
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 윈도우 에디션의 음악입니다.
description.lt_LT = Originali Transport Tycoon Deluxe Windows leidimo muzika.
description.nb_NO = Original musikk fra Transport Tycoon Deluxe for Windows.

View File

@ -31,7 +31,7 @@ description.hu_HU = Az eredeti Transport Tycoon Deluxe Windows verziójának han
description.id_ID = Efek suara orisinil Transport Tycoon Deluxe versi Windows.
description.is_IS = Upprunalega hljóðið úr Transport Tycoon Deluxe Windows útgáfunni.
description.it_IT = Suoni originali di Transport Tycoon Deluxe, edizione Windows.
description.ja_JP = オリジナルウィンドーズ『トランスポートタイクンデラックス』版音楽
description.ja_JP = Transport Tycoon Deluxe オリジナル版 効果音 (Windows)
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 윈도우 에디션의 효과음입니다.
description.lt_LT = Originalūs Transport Tycoon Deluxe Windows leidimo garsai.
description.nb_NO = Originale lyder fra Transport Tycoon Deluxe for Windows.

View File

@ -150,7 +150,8 @@ Table of contents
Note: No additional authentication is required for rcon commands.
The server will reply with a ADMIN_PACKET_SERVER_RCON packet. Applications
The server will reply with one or more ADMIN_PACKET_SERVER_RCON packets.
Finally an ADMIN_PACKET_ADMIN_RCON_END packet will be sent. Applications
will not receive the answer twice if they have asked for the AdminUpdateType
ADMIN_UPDATE_CONSOLE, as the result is not printed on the servers console
(just like clients rcon commands).
@ -160,6 +161,13 @@ Table of contents
Chat from the server itself will only be sent to the admin network when it
was not sent from the admin network.
Note that when content is queried or updated via rcon, the processing
happens asynchronously. But the ADMIN_PACKET_ADMIN_RCON_END packet is sent
already right after the content is requested as there's no immediate output.
Thus other packages and the output of content rcon command may be sent at
an arbitrary later time, mixing into the output of other console activity,
e.g. also of possible subsequent other rcon commands sent.
5.0) Sending chat
---- ------------

View File

@ -107,6 +107,7 @@ SQVM::SQVM(SQSharedState *ss)
_errorhandler = _null_;
_debughook = _null_;
_can_suspend = false;
_in_stackoverflow = false;
_ops_till_suspend = 0;
ci = NULL;
INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);

View File

@ -170,6 +170,7 @@ public:
SQBool _can_suspend;
SQInteger _ops_till_suspend;
SQBool _in_stackoverflow;
bool ShouldSuspend()
{
@ -200,8 +201,10 @@ inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->
#define PUSH_CALLINFO(v,nci){ \
if(v->_callsstacksize == v->_alloccallsstacksize) { \
if (v->_callsstacksize > 65535) {\
if (v->_callsstacksize > 65535 && !v->_in_stackoverflow) {\
v->_in_stackoverflow = true; \
v->Raise_Error(_SC("stack overflow"));\
v->CallErrorHandler(v->_lasterror);\
return false;\
}\
v->GrowCallStack(); \

View File

@ -47,6 +47,7 @@
/* Load default data and store the name in the settings */
config->Change(info->GetName(), -1, false, true);
}
config->AnchorUnchangeableSettings();
Backup<CompanyByte> cur_company(_current_company, company, FILE_LINE);
Company *c = Company::Get(company);

View File

@ -71,6 +71,8 @@
GameInfo *info = config->GetInfo();
if (info == NULL) return;
config->AnchorUnchangeableSettings();
Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
cur_company.Change(OWNER_DEITY);

View File

@ -25,33 +25,33 @@ static const char * const NETWORK_CONTENT_MIRROR_URL = "/bananas";
/** Message sent to the masterserver to 'identify' this client as OpenTTD */
static const char * const NETWORK_MASTER_SERVER_WELCOME_MESSAGE = "OpenTTDRegister";
static const uint16 NETWORK_MASTER_SERVER_PORT = 3978; ///< The default port of the master server (UDP)
static const uint16 NETWORK_CONTENT_SERVER_PORT = 3978; ///< The default port of the content server (TCP)
static const uint16 NETWORK_CONTENT_MIRROR_PORT = 80; ///< The default port of the content mirror (TCP)
static const uint16 NETWORK_DEFAULT_PORT = 3979; ///< The default port of the game server (TCP & UDP)
static const uint16 NETWORK_ADMIN_PORT = 3977; ///< The default port for admin network
static const uint16 NETWORK_DEFAULT_DEBUGLOG_PORT = 3982; ///< The default port debug-log is sent to (TCP)
static const uint16 NETWORK_MASTER_SERVER_PORT = 3978; ///< The default port of the master server (UDP)
static const uint16 NETWORK_CONTENT_SERVER_PORT = 3978; ///< The default port of the content server (TCP)
static const uint16 NETWORK_CONTENT_MIRROR_PORT = 80; ///< The default port of the content mirror (TCP)
static const uint16 NETWORK_DEFAULT_PORT = 3979; ///< The default port of the game server (TCP & UDP)
static const uint16 NETWORK_ADMIN_PORT = 3977; ///< The default port for admin network
static const uint16 NETWORK_DEFAULT_DEBUGLOG_PORT = 3982; ///< The default port debug-log is sent to (TCP)
static const uint16 SEND_MTU = 1460; ///< Number of bytes we can pack in a single packet
static const uint16 SEND_MTU = 1460; ///< Number of bytes we can pack in a single packet
static const byte NETWORK_GAME_ADMIN_VERSION = 1; ///< What version of the admin network do we use?
static const byte NETWORK_GAME_INFO_VERSION = 4; ///< What version of game-info do we use?
static const byte NETWORK_COMPANY_INFO_VERSION = 6; ///< What version of company info is this?
static const byte NETWORK_MASTER_SERVER_VERSION = 2; ///< What version of master-server-protocol do we use?
static const byte NETWORK_GAME_ADMIN_VERSION = 1; ///< What version of the admin network do we use?
static const byte NETWORK_GAME_INFO_VERSION = 4; ///< What version of game-info do we use?
static const byte NETWORK_COMPANY_INFO_VERSION = 6; ///< What version of company info is this?
static const byte NETWORK_MASTER_SERVER_VERSION = 2; ///< What version of master-server-protocol do we use?
static const uint NETWORK_NAME_LENGTH = 80; ///< The maximum length of the server name and map name, in bytes including '\0'
static const uint NETWORK_COMPANY_NAME_LENGTH = 128; ///< The maximum length of the company name, in bytes including '\0'
static const uint NETWORK_HOSTNAME_LENGTH = 80; ///< The maximum length of the host name, in bytes including '\0'
static const uint NETWORK_SERVER_ID_LENGTH = 33; ///< The maximum length of the network id of the servers, in bytes including '\0'
static const uint NETWORK_REVISION_LENGTH = 15; ///< The maximum length of the revision, in bytes including '\0'
static const uint NETWORK_PASSWORD_LENGTH = 33; ///< The maximum length of the password, in bytes including '\0' (must be >= NETWORK_SERVER_ID_LENGTH)
static const uint NETWORK_CLIENTS_LENGTH = 200; ///< The maximum length for the list of clients that controls a company, in bytes including '\0'
static const uint NETWORK_CLIENT_NAME_LENGTH = 25; ///< The maximum length of a client's name, in bytes including '\0'
static const uint NETWORK_RCONCOMMAND_LENGTH = 500; ///< The maximum length of a rconsole command, in bytes including '\0'
static const uint NETWORK_GAMESCRIPT_JSON_LENGTH = 1450; ///< The maximum length of a gamescript json string, in bytes including '\0'
static const uint NETWORK_CHAT_LENGTH = 900; ///< The maximum length of a chat message, in bytes including '\0'
static const uint NETWORK_NAME_LENGTH = 80; ///< The maximum length of the server name and map name, in bytes including '\0'
static const uint NETWORK_COMPANY_NAME_LENGTH = 128; ///< The maximum length of the company name, in bytes including '\0'
static const uint NETWORK_HOSTNAME_LENGTH = 80; ///< The maximum length of the host name, in bytes including '\0'
static const uint NETWORK_SERVER_ID_LENGTH = 33; ///< The maximum length of the network id of the servers, in bytes including '\0'
static const uint NETWORK_REVISION_LENGTH = 15; ///< The maximum length of the revision, in bytes including '\0'
static const uint NETWORK_PASSWORD_LENGTH = 33; ///< The maximum length of the password, in bytes including '\0' (must be >= NETWORK_SERVER_ID_LENGTH)
static const uint NETWORK_CLIENTS_LENGTH = 200; ///< The maximum length for the list of clients that controls a company, in bytes including '\0'
static const uint NETWORK_CLIENT_NAME_LENGTH = 25; ///< The maximum length of a client's name, in bytes including '\0'
static const uint NETWORK_RCONCOMMAND_LENGTH = 500; ///< The maximum length of a rconsole command, in bytes including '\0'
static const uint NETWORK_GAMESCRIPT_JSON_LENGTH = SEND_MTU - 3; ///< The maximum length of a gamescript json string, in bytes including '\0'. Must not be longer than SEND_MTU including header (3 bytes)
static const uint NETWORK_CHAT_LENGTH = 900; ///< The maximum length of a chat message, in bytes including '\0'
static const uint NETWORK_GRF_NAME_LENGTH = 80; ///< Maximum length of the name of a GRF
static const uint NETWORK_GRF_NAME_LENGTH = 80; ///< Maximum length of the name of a GRF
/**
* Maximum number of GRFs that can be sent.

View File

@ -61,6 +61,7 @@ NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet *p)
case ADMIN_PACKET_ADMIN_CHAT: return this->Receive_ADMIN_CHAT(p);
case ADMIN_PACKET_ADMIN_RCON: return this->Receive_ADMIN_RCON(p);
case ADMIN_PACKET_ADMIN_GAMESCRIPT: return this->Receive_ADMIN_GAMESCRIPT(p);
case ADMIN_PACKET_ADMIN_PING: return this->Receive_ADMIN_PING(p);
case ADMIN_PACKET_SERVER_FULL: return this->Receive_SERVER_FULL(p);
case ADMIN_PACKET_SERVER_BANNED: return this->Receive_SERVER_BANNED(p);
@ -87,6 +88,8 @@ NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet *p)
case ADMIN_PACKET_SERVER_CONSOLE: return this->Receive_SERVER_CONSOLE(p);
case ADMIN_PACKET_SERVER_CMD_NAMES: return this->Receive_SERVER_CMD_NAMES(p);
case ADMIN_PACKET_SERVER_CMD_LOGGING: return this->Receive_SERVER_CMD_LOGGING(p);
case ADMIN_PACKET_SERVER_RCON_END: return this->Receive_SERVER_RCON_END(p);
case ADMIN_PACKET_SERVER_PONG: return this->Receive_SERVER_PONG(p);
default:
if (this->HasClientQuit()) {
@ -136,6 +139,7 @@ NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet *p) { ret
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_CHAT); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_RCON); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_GAMESCRIPT); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_PING(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_PING); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_FULL(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_FULL); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_BANNED(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_BANNED); }
@ -162,5 +166,7 @@ NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_RCON(Packet *p) { re
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CONSOLE(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CONSOLE); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CMD_NAMES(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CMD_NAMES); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CMD_LOGGING(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CMD_LOGGING); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_RCON_END(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_RCON_END); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_PONG(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_PONG); }
#endif /* ENABLE_NETWORK */

View File

@ -33,6 +33,7 @@ enum PacketAdminType {
ADMIN_PACKET_ADMIN_CHAT, ///< The admin sends a chat message to be distributed.
ADMIN_PACKET_ADMIN_RCON, ///< The admin sends a remote console command.
ADMIN_PACKET_ADMIN_GAMESCRIPT, ///< The admin sends a JSON string for the GameScript.
ADMIN_PACKET_ADMIN_PING, ///< The admin sends a ping to the server, expecting a ping-reply (PONG) packet.
ADMIN_PACKET_SERVER_FULL = 100, ///< The server tells the admin it cannot accept the admin.
ADMIN_PACKET_SERVER_BANNED, ///< The server tells the admin it is banned.
@ -60,6 +61,8 @@ enum PacketAdminType {
ADMIN_PACKET_SERVER_CMD_NAMES, ///< The server sends out the names of the DoCommands to the admins.
ADMIN_PACKET_SERVER_CMD_LOGGING, ///< The server gives the admin copies of incoming command packets.
ADMIN_PACKET_SERVER_GAMESCRIPT, ///< The server gives the admin information from the GameScript in JSON.
ADMIN_PACKET_SERVER_RCON_END, ///< The server indicates that the remote console command has completed.
ADMIN_PACKET_SERVER_PONG, ///< The server replies to a ping request from the admin.
INVALID_ADMIN_PACKET = 0xFF, ///< An invalid marker for admin packets.
};
@ -180,6 +183,14 @@ protected:
*/
virtual NetworkRecvStatus Receive_ADMIN_GAMESCRIPT(Packet *p);
/**
* Ping the server, requiring the server to reply with a pong packet.
* uint32 Integer value to pass to the server, which is quoted in the reply.
* @param p The packet that was just received.
* @return The state the network should have.
*/
virtual NetworkRecvStatus Receive_ADMIN_PING(Packet *p);
/**
* The server is full (connection gets closed).
* @param p The packet that was just received.
@ -454,6 +465,22 @@ protected:
*/
virtual NetworkRecvStatus Receive_SERVER_CMD_LOGGING(Packet *p);
/**
* Send a ping-reply (pong) to the admin that sent us the ping packet.
* uint32 Integer identifier - should be the same as read from the admins ping packet.
* @param p The packet that was just received.
* @return The state the network should have.
*/
virtual NetworkRecvStatus Receive_SERVER_PONG(Packet *p);
/**
* Notify the admin connection that the rcon command has finished.
* string The command as requested by the admin connection.
* @param p The packet that was just received.
* @return The state the network should have.
*/
virtual NetworkRecvStatus Receive_SERVER_RCON_END(Packet *p);
NetworkRecvStatus HandlePacket(Packet *p);
public:
NetworkRecvStatus CloseConnection(bool error = true);

View File

@ -189,8 +189,9 @@ bool NetworkContentSocketHandler::HandlePacket(Packet *p)
/**
* Receive a packet at TCP level
* @return Whether at least one packet was received.
*/
void NetworkContentSocketHandler::ReceivePackets()
bool NetworkContentSocketHandler::ReceivePackets()
{
/*
* We read only a few of the packets. This as receiving packets can be expensive
@ -212,12 +213,15 @@ void NetworkContentSocketHandler::ReceivePackets()
* What arbitrary number to choose is the ultimate question though.
*/
Packet *p;
int i = 42;
static const int MAX_PACKETS_TO_RECEIVE = 42;
int i = MAX_PACKETS_TO_RECEIVE;
while (--i != 0 && (p = this->ReceivePacket()) != NULL) {
bool cont = this->HandlePacket(p);
delete p;
if (!cont) return;
if (!cont) return true;
}
return i != MAX_PACKETS_TO_RECEIVE - 1;
}

View File

@ -206,7 +206,7 @@ public:
/** On destructing of this class, the socket needs to be closed */
virtual ~NetworkContentSocketHandler() { this->Close(); }
void ReceivePackets();
bool ReceivePackets();
};
#ifndef OPENTTD_MSU

View File

@ -480,6 +480,20 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendChat(NetworkAction action
return NETWORK_RECV_STATUS_OKAY;
}
/**
* Send a notification indicating the rcon command has completed.
* @param command The original command sent.
*/
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendRconEnd(const char *command)
{
Packet *p = new Packet(ADMIN_PACKET_SERVER_RCON_END);
p->Send_string(command);
this->SendPacket(p);
return NETWORK_RECV_STATUS_OKAY;
}
/**
* Send the reply of an rcon command.
* @param colour The colour of the text.
@ -509,7 +523,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p)
_redirect_console_to_admin = this->index;
IConsoleCmdExec(command);
_redirect_console_to_admin = INVALID_ADMIN_ID;
return NETWORK_RECV_STATUS_OKAY;
return this->SendRconEnd(command);
}
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet *p)
@ -526,6 +540,17 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Pack
return NETWORK_RECV_STATUS_OKAY;
}
NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_PING(Packet *p)
{
if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
uint32 d1 = p->Recv_uint32();
DEBUG(net, 2, "[admin] Ping from '%s' (%s): '%d'", this->admin_name, this->admin_version, d1);
return this->SendPong(d1);
}
/**
* Send console output of other clients.
* @param origin The origin of the string.
@ -554,10 +579,10 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origi
*/
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendGameScript(const char *json)
{
/* At the moment we cannot transmit anything larger than MTU. So the string
* has to be no longer than the length of the json + '\0' + 3 bytes of the
* packet header. */
if (strlen(json) + 1 + 3 >= SEND_MTU) return NETWORK_RECV_STATUS_OKAY;
/* At the moment we cannot transmit anything larger than MTU. So we limit
* the maximum amount of json data that can be sent. Account also for
* the trailing \0 of the string */
if (strlen(json) + 1 >= NETWORK_GAMESCRIPT_JSON_LENGTH) return NETWORK_RECV_STATUS_OKAY;
Packet *p = new Packet(ADMIN_PACKET_SERVER_GAMESCRIPT);
@ -567,6 +592,17 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendGameScript(const char *js
return NETWORK_RECV_STATUS_OKAY;
}
/** Send ping-reply (pong) to admin **/
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendPong(uint32 d1)
{
Packet *p = new Packet(ADMIN_PACKET_SERVER_PONG);
p->Send_uint32(d1);
this->SendPacket(p);
return NETWORK_RECV_STATUS_OKAY;
}
/** Send the names of the commands. */
NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames()
{

View File

@ -35,8 +35,10 @@ protected:
virtual NetworkRecvStatus Receive_ADMIN_CHAT(Packet *p);
virtual NetworkRecvStatus Receive_ADMIN_RCON(Packet *p);
virtual NetworkRecvStatus Receive_ADMIN_GAMESCRIPT(Packet *p);
virtual NetworkRecvStatus Receive_ADMIN_PING(Packet *p);
NetworkRecvStatus SendProtocol();
NetworkRecvStatus SendPong(uint32 d1);
public:
AdminUpdateFrequency update_frequency[ADMIN_UPDATE_END]; ///< Admin requested update intervals.
uint32 realtime_connect; ///< Time of connection.
@ -69,6 +71,7 @@ public:
NetworkRecvStatus SendGameScript(const char *json);
NetworkRecvStatus SendCmdNames();
NetworkRecvStatus SendCmdLogging(ClientID client_id, const CommandPacket *cp);
NetworkRecvStatus SendRconEnd(const char *command);
static void Send();
static void AcceptConnection(SOCKET s, const NetworkAddress &address);

View File

@ -778,8 +778,10 @@ void ClientNetworkContentSocketHandler::SendReceive()
}
if (this->CanSendReceive()) {
this->ReceivePackets();
this->lastActivity = _realtime_tick;
if (this->ReceivePackets()) {
/* Only update activity once a packet is received, instead of everytime we try it. */
this->lastActivity = _realtime_tick;
}
}
this->SendPackets();

View File

@ -84,6 +84,15 @@ void ScriptConfig::ClearConfigList()
this->settings.clear();
}
void ScriptConfig::AnchorUnchangeableSettings()
{
for (ScriptConfigItemList::const_iterator it = this->GetConfigList()->begin(); it != this->GetConfigList()->end(); it++) {
if (((*it).flags & SCRIPTCONFIG_INGAME) == 0) {
this->SetSetting((*it).name, this->GetSetting((*it).name));
}
}
}
int ScriptConfig::GetSetting(const char *name) const
{
SettingValueList::const_iterator it = this->settings.find(name);

View File

@ -107,6 +107,16 @@ public:
SSS_FORCE_GAME, ///< Get the Script config from the current game
};
/**
* As long as the default of a setting has not been changed, the value of
* the setting is not stored. This to allow changing the difficulty setting
* without having to reset the script's config. However, when a setting may
* not be changed in game, we must "anchor" this value to what the setting
* would be at the time of starting. Otherwise changing the difficulty
* setting would change the setting's value (which isn't allowed).
*/
void AnchorUnchangeableSettings();
/**
* Get the value of a setting for this config. It might fallback to his
* 'info' to find the default value (if not set or if not-custom difficulty