Merge branch 'master' into jgrpp
# Conflicts: # src/network/network_server.h # src/pathfinder/yapf/yapf_road.cpp # src/viewport.cpp
This commit is contained in:
@@ -4,3 +4,5 @@
|
|||||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
AILog.Info("1.10 API compatibility in effect.");
|
||||||
|
6
bin/ai/compat_1.11.nut
Normal file
6
bin/ai/compat_1.11.nut
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
@@ -4,7 +4,7 @@ class Regression extends AIInfo {
|
|||||||
function GetShortName() { return "REGR"; }
|
function GetShortName() { return "REGR"; }
|
||||||
function GetDescription() { return "This runs regression-tests on some commands. On the same map the result should always be the same."; }
|
function GetDescription() { return "This runs regression-tests on some commands. On the same map the result should always be the same."; }
|
||||||
function GetVersion() { return 1; }
|
function GetVersion() { return 1; }
|
||||||
function GetAPIVersion() { return "1.10"; }
|
function GetAPIVersion() { return "1.11"; }
|
||||||
function GetDate() { return "2007-03-18"; }
|
function GetDate() { return "2007-03-18"; }
|
||||||
function CreateInstance() { return "Regression"; }
|
function CreateInstance() { return "Regression"; }
|
||||||
}
|
}
|
||||||
|
@@ -4,3 +4,5 @@
|
|||||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
GSLog.Info("1.10 API compatibility in effect.");
|
||||||
|
6
bin/game/compat_1.11.nut
Normal file
6
bin/game/compat_1.11.nut
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
@@ -1,6 +1,6 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
set OPENTTD_VERSION=1.10.0
|
set OPENTTD_VERSION=1.11.0
|
||||||
set OPENSFX_VERSION=0.8.0
|
set OPENSFX_VERSION=0.8.0
|
||||||
set NOSOUND_VERSION=0.8.0
|
set NOSOUND_VERSION=0.8.0
|
||||||
set OPENGFX_VERSION=1.2.0
|
set OPENGFX_VERSION=1.2.0
|
||||||
|
@@ -17,9 +17,9 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
Name: openttd
|
Name: openttd
|
||||||
Version: 1.10.beta2
|
Version: 1.11.beta1
|
||||||
Release: 0
|
Release: 0
|
||||||
%define srcver 1.10.0-beta2
|
%define srcver 1.11.0-beta1
|
||||||
Summary: An open source reimplementation of Chris Sawyer's Transport Tycoon Deluxe
|
Summary: An open source reimplementation of Chris Sawyer's Transport Tycoon Deluxe
|
||||||
License: GPL-2.0
|
License: GPL-2.0
|
||||||
Group: Amusements/Games/Strategy/Other
|
Group: Amusements/Games/Strategy/Other
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
# Version numbers to update
|
# Version numbers to update
|
||||||
!define APPV_MAJOR 1
|
!define APPV_MAJOR 1
|
||||||
!define APPV_MINOR 10
|
!define APPV_MINOR 11
|
||||||
!define APPV_MAINT 0
|
!define APPV_MAINT 0
|
||||||
!define APPV_BUILD 1
|
!define APPV_BUILD 0
|
||||||
!define APPV_EXTRA "-beta2"
|
!define APPV_EXTRA "-beta1"
|
||||||
|
|
||||||
!define APPNAME "OpenTTD" ; Define application name
|
!define APPNAME "OpenTTD" ; Define application name
|
||||||
!define APPVERSION "${APPV_MAJOR}.${APPV_MINOR}.${APPV_MAINT}${APPV_EXTRA}" ; Define application version
|
!define APPVERSION "${APPV_MAJOR}.${APPV_MINOR}.${APPV_MAINT}${APPV_EXTRA}" ; Define application version
|
||||||
|
6
src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp
vendored
6
src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp
vendored
@@ -38,7 +38,7 @@ void sqstd_printcallstack(HSQUIRRELVM v)
|
|||||||
src = si.source;
|
src = si.source;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pf(v,"*FUNCTION [%s()] %s line [%d]\n",fn,src,si.line);
|
pf(v,"*FUNCTION [%s()] %s line [" OTTD_PRINTF64 "]\n",fn,src,si.line);
|
||||||
level++;
|
level++;
|
||||||
}
|
}
|
||||||
level=0;
|
level=0;
|
||||||
@@ -56,7 +56,7 @@ void sqstd_printcallstack(HSQUIRRELVM v)
|
|||||||
break;
|
break;
|
||||||
case OT_INTEGER:
|
case OT_INTEGER:
|
||||||
sq_getinteger(v,-1,&i);
|
sq_getinteger(v,-1,&i);
|
||||||
pf(v,"[%s] %d\n",name,i);
|
pf(v,"[%s] " OTTD_PRINTF64 "\n",name,i);
|
||||||
break;
|
break;
|
||||||
case OT_FLOAT:
|
case OT_FLOAT:
|
||||||
sq_getfloat(v,-1,&f);
|
sq_getfloat(v,-1,&f);
|
||||||
@@ -134,7 +134,7 @@ void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSourc
|
|||||||
{
|
{
|
||||||
SQPRINTFUNCTION pf = sq_getprintfunc(v);
|
SQPRINTFUNCTION pf = sq_getprintfunc(v);
|
||||||
if(pf) {
|
if(pf) {
|
||||||
pf(v,"%s line = (%d) column = (%d) : error %s\n",sSource,line,column,sErr);
|
pf(v,"%s line = (" OTTD_PRINTF64 ") column = (" OTTD_PRINTF64 ") : error %s\n",sSource,line,column,sErr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
src/3rdparty/squirrel/squirrel/sqbaselib.cpp
vendored
2
src/3rdparty/squirrel/squirrel/sqbaselib.cpp
vendored
@@ -219,7 +219,7 @@ static SQInteger base_array(HSQUIRRELVM v)
|
|||||||
SQInteger nInitialSize = tointeger(stack_get(v,2));
|
SQInteger nInitialSize = tointeger(stack_get(v,2));
|
||||||
SQInteger ret = 1;
|
SQInteger ret = 1;
|
||||||
if (nInitialSize < 0) {
|
if (nInitialSize < 0) {
|
||||||
v->Raise_Error("can't create/resize array with/to size %d", nInitialSize);
|
v->Raise_Error("can't create/resize array with/to size " OTTD_PRINTF64, nInitialSize);
|
||||||
nInitialSize = 0;
|
nInitialSize = 0;
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
2
src/3rdparty/squirrel/squirrel/sqdebug.cpp
vendored
2
src/3rdparty/squirrel/squirrel/sqdebug.cpp
vendored
@@ -122,5 +122,5 @@ void SQVM::Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger ty
|
|||||||
StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes);
|
StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Raise_Error("parameter %d has an invalid type '%s' ; expected: '%s'", nparam, IdType2Name((SQObjectType)type), _stringval(exptypes));
|
Raise_Error("parameter " OTTD_PRINTF64 " has an invalid type '%s' ; expected: '%s'", nparam, IdType2Name((SQObjectType)type), _stringval(exptypes));
|
||||||
}
|
}
|
||||||
|
@@ -179,6 +179,7 @@ struct AIListWindow : public Window {
|
|||||||
InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_AI);
|
InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_AI);
|
||||||
InvalidateWindowClassesData(WC_AI_SETTINGS);
|
InvalidateWindowClassesData(WC_AI_SETTINGS);
|
||||||
DeleteWindowByClass(WC_QUERY_STRING);
|
DeleteWindowByClass(WC_QUERY_STRING);
|
||||||
|
InvalidateWindowClassesData(WC_TEXTFILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnClick(Point pt, int widget, int click_count) override
|
void OnClick(Point pt, int widget, int click_count) override
|
||||||
@@ -640,15 +641,24 @@ struct ScriptTextfileWindow : public TextfileWindow {
|
|||||||
|
|
||||||
ScriptTextfileWindow(TextfileType file_type, CompanyID slot) : TextfileWindow(file_type), slot(slot)
|
ScriptTextfileWindow(TextfileType file_type, CompanyID slot) : TextfileWindow(file_type), slot(slot)
|
||||||
{
|
{
|
||||||
const char *textfile = GetConfig(slot)->GetTextfile(file_type, slot);
|
this->OnInvalidateData();
|
||||||
this->LoadTextfile(textfile, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetStringParameters(int widget) const override
|
void SetStringParameters(int widget) const override
|
||||||
{
|
{
|
||||||
if (widget == WID_TF_CAPTION) {
|
if (widget == WID_TF_CAPTION) {
|
||||||
SetDParam(0, (slot == OWNER_DEITY) ? STR_CONTENT_TYPE_GAME_SCRIPT : STR_CONTENT_TYPE_AI);
|
SetDParam(0, (slot == OWNER_DEITY) ? STR_CONTENT_TYPE_GAME_SCRIPT : STR_CONTENT_TYPE_AI);
|
||||||
SetDParamStr(1, GetConfig(slot)->GetName());
|
SetDParamStr(1, GetConfig(slot)->GetInfo()->GetName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnInvalidateData(int data = 0, bool gui_scope = true) override
|
||||||
|
{
|
||||||
|
const char *textfile = GetConfig(slot)->GetTextfile(file_type, slot);
|
||||||
|
if (textfile == nullptr) {
|
||||||
|
delete this;
|
||||||
|
} else {
|
||||||
|
this->LoadTextfile(textfile, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -27,7 +27,8 @@ static bool CheckAPIVersion(const char *api_version)
|
|||||||
return strcmp(api_version, "0.7") == 0 || strcmp(api_version, "1.0") == 0 || strcmp(api_version, "1.1") == 0 ||
|
return strcmp(api_version, "0.7") == 0 || strcmp(api_version, "1.0") == 0 || strcmp(api_version, "1.1") == 0 ||
|
||||||
strcmp(api_version, "1.2") == 0 || strcmp(api_version, "1.3") == 0 || strcmp(api_version, "1.4") == 0 ||
|
strcmp(api_version, "1.2") == 0 || strcmp(api_version, "1.3") == 0 || strcmp(api_version, "1.4") == 0 ||
|
||||||
strcmp(api_version, "1.5") == 0 || strcmp(api_version, "1.6") == 0 || strcmp(api_version, "1.7") == 0 ||
|
strcmp(api_version, "1.5") == 0 || strcmp(api_version, "1.6") == 0 || strcmp(api_version, "1.7") == 0 ||
|
||||||
strcmp(api_version, "1.8") == 0 || strcmp(api_version, "1.9") == 0 || strcmp(api_version, "1.10") == 0;
|
strcmp(api_version, "1.8") == 0 || strcmp(api_version, "1.9") == 0 || strcmp(api_version, "1.10") == 0 ||
|
||||||
|
strcmp(api_version, "1.11") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
|
|
||||||
static const uint ICON_TOKEN_COUNT = 20; ///< Maximum number of tokens in one command
|
static const uint ICON_TOKEN_COUNT = 20; ///< Maximum number of tokens in one command
|
||||||
|
static const uint ICON_MAX_RECURSE = 10; ///< Maximum number of recursion
|
||||||
|
|
||||||
/* console parser */
|
/* console parser */
|
||||||
IConsoleCmd *_iconsole_cmds; ///< list of registered commands
|
IConsoleCmd *_iconsole_cmds; ///< list of registered commands
|
||||||
@@ -317,13 +318,18 @@ IConsoleAlias *IConsoleAliasGet(const char *name)
|
|||||||
* @param tokencount the number of parameters passed
|
* @param tokencount the number of parameters passed
|
||||||
* @param *tokens are the parameters given to the original command (0 is the first param)
|
* @param *tokens are the parameters given to the original command (0 is the first param)
|
||||||
*/
|
*/
|
||||||
static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[ICON_TOKEN_COUNT])
|
static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[ICON_TOKEN_COUNT], const uint recurse_count)
|
||||||
{
|
{
|
||||||
char alias_buffer[ICON_MAX_STREAMSIZE] = { '\0' };
|
char alias_buffer[ICON_MAX_STREAMSIZE] = { '\0' };
|
||||||
char *alias_stream = alias_buffer;
|
char *alias_stream = alias_buffer;
|
||||||
|
|
||||||
DEBUG(console, 6, "Requested command is an alias; parsing...");
|
DEBUG(console, 6, "Requested command is an alias; parsing...");
|
||||||
|
|
||||||
|
if (recurse_count > ICON_MAX_RECURSE) {
|
||||||
|
IConsoleError("Too many alias expansions, recursion limit reached. Aborting");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (const char *cmdptr = alias->cmdline; *cmdptr != '\0'; cmdptr++) {
|
for (const char *cmdptr = alias->cmdline; *cmdptr != '\0'; cmdptr++) {
|
||||||
switch (*cmdptr) {
|
switch (*cmdptr) {
|
||||||
case '\'': // ' will double for ""
|
case '\'': // ' will double for ""
|
||||||
@@ -331,7 +337,7 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ';': // Cmd separator; execute previous and start new command
|
case ';': // Cmd separator; execute previous and start new command
|
||||||
IConsoleCmdExec(alias_buffer);
|
IConsoleCmdExec(alias_buffer, recurse_count);
|
||||||
|
|
||||||
alias_stream = alias_buffer;
|
alias_stream = alias_buffer;
|
||||||
*alias_stream = '\0'; // Make sure the new command is terminated.
|
*alias_stream = '\0'; // Make sure the new command is terminated.
|
||||||
@@ -391,7 +397,7 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IConsoleCmdExec(alias_buffer);
|
IConsoleCmdExec(alias_buffer, recurse_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -399,7 +405,7 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char
|
|||||||
* individual tokens (separated by spaces), then execute it if possible
|
* individual tokens (separated by spaces), then execute it if possible
|
||||||
* @param cmdstr string to be parsed and executed
|
* @param cmdstr string to be parsed and executed
|
||||||
*/
|
*/
|
||||||
void IConsoleCmdExec(const char *cmdstr)
|
void IConsoleCmdExec(const char *cmdstr, const uint recurse_count)
|
||||||
{
|
{
|
||||||
const char *cmdptr;
|
const char *cmdptr;
|
||||||
char *tokens[ICON_TOKEN_COUNT], tokenstream[ICON_MAX_STREAMSIZE];
|
char *tokens[ICON_TOKEN_COUNT], tokenstream[ICON_MAX_STREAMSIZE];
|
||||||
@@ -505,7 +511,7 @@ void IConsoleCmdExec(const char *cmdstr)
|
|||||||
t_index--;
|
t_index--;
|
||||||
IConsoleAlias *alias = IConsoleAliasGet(tokens[0]);
|
IConsoleAlias *alias = IConsoleAliasGet(tokens[0]);
|
||||||
if (alias != nullptr) {
|
if (alias != nullptr) {
|
||||||
IConsoleAliasExec(alias, t_index, &tokens[1]);
|
IConsoleAliasExec(alias, t_index, &tokens[1], recurse_count + 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -526,7 +526,7 @@ DEF_CONSOLE_CMD(ConClearBuffer)
|
|||||||
* Network Core Console Commands
|
* Network Core Console Commands
|
||||||
**********************************/
|
**********************************/
|
||||||
|
|
||||||
static bool ConKickOrBan(const char *argv, bool ban)
|
static bool ConKickOrBan(const char *argv, bool ban, const char *reason)
|
||||||
{
|
{
|
||||||
uint n;
|
uint n;
|
||||||
|
|
||||||
@@ -550,14 +550,14 @@ static bool ConKickOrBan(const char *argv, bool ban)
|
|||||||
|
|
||||||
if (!ban) {
|
if (!ban) {
|
||||||
/* Kick only this client, not all clients with that IP */
|
/* Kick only this client, not all clients with that IP */
|
||||||
NetworkServerKickClient(client_id);
|
NetworkServerKickClient(client_id, reason);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When banning, kick+ban all clients with that IP */
|
/* When banning, kick+ban all clients with that IP */
|
||||||
n = NetworkServerKickOrBanIP(client_id, ban);
|
n = NetworkServerKickOrBanIP(client_id, ban, reason);
|
||||||
} else {
|
} else {
|
||||||
n = NetworkServerKickOrBanIP(argv, ban);
|
n = NetworkServerKickOrBanIP(argv, ban, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
@@ -572,28 +572,48 @@ static bool ConKickOrBan(const char *argv, bool ban)
|
|||||||
DEF_CONSOLE_CMD(ConKick)
|
DEF_CONSOLE_CMD(ConKick)
|
||||||
{
|
{
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
IConsoleHelp("Kick a client from a network game. Usage: 'kick <ip | client-id>'");
|
IConsoleHelp("Kick a client from a network game. Usage: 'kick <ip | client-id> [<kick-reason>]'");
|
||||||
IConsoleHelp("For client-id's, see the command 'clients'");
|
IConsoleHelp("For client-id's, see the command 'clients'");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc != 2) return false;
|
if (argc != 2 && argc != 3) return false;
|
||||||
|
|
||||||
return ConKickOrBan(argv[1], false);
|
/* No reason supplied for kicking */
|
||||||
|
if (argc == 2) return ConKickOrBan(argv[1], false, nullptr);
|
||||||
|
|
||||||
|
/* Reason for kicking supplied */
|
||||||
|
size_t kick_message_length = strlen(argv[2]);
|
||||||
|
if (kick_message_length >= 255) {
|
||||||
|
IConsolePrintF(CC_ERROR, "ERROR: Maximum kick message length is 254 characters. You entered %d characters.", kick_message_length);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return ConKickOrBan(argv[1], false, argv[2]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_CONSOLE_CMD(ConBan)
|
DEF_CONSOLE_CMD(ConBan)
|
||||||
{
|
{
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
IConsoleHelp("Ban a client from a network game. Usage: 'ban <ip | client-id>'");
|
IConsoleHelp("Ban a client from a network game. Usage: 'ban <ip | client-id> [<ban-reason>]'");
|
||||||
IConsoleHelp("For client-id's, see the command 'clients'");
|
IConsoleHelp("For client-id's, see the command 'clients'");
|
||||||
IConsoleHelp("If the client is no longer online, you can still ban his/her IP");
|
IConsoleHelp("If the client is no longer online, you can still ban his/her IP");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc != 2) return false;
|
if (argc != 2 && argc != 3) return false;
|
||||||
|
|
||||||
return ConKickOrBan(argv[1], true);
|
/* No reason supplied for kicking */
|
||||||
|
if (argc == 2) return ConKickOrBan(argv[1], true, nullptr);
|
||||||
|
|
||||||
|
/* Reason for kicking supplied */
|
||||||
|
size_t kick_message_length = strlen(argv[2]);
|
||||||
|
if (kick_message_length >= 255) {
|
||||||
|
IConsolePrintF(CC_ERROR, "ERROR: Maximum kick message length is 254 characters. You entered %d characters.", kick_message_length);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return ConKickOrBan(argv[1], true, argv[2]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_CONSOLE_CMD(ConUnBan)
|
DEF_CONSOLE_CMD(ConUnBan)
|
||||||
|
@@ -28,7 +28,7 @@ void IConsoleWarning(const char *string);
|
|||||||
void IConsoleError(const char *string);
|
void IConsoleError(const char *string);
|
||||||
|
|
||||||
/* Parser */
|
/* Parser */
|
||||||
void IConsoleCmdExec(const char *cmdstr);
|
void IConsoleCmdExec(const char *cmdstr, const uint recurse_count = 0);
|
||||||
|
|
||||||
bool IsValidConsoleColour(TextColour c);
|
bool IsValidConsoleColour(TextColour c);
|
||||||
|
|
||||||
|
@@ -28,6 +28,8 @@ INSTANTIATE_POOL_METHODS(Depot)
|
|||||||
*/
|
*/
|
||||||
Depot::~Depot()
|
Depot::~Depot()
|
||||||
{
|
{
|
||||||
|
free(this->name);
|
||||||
|
|
||||||
if (CleaningPool()) return;
|
if (CleaningPool()) return;
|
||||||
|
|
||||||
if (!IsDepotTile(this->xy) || GetDepotIndex(this->xy) != this->index) {
|
if (!IsDepotTile(this->xy) || GetDepotIndex(this->xy) != this->index) {
|
||||||
|
@@ -24,7 +24,8 @@ static bool CheckAPIVersion(const char *api_version)
|
|||||||
{
|
{
|
||||||
return strcmp(api_version, "1.2") == 0 || strcmp(api_version, "1.3") == 0 || strcmp(api_version, "1.4") == 0 ||
|
return strcmp(api_version, "1.2") == 0 || strcmp(api_version, "1.3") == 0 || strcmp(api_version, "1.4") == 0 ||
|
||||||
strcmp(api_version, "1.5") == 0 || strcmp(api_version, "1.6") == 0 || strcmp(api_version, "1.7") == 0 ||
|
strcmp(api_version, "1.5") == 0 || strcmp(api_version, "1.6") == 0 || strcmp(api_version, "1.7") == 0 ||
|
||||||
strcmp(api_version, "1.8") == 0 || strcmp(api_version, "1.9") == 0 || strcmp(api_version, "1.10") == 0;
|
strcmp(api_version, "1.8") == 0 || strcmp(api_version, "1.9") == 0 || strcmp(api_version, "1.10") == 0 ||
|
||||||
|
strcmp(api_version, "1.11") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
@@ -1102,6 +1102,7 @@ public:
|
|||||||
}
|
}
|
||||||
this->groups.ForceRebuild();
|
this->groups.ForceRebuild();
|
||||||
this->BuildGroupList(this->owner);
|
this->BuildGroupList(this->owner);
|
||||||
|
this->group_sb->SetCount((uint)this->groups.size());
|
||||||
id_g = find_index(this->groups, g);
|
id_g = find_index(this->groups, g);
|
||||||
}
|
}
|
||||||
this->group_sb->ScrollTowards(id_g);
|
this->group_sb->ScrollTowards(id_g);
|
||||||
|
@@ -1395,6 +1395,8 @@ STR_CONFIG_SETTING_POPULATION_IN_LABEL :Zobrazovat popu
|
|||||||
STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT :Zobrazovat městskou populaci u názvu města na mapě
|
STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT :Zobrazovat městskou populaci u názvu města na mapě
|
||||||
STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS :Tloušťky čar v grafech: {STRING}
|
STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS :Tloušťky čar v grafech: {STRING}
|
||||||
STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :Tloušťka čáry v grafech. Tenká čára se čte přesněji, silnější je lépe viditelná a barva je snadněji rozpoznatelná.
|
STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :Tloušťka čáry v grafech. Tenká čára se čte přesněji, silnější je lépe viditelná a barva je snadněji rozpoznatelná.
|
||||||
|
STR_CONFIG_SETTING_SHOW_NEWGRF_NAME :Zobrazovat název NewGRF v okně nákupu vozidel: {STRING}
|
||||||
|
STR_CONFIG_SETTING_SHOW_NEWGRF_NAME_HELPTEXT :Přidá řádek do okna nákupu vozidel informující, ze které NewGRF vybrané vozidlo pochází.
|
||||||
|
|
||||||
STR_CONFIG_SETTING_LANDSCAPE :Klima: {STRING}
|
STR_CONFIG_SETTING_LANDSCAPE :Klima: {STRING}
|
||||||
STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :Klima určuje základy herního scénáře s rozdílnými druhy nákladu a požadavky na růst měst. Nové GRaFiky a Herní Skripty umožní ještě jemnější kontrolu
|
STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :Klima určuje základy herního scénáře s rozdílnými druhy nákladu a požadavky na růst měst. Nové GRaFiky a Herní Skripty umožní ještě jemnější kontrolu
|
||||||
@@ -1632,6 +1634,10 @@ STR_CONFIG_SETTING_NEWS_MESSAGES_FULL :Plná
|
|||||||
STR_CONFIG_SETTING_COLOURED_NEWS_YEAR :Barevné noviny se objeví v roce: {STRING}
|
STR_CONFIG_SETTING_COLOURED_NEWS_YEAR :Barevné noviny se objeví v roce: {STRING}
|
||||||
STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :Rok od kterého budou novinová oznámeni zobrazena v barvách. Před tímto rokem jsou černobílá.
|
STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT :Rok od kterého budou novinová oznámeni zobrazena v barvách. Před tímto rokem jsou černobílá.
|
||||||
STR_CONFIG_SETTING_STARTING_YEAR :Počáteční datum: {STRING}
|
STR_CONFIG_SETTING_STARTING_YEAR :Počáteční datum: {STRING}
|
||||||
|
STR_CONFIG_SETTING_ENDING_YEAR :Rok vyhodnocení: {STRING}
|
||||||
|
STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT :Rok, kdy je ve hře uzavřeno hodnocení společností. Na konci tohoto roku je zaznamenáno skóre společností a je zobrazena tabulka nejlepších společností, ale ve hře je možné pokračovat i dál.{}Pokud je nastaven rok před rokem počátku hry, tabulka s hodnocením nebude zobrazena nikdy.
|
||||||
|
STR_CONFIG_SETTING_ENDING_YEAR_VALUE :{NUM}
|
||||||
|
STR_CONFIG_SETTING_ENDING_YEAR_ZERO :Nikdy
|
||||||
STR_CONFIG_SETTING_SMOOTH_ECONOMY :Plynulé změny ekonomiky (více menších změn): {STRING}
|
STR_CONFIG_SETTING_SMOOTH_ECONOMY :Plynulé změny ekonomiky (více menších změn): {STRING}
|
||||||
STR_CONFIG_SETTING_SMOOTH_ECONOMY_HELPTEXT :Pokud je zapnuto, produkce průmyslu se mění častěji ale změny jsou menší. Toto nastavení většinou nemá vliv na průmysl, který je přidaný novou grafikou
|
STR_CONFIG_SETTING_SMOOTH_ECONOMY_HELPTEXT :Pokud je zapnuto, produkce průmyslu se mění častěji ale změny jsou menší. Toto nastavení většinou nemá vliv na průmysl, který je přidaný novou grafikou
|
||||||
STR_CONFIG_SETTING_ALLOW_SHARES :Povolit kupování podílu z ostatních společností: {STRING}
|
STR_CONFIG_SETTING_ALLOW_SHARES :Povolit kupování podílu z ostatních společností: {STRING}
|
||||||
@@ -3477,8 +3483,17 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}{CURRENC
|
|||||||
# Industry directory
|
# Industry directory
|
||||||
STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}Průmysl
|
STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}Průmysl
|
||||||
STR_INDUSTRY_DIRECTORY_NONE :{ORANGE}- Nic -
|
STR_INDUSTRY_DIRECTORY_NONE :{ORANGE}- Nic -
|
||||||
|
STR_INDUSTRY_DIRECTORY_ITEM_INFO :{BLACK}{CARGO_LONG}{STRING}{YELLOW} ({COMMA}% přepraveno){BLACK}
|
||||||
STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY}
|
STR_INDUSTRY_DIRECTORY_ITEM_NOPROD :{ORANGE}{INDUSTRY}
|
||||||
|
STR_INDUSTRY_DIRECTORY_ITEM_PROD1 :{ORANGE}{INDUSTRY} {STRING}
|
||||||
|
STR_INDUSTRY_DIRECTORY_ITEM_PROD2 :{ORANGE}{INDUSTRY} {STRING}, {STRING}
|
||||||
|
STR_INDUSTRY_DIRECTORY_ITEM_PROD3 :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING}
|
||||||
|
STR_INDUSTRY_DIRECTORY_ITEM_PRODMORE :{ORANGE}{INDUSTRY} {STRING}, {STRING}, {STRING} a {NUM} další...
|
||||||
STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}Název průmyslu - pohled na něj zaměříš kliknutím na jeho jméno. Při stisknutém Ctrl otevřeš nový pohled
|
STR_INDUSTRY_DIRECTORY_LIST_CAPTION :{BLACK}Název průmyslu - pohled na něj zaměříš kliknutím na jeho jméno. Při stisknutém Ctrl otevřeš nový pohled
|
||||||
|
STR_INDUSTRY_DIRECTORY_ACCEPTED_CARGO_FILTER :{BLACK}Přijímá náklad: {SILVER}{STRING}
|
||||||
|
STR_INDUSTRY_DIRECTORY_PRODUCED_CARGO_FILTER :{BLACK}Produkuje náklad: {SILVER}{STRING}
|
||||||
|
STR_INDUSTRY_DIRECTORY_FILTER_ALL_TYPES :Všechny druhy nákladu
|
||||||
|
STR_INDUSTRY_DIRECTORY_FILTER_NONE :Žádný
|
||||||
|
|
||||||
# Industry view
|
# Industry view
|
||||||
STR_INDUSTRY_VIEW_CAPTION :{WHITE}{INDUSTRY}
|
STR_INDUSTRY_VIEW_CAPTION :{WHITE}{INDUSTRY}
|
||||||
@@ -4256,6 +4271,13 @@ STR_AI_LIST_ACCEPT_TOOLTIP :{BLACK}Vybrat o
|
|||||||
STR_AI_LIST_CANCEL :{BLACK}Zrušit
|
STR_AI_LIST_CANCEL :{BLACK}Zrušit
|
||||||
STR_AI_LIST_CANCEL_TOOLTIP :{BLACK}Neměňte skript
|
STR_AI_LIST_CANCEL_TOOLTIP :{BLACK}Neměňte skript
|
||||||
|
|
||||||
|
STR_SCREENSHOT_CAPTION :{WHITE}Pořídit snímek obrazovky
|
||||||
|
STR_SCREENSHOT_SCREENSHOT :{BLACK}Běžný snímek obrazovky
|
||||||
|
STR_SCREENSHOT_ZOOMIN_SCREENSHOT :{BLACK}Snímek obrazovky v úplném přiblížení
|
||||||
|
STR_SCREENSHOT_DEFAULTZOOM_SCREENSHOT :{BLACK}Snímek obrazovky ve výchozím přiblížení
|
||||||
|
STR_SCREENSHOT_WORLD_SCREENSHOT :{BLACK}Snímek celé mapy
|
||||||
|
STR_SCREENSHOT_HEIGHTMAP_SCREENSHOT :{BLACK}Snímek výškové mapy
|
||||||
|
STR_SCREENSHOT_MINIMAP_SCREENSHOT :{BLACK}Snímek (náhledové) mapy světa
|
||||||
|
|
||||||
# AI Parameters
|
# AI Parameters
|
||||||
STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} Parametry
|
STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} Parametry
|
||||||
|
@@ -2402,6 +2402,7 @@ STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Wrong pa
|
|||||||
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}The server is full
|
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}The server is full
|
||||||
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}You are banned from this server
|
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}You are banned from this server
|
||||||
STR_NETWORK_ERROR_KICKED :{WHITE}You were kicked out of the game
|
STR_NETWORK_ERROR_KICKED :{WHITE}You were kicked out of the game
|
||||||
|
STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}Reason: {RAW_STRING}
|
||||||
STR_NETWORK_ERROR_CHEATER :{WHITE}Cheating is not allowed on this server
|
STR_NETWORK_ERROR_CHEATER :{WHITE}Cheating is not allowed on this server
|
||||||
STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}You were sending too many commands to the server
|
STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}You were sending too many commands to the server
|
||||||
STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}You took too long to enter the password
|
STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}You took too long to enter the password
|
||||||
@@ -2465,6 +2466,7 @@ STR_NETWORK_MESSAGE_MONEY_GIVEN :*** {RAW_STRING
|
|||||||
STR_NETWORK_MESSAGE_MONEY_GIVE_SRC_DESCRIPTION :{RAW_STRING} ({COMPANY})
|
STR_NETWORK_MESSAGE_MONEY_GIVE_SRC_DESCRIPTION :{RAW_STRING} ({COMPANY})
|
||||||
STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}The server closed the session
|
STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}The server closed the session
|
||||||
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}The server is restarting...{}Please wait...
|
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}The server is restarting...{}Please wait...
|
||||||
|
STR_NETWORK_MESSAGE_KICKED :*** {RAW_STRING} was kicked. Reason: ({RAW_STRING})
|
||||||
|
|
||||||
# Content downloading window
|
# Content downloading window
|
||||||
STR_CONTENT_TITLE :{WHITE}Content downloading
|
STR_CONTENT_TITLE :{WHITE}Content downloading
|
||||||
|
@@ -799,8 +799,8 @@ STR_NEWS_FIRST_SHIP_ARRIVAL :{BIG_FONT}{BLAC
|
|||||||
STR_NEWS_FIRST_AIRCRAFT_ARRIVAL :{BIG_FONT}{BLACK}시민들이 축하하고 있습니다 . . .{}{STATION}에 처음으로 항공기가 도착했습니다!
|
STR_NEWS_FIRST_AIRCRAFT_ARRIVAL :{BIG_FONT}{BLACK}시민들이 축하하고 있습니다 . . .{}{STATION}에 처음으로 항공기가 도착했습니다!
|
||||||
|
|
||||||
STR_NEWS_TRAIN_CRASH :{BIG_FONT}{BLACK}열차 충돌 사고!{}충돌로 인한 폭발로 {COMMA}명의 사망자가 발생하였습니다!
|
STR_NEWS_TRAIN_CRASH :{BIG_FONT}{BLACK}열차 충돌 사고!{}충돌로 인한 폭발로 {COMMA}명의 사망자가 발생하였습니다!
|
||||||
STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER :{BIG_FONT}{BLACK}차량 충돌!{}열차와의 충돌로 인해 운전자가 사망했습니다!
|
STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER :{BIG_FONT}{BLACK}차량 충돌!{}열차 충돌로 운전자가 사망했습니다!
|
||||||
STR_NEWS_ROAD_VEHICLE_CRASH :{BIG_FONT}{BLACK}차량 충돌!{}열차와의 충돌로 {COMMA}명이 사망했습니다!
|
STR_NEWS_ROAD_VEHICLE_CRASH :{BIG_FONT}{BLACK}차량 충돌!{}열차 충돌로 {COMMA}명이 사망했습니다!
|
||||||
STR_NEWS_AIRCRAFT_CRASH :{BIG_FONT}{BLACK}항공기 충돌사고 발생!{}{COMMA}명이 {STATION}공항에서 사망하였습니다!
|
STR_NEWS_AIRCRAFT_CRASH :{BIG_FONT}{BLACK}항공기 충돌사고 발생!{}{COMMA}명이 {STATION}공항에서 사망하였습니다!
|
||||||
STR_NEWS_PLANE_CRASH_OUT_OF_FUEL :{BIG_FONT}{BLACK}항공기 추락사고 발생!{}연료 부족으로 인하여 {COMMA}명이 사망하였습니다!
|
STR_NEWS_PLANE_CRASH_OUT_OF_FUEL :{BIG_FONT}{BLACK}항공기 추락사고 발생!{}연료 부족으로 인하여 {COMMA}명이 사망하였습니다!
|
||||||
|
|
||||||
@@ -1739,7 +1739,7 @@ STR_CONFIG_SETTING_TOWN_LAYOUT_BETTER_ROADS :개선된 도
|
|||||||
STR_CONFIG_SETTING_TOWN_LAYOUT_2X2_GRID :2x2 칸
|
STR_CONFIG_SETTING_TOWN_LAYOUT_2X2_GRID :2x2 칸
|
||||||
STR_CONFIG_SETTING_TOWN_LAYOUT_3X3_GRID :3x3 칸
|
STR_CONFIG_SETTING_TOWN_LAYOUT_3X3_GRID :3x3 칸
|
||||||
STR_CONFIG_SETTING_TOWN_LAYOUT_RANDOM :무작위
|
STR_CONFIG_SETTING_TOWN_LAYOUT_RANDOM :무작위
|
||||||
STR_CONFIG_SETTING_ALLOW_TOWN_ROADS :도시 스스로의 도로 건설 허용: {STRING}
|
STR_CONFIG_SETTING_ALLOW_TOWN_ROADS :도시 스스로 도로를 건설하는 것을 허용: {STRING}
|
||||||
STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT :도시가 성장하기 위해 도로를 건설할 수 있도록 허용합니다. 도시 당국이 스스로 도로를 만들지 못하도록 하려면 이 설정을 끄십시오.
|
STR_CONFIG_SETTING_ALLOW_TOWN_ROADS_HELPTEXT :도시가 성장하기 위해 도로를 건설할 수 있도록 허용합니다. 도시 당국이 스스로 도로를 만들지 못하도록 하려면 이 설정을 끄십시오.
|
||||||
STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS :도시가 회사 소유의 선로에 건널목을 만드는 것을 허용: {STRING}
|
STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS :도시가 회사 소유의 선로에 건널목을 만드는 것을 허용: {STRING}
|
||||||
STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT :도시가 회사 소유의 선로에 건널목을 건설할 수 있도록 허용합니다.
|
STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT :도시가 회사 소유의 선로에 건널목을 건설할 수 있도록 허용합니다.
|
||||||
@@ -2369,7 +2369,7 @@ STR_COMPANY_PASSWORD_MAKE_DEFAULT_TOOLTIP :{BLACK}이 회
|
|||||||
STR_COMPANY_VIEW_JOIN :{BLACK}참여
|
STR_COMPANY_VIEW_JOIN :{BLACK}참여
|
||||||
STR_COMPANY_VIEW_JOIN_TOOLTIP :{BLACK}이 회사로 참가해서 플레이합니다
|
STR_COMPANY_VIEW_JOIN_TOOLTIP :{BLACK}이 회사로 참가해서 플레이합니다
|
||||||
STR_COMPANY_VIEW_PASSWORD :{BLACK}암호
|
STR_COMPANY_VIEW_PASSWORD :{BLACK}암호
|
||||||
STR_COMPANY_VIEW_PASSWORD_TOOLTIP :{BLACK}다른 참가자가 이 회사로의 플레이를 하지 못하도록 암호로 보호합니다
|
STR_COMPANY_VIEW_PASSWORD_TOOLTIP :{BLACK}다른 참가자가 이 회사에 참여하여 플레이하지 못 하도록 암호로 보호합니다
|
||||||
STR_COMPANY_VIEW_SET_PASSWORD :{BLACK}회사 암호 설정
|
STR_COMPANY_VIEW_SET_PASSWORD :{BLACK}회사 암호 설정
|
||||||
|
|
||||||
# Network chat
|
# Network chat
|
||||||
@@ -2402,6 +2402,7 @@ STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}잘못
|
|||||||
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}서버에 인원이 가득 찼습니다
|
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}서버에 인원이 가득 찼습니다
|
||||||
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}서버 관리자에 의해 접속이 차단되었습니다
|
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}서버 관리자에 의해 접속이 차단되었습니다
|
||||||
STR_NETWORK_ERROR_KICKED :{WHITE}서버에서 강제로 추방되었습니다
|
STR_NETWORK_ERROR_KICKED :{WHITE}서버에서 강제로 추방되었습니다
|
||||||
|
STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}사유: {STRING}
|
||||||
STR_NETWORK_ERROR_CHEATER :{WHITE}이 서버에서 치트를 사용할 수 없습니다
|
STR_NETWORK_ERROR_CHEATER :{WHITE}이 서버에서 치트를 사용할 수 없습니다
|
||||||
STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}서버에 너무 많은 명령을 보냈습니다
|
STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}서버에 너무 많은 명령을 보냈습니다
|
||||||
STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}비밀번호 입력 시간을 초과하였습니다
|
STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}비밀번호 입력 시간을 초과하였습니다
|
||||||
@@ -2465,6 +2466,7 @@ STR_NETWORK_MESSAGE_MONEY_GIVEN :*** {STRING}
|
|||||||
STR_NETWORK_MESSAGE_MONEY_GIVE_SRC_DESCRIPTION :{STRING} ({COMPANY})
|
STR_NETWORK_MESSAGE_MONEY_GIVE_SRC_DESCRIPTION :{STRING} ({COMPANY})
|
||||||
STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}서버가 게임을 종료하였습니다
|
STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}서버가 게임을 종료하였습니다
|
||||||
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}서버가 재시작되고 있습니다...{}기다려주세요...
|
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}서버가 재시작되고 있습니다...{}기다려주세요...
|
||||||
|
STR_NETWORK_MESSAGE_KICKED :*** {STRING} - 서버에서 강제로 추방되었습니다. 사유: ({STRING})
|
||||||
|
|
||||||
# Content downloading window
|
# Content downloading window
|
||||||
STR_CONTENT_TITLE :{WHITE}콘텐츠 다운로드
|
STR_CONTENT_TITLE :{WHITE}콘텐츠 다운로드
|
||||||
|
@@ -2320,6 +2320,7 @@ STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Неве
|
|||||||
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Сервер переполнен
|
STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Сервер переполнен
|
||||||
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Вас забанили на этом сервере
|
STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Вас забанили на этом сервере
|
||||||
STR_NETWORK_ERROR_KICKED :{WHITE}Вас выкинули из игры
|
STR_NETWORK_ERROR_KICKED :{WHITE}Вас выкинули из игры
|
||||||
|
STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}Причина: {STRING}
|
||||||
STR_NETWORK_ERROR_CHEATER :{WHITE}Чит-коды не разрешены на этом сервере
|
STR_NETWORK_ERROR_CHEATER :{WHITE}Чит-коды не разрешены на этом сервере
|
||||||
STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}Вы посылали на сервер слишком много команд
|
STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}Вы посылали на сервер слишком много команд
|
||||||
STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Вы не успели ввести пароль
|
STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}Вы не успели ввести пароль
|
||||||
@@ -2379,6 +2380,7 @@ STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} п
|
|||||||
STR_NETWORK_MESSAGE_GAVE_MONEY_AWAY :*** Вы передали {1:STRING} {2:CURRENCY_LONG}
|
STR_NETWORK_MESSAGE_GAVE_MONEY_AWAY :*** Вы передали {1:STRING} {2:CURRENCY_LONG}
|
||||||
STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Сервер закрыл сессию
|
STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Сервер закрыл сессию
|
||||||
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Сервер перезапускается...{}Пожалуйста, подождите...
|
STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Сервер перезапускается...{}Пожалуйста, подождите...
|
||||||
|
STR_NETWORK_MESSAGE_KICKED :*** {STRING} был исключён из игры. Причина: ({STRING})
|
||||||
|
|
||||||
# Content downloading window
|
# Content downloading window
|
||||||
STR_CONTENT_TITLE :{WHITE}Загрузка контента
|
STR_CONTENT_TITLE :{WHITE}Загрузка контента
|
||||||
|
@@ -15,11 +15,13 @@
|
|||||||
#include "midifile.hpp"
|
#include "midifile.hpp"
|
||||||
#include <fluidsynth.h>
|
#include <fluidsynth.h>
|
||||||
#include "../mixer.h"
|
#include "../mixer.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
fluid_settings_t* settings; ///< FluidSynth settings handle
|
fluid_settings_t* settings; ///< FluidSynth settings handle
|
||||||
fluid_synth_t* synth; ///< FluidSynth synthesizer handle
|
fluid_synth_t* synth; ///< FluidSynth synthesizer handle
|
||||||
fluid_player_t* player; ///< FluidSynth MIDI player handle
|
fluid_player_t* player; ///< FluidSynth MIDI player handle
|
||||||
|
std::mutex synth_mutex; ///< Guard mutex for synth access
|
||||||
} _midi; ///< Metadata about the midi we're playing.
|
} _midi; ///< Metadata about the midi we're playing.
|
||||||
|
|
||||||
/** Factory for the FluidSynth driver. */
|
/** Factory for the FluidSynth driver. */
|
||||||
@@ -42,12 +44,16 @@ static const char *default_sf[] = {
|
|||||||
|
|
||||||
static void RenderMusicStream(int16 *buffer, size_t samples)
|
static void RenderMusicStream(int16 *buffer, size_t samples)
|
||||||
{
|
{
|
||||||
if (!_midi.synth || !_midi.player) return;
|
std::unique_lock<std::mutex> lock{ _midi.synth_mutex, std::try_to_lock };
|
||||||
|
|
||||||
|
if (!lock.owns_lock() || !_midi.synth || !_midi.player) return;
|
||||||
fluid_synth_write_s16(_midi.synth, samples, buffer, 0, 2, buffer, 1, 2);
|
fluid_synth_write_s16(_midi.synth, samples, buffer, 0, 2, buffer, 1, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *MusicDriver_FluidSynth::Start(const char * const *param)
|
const char *MusicDriver_FluidSynth::Start(const char * const *param)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> lock{ _midi.synth_mutex };
|
||||||
|
|
||||||
const char *sfont_name = GetDriverParam(param, "soundfont");
|
const char *sfont_name = GetDriverParam(param, "soundfont");
|
||||||
int sfont_id;
|
int sfont_id;
|
||||||
|
|
||||||
@@ -59,6 +65,11 @@ const char *MusicDriver_FluidSynth::Start(const char * const *param)
|
|||||||
/* Don't try to lock sample data in memory, OTTD usually does not run with privileges allowing that */
|
/* Don't try to lock sample data in memory, OTTD usually does not run with privileges allowing that */
|
||||||
fluid_settings_setint(_midi.settings, "synth.lock-memory", 0);
|
fluid_settings_setint(_midi.settings, "synth.lock-memory", 0);
|
||||||
|
|
||||||
|
/* Install the music render routine and set up the samplerate */
|
||||||
|
uint32 samplerate = MxSetMusicSource(RenderMusicStream);
|
||||||
|
fluid_settings_setnum(_midi.settings, "synth.sample-rate", samplerate);
|
||||||
|
DEBUG(driver, 1, "Fluidsynth: samplerate %.0f", (float)samplerate);
|
||||||
|
|
||||||
/* Create the synthesizer. */
|
/* Create the synthesizer. */
|
||||||
_midi.synth = new_fluid_synth(_midi.settings);
|
_midi.synth = new_fluid_synth(_midi.settings);
|
||||||
if (!_midi.synth) return "Could not open synth";
|
if (!_midi.synth) return "Could not open synth";
|
||||||
@@ -81,19 +92,23 @@ const char *MusicDriver_FluidSynth::Start(const char * const *param)
|
|||||||
|
|
||||||
_midi.player = nullptr;
|
_midi.player = nullptr;
|
||||||
|
|
||||||
uint32 samplerate = MxSetMusicSource(RenderMusicStream);
|
|
||||||
fluid_synth_set_sample_rate(_midi.synth, samplerate);
|
|
||||||
DEBUG(driver, 1, "Fluidsynth: samplerate %.0f", (float)samplerate);
|
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MusicDriver_FluidSynth::Stop()
|
void MusicDriver_FluidSynth::Stop()
|
||||||
{
|
{
|
||||||
MxSetMusicSource(nullptr);
|
MxSetMusicSource(nullptr);
|
||||||
this->StopSong();
|
|
||||||
delete_fluid_synth(_midi.synth);
|
std::lock_guard<std::mutex> lock{ _midi.synth_mutex };
|
||||||
delete_fluid_settings(_midi.settings);
|
|
||||||
|
if (_midi.player != nullptr) delete_fluid_player(_midi.player);
|
||||||
|
_midi.player = nullptr;
|
||||||
|
|
||||||
|
if (_midi.synth != nullptr) delete_fluid_synth(_midi.synth);
|
||||||
|
_midi.synth = nullptr;
|
||||||
|
|
||||||
|
if (_midi.settings != nullptr) delete_fluid_settings(_midi.settings);
|
||||||
|
_midi.settings = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MusicDriver_FluidSynth::PlaySong(const MusicSongInfo &song)
|
void MusicDriver_FluidSynth::PlaySong(const MusicSongInfo &song)
|
||||||
@@ -106,6 +121,8 @@ void MusicDriver_FluidSynth::PlaySong(const MusicSongInfo &song)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock{ _midi.synth_mutex };
|
||||||
|
|
||||||
_midi.player = new_fluid_player(_midi.synth);
|
_midi.player = new_fluid_player(_midi.synth);
|
||||||
if (!_midi.player) {
|
if (!_midi.player) {
|
||||||
DEBUG(driver, 0, "Could not create midi player");
|
DEBUG(driver, 0, "Could not create midi player");
|
||||||
@@ -128,6 +145,8 @@ void MusicDriver_FluidSynth::PlaySong(const MusicSongInfo &song)
|
|||||||
|
|
||||||
void MusicDriver_FluidSynth::StopSong()
|
void MusicDriver_FluidSynth::StopSong()
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> lock{ _midi.synth_mutex };
|
||||||
|
|
||||||
if (!_midi.player) return;
|
if (!_midi.player) return;
|
||||||
|
|
||||||
fluid_player_stop(_midi.player);
|
fluid_player_stop(_midi.player);
|
||||||
@@ -142,6 +161,7 @@ void MusicDriver_FluidSynth::StopSong()
|
|||||||
|
|
||||||
bool MusicDriver_FluidSynth::IsSongPlaying()
|
bool MusicDriver_FluidSynth::IsSongPlaying()
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> lock{ _midi.synth_mutex };
|
||||||
if (!_midi.player) return false;
|
if (!_midi.player) return false;
|
||||||
|
|
||||||
return fluid_player_get_status(_midi.player) == FLUID_PLAYER_PLAYING;
|
return fluid_player_get_status(_midi.player) == FLUID_PLAYER_PLAYING;
|
||||||
@@ -149,6 +169,9 @@ bool MusicDriver_FluidSynth::IsSongPlaying()
|
|||||||
|
|
||||||
void MusicDriver_FluidSynth::SetVolume(byte vol)
|
void MusicDriver_FluidSynth::SetVolume(byte vol)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> lock{ _midi.synth_mutex };
|
||||||
|
if (_midi.settings == nullptr) return;
|
||||||
|
|
||||||
/* Allowed range of synth.gain is 0.0 to 10.0 */
|
/* Allowed range of synth.gain is 0.0 to 10.0 */
|
||||||
/* fluidsynth's default gain is 0.2, so use this as "full
|
/* fluidsynth's default gain is 0.2, so use this as "full
|
||||||
* volume". Set gain using OpenTTD's volume, as a number between 0
|
* volume". Set gain using OpenTTD's volume, as a number between 0
|
||||||
|
@@ -267,6 +267,7 @@ void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send,
|
|||||||
|
|
||||||
case NETWORK_ACTION_CHAT_COMPANY: strid = self_send ? STR_NETWORK_CHAT_TO_COMPANY : STR_NETWORK_CHAT_COMPANY; break;
|
case NETWORK_ACTION_CHAT_COMPANY: strid = self_send ? STR_NETWORK_CHAT_TO_COMPANY : STR_NETWORK_CHAT_COMPANY; break;
|
||||||
case NETWORK_ACTION_CHAT_CLIENT: strid = self_send ? STR_NETWORK_CHAT_TO_CLIENT : STR_NETWORK_CHAT_CLIENT; break;
|
case NETWORK_ACTION_CHAT_CLIENT: strid = self_send ? STR_NETWORK_CHAT_TO_CLIENT : STR_NETWORK_CHAT_CLIENT; break;
|
||||||
|
case NETWORK_ACTION_KICKED: strid = STR_NETWORK_MESSAGE_KICKED; break;
|
||||||
default: strid = STR_NETWORK_CHAT_ALL; break;
|
default: strid = STR_NETWORK_CHAT_ALL; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -776,8 +776,15 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p
|
|||||||
|
|
||||||
StringID err = STR_NETWORK_ERROR_LOSTCONNECTION;
|
StringID err = STR_NETWORK_ERROR_LOSTCONNECTION;
|
||||||
if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error];
|
if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error];
|
||||||
|
/* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */
|
||||||
ShowErrorMessage(err, INVALID_STRING_ID, WL_CRITICAL);
|
if (error == NETWORK_ERROR_KICKED && p->CanReadFromPacket(1)) {
|
||||||
|
char kick_msg[255];
|
||||||
|
p->Recv_string(kick_msg, sizeof(kick_msg));
|
||||||
|
SetDParamStr(0, kick_msg);
|
||||||
|
ShowErrorMessage(err, STR_NETWORK_ERROR_KICK_MESSAGE, WL_CRITICAL);
|
||||||
|
} else {
|
||||||
|
ShowErrorMessage(err, INVALID_STRING_ID, WL_CRITICAL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Perform an emergency save if we had already entered the game */
|
/* Perform an emergency save if we had already entered the game */
|
||||||
if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave();
|
if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave();
|
||||||
|
@@ -76,9 +76,9 @@ void NetworkServerDoMove(ClientID client_id, CompanyID company_id);
|
|||||||
void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string);
|
void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const char *string);
|
||||||
void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, ClientID from_id, NetworkTextMessageData data = NetworkTextMessageData(), bool from_admin = false);
|
void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, ClientID from_id, NetworkTextMessageData data = NetworkTextMessageData(), bool from_admin = false);
|
||||||
|
|
||||||
void NetworkServerKickClient(ClientID client_id);
|
void NetworkServerKickClient(ClientID client_id, const char *reason);
|
||||||
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban);
|
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason);
|
||||||
uint NetworkServerKickOrBanIP(const char *ip, bool ban);
|
uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason);
|
||||||
|
|
||||||
void NetworkInitChatMessage();
|
void NetworkInitChatMessage();
|
||||||
void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *message, ...) WARN_FORMAT(3, 4);
|
void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *message, ...) WARN_FORMAT(3, 4);
|
||||||
|
@@ -1688,12 +1688,12 @@ static WindowDesc _client_list_popup_desc(
|
|||||||
/* Here we start to define the options out of the menu */
|
/* Here we start to define the options out of the menu */
|
||||||
static void ClientList_Kick(const NetworkClientInfo *ci)
|
static void ClientList_Kick(const NetworkClientInfo *ci)
|
||||||
{
|
{
|
||||||
NetworkServerKickClient(ci->client_id);
|
NetworkServerKickClient(ci->client_id, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ClientList_Ban(const NetworkClientInfo *ci)
|
static void ClientList_Ban(const NetworkClientInfo *ci)
|
||||||
{
|
{
|
||||||
NetworkServerKickOrBanIP(ci->client_id, true);
|
NetworkServerKickOrBanIP(ci->client_id, true, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ClientList_SpeakToClient(const NetworkClientInfo *ci)
|
static void ClientList_SpeakToClient(const NetworkClientInfo *ci)
|
||||||
|
@@ -422,13 +422,15 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo()
|
|||||||
/**
|
/**
|
||||||
* Send an error to the client, and close its connection.
|
* Send an error to the client, and close its connection.
|
||||||
* @param error The error to disconnect for.
|
* @param error The error to disconnect for.
|
||||||
|
* @param reason In case of kicking a client, specifies the reason for kicking the client.
|
||||||
*/
|
*/
|
||||||
NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode error)
|
NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode error, const char *reason)
|
||||||
{
|
{
|
||||||
char str[100];
|
char str[100];
|
||||||
Packet *p = new Packet(PACKET_SERVER_ERROR);
|
Packet *p = new Packet(PACKET_SERVER_ERROR);
|
||||||
|
|
||||||
p->Send_uint8(error);
|
p->Send_uint8(error);
|
||||||
|
if (reason != nullptr) p->Send_string(reason);
|
||||||
this->SendPacket(p);
|
this->SendPacket(p);
|
||||||
|
|
||||||
StringID strid = GetNetworkErrorMsg(error);
|
StringID strid = GetNetworkErrorMsg(error);
|
||||||
@@ -442,7 +444,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err
|
|||||||
|
|
||||||
DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
|
DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
|
||||||
|
|
||||||
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid);
|
if (error == NETWORK_ERROR_KICKED && reason != nullptr) {
|
||||||
|
NetworkTextMessage(NETWORK_ACTION_KICKED, CC_DEFAULT, false, client_name, reason, strid);
|
||||||
|
} else {
|
||||||
|
NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, nullptr, strid);
|
||||||
|
}
|
||||||
|
|
||||||
for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
|
for (NetworkClientSocket *new_cs : NetworkClientSocket::Iterate()) {
|
||||||
if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
|
if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) {
|
||||||
@@ -2139,29 +2145,32 @@ void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const cha
|
|||||||
/**
|
/**
|
||||||
* Kick a single client.
|
* Kick a single client.
|
||||||
* @param client_id The client to kick.
|
* @param client_id The client to kick.
|
||||||
|
* @param reason In case of kicking a client, specifies the reason for kicking the client.
|
||||||
*/
|
*/
|
||||||
void NetworkServerKickClient(ClientID client_id)
|
void NetworkServerKickClient(ClientID client_id, const char *reason)
|
||||||
{
|
{
|
||||||
if (client_id == CLIENT_ID_SERVER) return;
|
if (client_id == CLIENT_ID_SERVER) return;
|
||||||
NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED);
|
NetworkClientSocket::GetByClientID(client_id)->SendError(NETWORK_ERROR_KICKED, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ban, or kick, everyone joined from the given client's IP.
|
* Ban, or kick, everyone joined from the given client's IP.
|
||||||
* @param client_id The client to check for.
|
* @param client_id The client to check for.
|
||||||
* @param ban Whether to ban or kick.
|
* @param ban Whether to ban or kick.
|
||||||
|
* @param reason In case of kicking a client, specifies the reason for kicking the client.
|
||||||
*/
|
*/
|
||||||
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban)
|
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason)
|
||||||
{
|
{
|
||||||
return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban);
|
return NetworkServerKickOrBanIP(NetworkClientSocket::GetByClientID(client_id)->GetClientIP(), ban, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kick or ban someone based on an IP address.
|
* Kick or ban someone based on an IP address.
|
||||||
* @param ip The IP address/range to ban/kick.
|
* @param ip The IP address/range to ban/kick.
|
||||||
* @param ban Whether to ban or just kick.
|
* @param ban Whether to ban or just kick.
|
||||||
|
* @param reason In case of kicking a client, specifies the reason for kicking the client.
|
||||||
*/
|
*/
|
||||||
uint NetworkServerKickOrBanIP(const char *ip, bool ban)
|
uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason)
|
||||||
{
|
{
|
||||||
/* Add address to ban-list */
|
/* Add address to ban-list */
|
||||||
if (ban) {
|
if (ban) {
|
||||||
@@ -2177,11 +2186,16 @@ uint NetworkServerKickOrBanIP(const char *ip, bool ban)
|
|||||||
|
|
||||||
uint n = 0;
|
uint n = 0;
|
||||||
|
|
||||||
/* There can be multiple clients with the same IP, kick them all */
|
/* There can be multiple clients with the same IP, kick them all but don't kill the server,
|
||||||
|
* or the client doing the rcon. The latter can't be kicked because kicking frees closes
|
||||||
|
* and subsequently free the connection related instances, which we would be reading from
|
||||||
|
* and writing to after returning. So we would read or write data from freed memory up till
|
||||||
|
* the segfault triggers. */
|
||||||
for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
|
for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
|
||||||
if (cs->client_id == CLIENT_ID_SERVER) continue;
|
if (cs->client_id == CLIENT_ID_SERVER) continue;
|
||||||
|
if (cs->client_id == _redirect_console_to_client) continue;
|
||||||
if (cs->client_address.IsInNetmask(ip)) {
|
if (cs->client_address.IsInNetmask(ip)) {
|
||||||
NetworkServerKickClient(cs->client_id);
|
NetworkServerKickClient(cs->client_id, reason);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -98,7 +98,7 @@ public:
|
|||||||
NetworkRecvStatus SendMove(ClientID client_id, CompanyID company_id);
|
NetworkRecvStatus SendMove(ClientID client_id, CompanyID company_id);
|
||||||
|
|
||||||
NetworkRecvStatus SendClientInfo(NetworkClientInfo *ci);
|
NetworkRecvStatus SendClientInfo(NetworkClientInfo *ci);
|
||||||
NetworkRecvStatus SendError(NetworkErrorCode error);
|
NetworkRecvStatus SendError(NetworkErrorCode error, const char *reason = nullptr);
|
||||||
NetworkRecvStatus SendDesyncLog(const std::string &log);
|
NetworkRecvStatus SendDesyncLog(const std::string &log);
|
||||||
NetworkRecvStatus SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, NetworkTextMessageData data);
|
NetworkRecvStatus SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, NetworkTextMessageData data);
|
||||||
NetworkRecvStatus SendJoin(ClientID client_id);
|
NetworkRecvStatus SendJoin(ClientID client_id);
|
||||||
|
@@ -86,6 +86,7 @@ enum DestType {
|
|||||||
enum NetworkAction {
|
enum NetworkAction {
|
||||||
NETWORK_ACTION_JOIN,
|
NETWORK_ACTION_JOIN,
|
||||||
NETWORK_ACTION_LEAVE,
|
NETWORK_ACTION_LEAVE,
|
||||||
|
NETWORK_ACTION_KICKED,
|
||||||
NETWORK_ACTION_SERVER_MESSAGE,
|
NETWORK_ACTION_SERVER_MESSAGE,
|
||||||
NETWORK_ACTION_CHAT,
|
NETWORK_ACTION_CHAT,
|
||||||
NETWORK_ACTION_CHAT_COMPANY,
|
NETWORK_ACTION_CHAT_COMPANY,
|
||||||
|
@@ -368,6 +368,16 @@ TownScopeResolver *StationResolverObject::GetTown()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 0x6A: { // GRFID of nearby station tiles
|
||||||
|
TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
|
||||||
|
|
||||||
|
if (!HasStationTileRail(nearby_tile)) return 0xFFFFFFFF;
|
||||||
|
if (!IsCustomStationSpecIndex(nearby_tile)) return 0;
|
||||||
|
|
||||||
|
const StationSpecList ssl = BaseStation::GetByTile(nearby_tile)->speclist[GetCustomStationSpecIndex(nearby_tile)];
|
||||||
|
return ssl.grfid;
|
||||||
|
}
|
||||||
|
|
||||||
/* General station variables */
|
/* General station variables */
|
||||||
case 0x82: return 50;
|
case 0x82: return 50;
|
||||||
case 0x84: return this->st->string_id;
|
case 0x84: return this->st->string_id;
|
||||||
|
@@ -77,8 +77,8 @@ END
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,10,0,!!ISODATE!!
|
FILEVERSION 1,11,0,!!ISODATE!!
|
||||||
PRODUCTVERSION 1,10,0,!!ISODATE!!
|
PRODUCTVERSION 1,11,0,!!ISODATE!!
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@@ -44,6 +44,9 @@ static const int YAPF_SHIP_PATH_CACHE_LENGTH = 32;
|
|||||||
/** Maximum segments of road vehicle path cache */
|
/** Maximum segments of road vehicle path cache */
|
||||||
static const int YAPF_ROADVEH_PATH_CACHE_SEGMENTS = 16;
|
static const int YAPF_ROADVEH_PATH_CACHE_SEGMENTS = 16;
|
||||||
|
|
||||||
|
/** Distance from destination road stops to not cache any further */
|
||||||
|
static const int YAPF_ROADVEH_PATH_CACHE_DESTINATION_LIMIT = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper container to find a depot
|
* Helper container to find a depot
|
||||||
*/
|
*/
|
||||||
|
@@ -429,9 +429,9 @@ public:
|
|||||||
const RoadStop *stop = st->GetPrimaryRoadStop(v);
|
const RoadStop *stop = st->GetPrimaryRoadStop(v);
|
||||||
if (stop != nullptr && (IsDriveThroughStopTile(stop->xy) || stop->GetNextRoadStop(v) != nullptr)) {
|
if (stop != nullptr && (IsDriveThroughStopTile(stop->xy) || stop->GetNextRoadStop(v) != nullptr)) {
|
||||||
/* Destination station has at least 2 usable road stops, or first is a drive-through stop,
|
/* Destination station has at least 2 usable road stops, or first is a drive-through stop,
|
||||||
* trim end of path cache within 8 tiles of road stop tile area */
|
* trim end of path cache within a number of tiles of road stop tile area */
|
||||||
TileArea non_cached_area = v->IsBus() ? st->bus_station : st->truck_station;
|
TileArea non_cached_area = v->IsBus() ? st->bus_station : st->truck_station;
|
||||||
non_cached_area.Expand(8);
|
non_cached_area.Expand(YAPF_ROADVEH_PATH_CACHE_DESTINATION_LIMIT);
|
||||||
while (!path_cache.empty() && non_cached_area.Contains(path_cache.tile.back())) {
|
while (!path_cache.empty() && non_cached_area.Contains(path_cache.tile.back())) {
|
||||||
path_cache.td.pop_back();
|
path_cache.td.pop_back();
|
||||||
path_cache.tile.pop_back();
|
path_cache.tile.pop_back();
|
||||||
|
@@ -91,4 +91,4 @@ const byte _openttd_revision_tagged = !!ISTAG!!;
|
|||||||
* final release will always have a lower version number than the released
|
* final release will always have a lower version number than the released
|
||||||
* version, thus making comparisons on specific revisions easy.
|
* version, thus making comparisons on specific revisions easy.
|
||||||
*/
|
*/
|
||||||
const uint32 _openttd_newgrf_version = 1 << 28 | 10 << 24 | 0 << 20 | !!ISSTABLETAG!! << 19 | 28004;
|
const uint32 _openttd_newgrf_version = 1 << 28 | 11 << 24 | 0 << 20 | !!ISSTABLETAG!! << 19 | 28004;
|
||||||
|
@@ -305,7 +305,7 @@ enum SaveLoadVersion : uint16 {
|
|||||||
SLV_SCRIPT_MEMLIMIT, ///< 215 PR#7516 Limit on AI/GS memory consumption.
|
SLV_SCRIPT_MEMLIMIT, ///< 215 PR#7516 Limit on AI/GS memory consumption.
|
||||||
SLV_MULTITILE_DOCKS, ///< 216 PR#7380 Multiple docks per station.
|
SLV_MULTITILE_DOCKS, ///< 216 PR#7380 Multiple docks per station.
|
||||||
SLV_TRADING_AGE, ///< 217 PR#7780 Configurable company trading age.
|
SLV_TRADING_AGE, ///< 217 PR#7780 Configurable company trading age.
|
||||||
SLV_ENDING_YEAR, ///< 218 PR#7747 Configurable ending year.
|
SLV_ENDING_YEAR, ///< 218 PR#7747 v1.10 Configurable ending year.
|
||||||
|
|
||||||
SL_MAX_VERSION, ///< Highest possible saveload version
|
SL_MAX_VERSION, ///< Highest possible saveload version
|
||||||
|
|
||||||
@@ -506,7 +506,8 @@ enum VarTypes {
|
|||||||
SLF_NO_NETWORK_SYNC = 1 << 10, ///< do not synchronize over network (but it is saved if SLF_NOT_IN_SAVE is not set)
|
SLF_NO_NETWORK_SYNC = 1 << 10, ///< do not synchronize over network (but it is saved if SLF_NOT_IN_SAVE is not set)
|
||||||
SLF_ALLOW_CONTROL = 1 << 11, ///< allow control codes in the strings
|
SLF_ALLOW_CONTROL = 1 << 11, ///< allow control codes in the strings
|
||||||
SLF_ALLOW_NEWLINE = 1 << 12, ///< allow new lines in the strings
|
SLF_ALLOW_NEWLINE = 1 << 12, ///< allow new lines in the strings
|
||||||
/* 3 more possible flags */
|
SLF_HEX = 1 << 13, ///< print numbers as hex in the config file (only useful for unsigned)
|
||||||
|
/* 2 more possible flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32 VarType;
|
typedef uint32 VarType;
|
||||||
|
@@ -13,10 +13,12 @@
|
|||||||
* functions may still be available if you return an older API version
|
* functions may still be available if you return an older API version
|
||||||
* in GetAPIVersion() in info.nut.
|
* in GetAPIVersion() in info.nut.
|
||||||
*
|
*
|
||||||
* \b 1.10.0
|
* \b 1.11.0
|
||||||
*
|
*
|
||||||
* This version is not yet released. The following changes are not set in stone yet.
|
* This version is not yet released. The following changes are not set in stone yet.
|
||||||
*
|
*
|
||||||
|
* \b 1.10.0
|
||||||
|
*
|
||||||
* API additions:
|
* API additions:
|
||||||
* \li AIGroup::SetPrimaryColour
|
* \li AIGroup::SetPrimaryColour
|
||||||
* \li AIGroup::SetSecondaryColour
|
* \li AIGroup::SetSecondaryColour
|
||||||
|
@@ -13,10 +13,12 @@
|
|||||||
* functions may still be available if you return an older API version
|
* functions may still be available if you return an older API version
|
||||||
* in GetAPIVersion() in info.nut.
|
* in GetAPIVersion() in info.nut.
|
||||||
*
|
*
|
||||||
* \b 1.10.0
|
* \b 1.11.0
|
||||||
*
|
*
|
||||||
* This version is not yet released. The following changes are not set in stone yet.
|
* This version is not yet released. The following changes are not set in stone yet.
|
||||||
*
|
*
|
||||||
|
* \b 1.10.0
|
||||||
|
*
|
||||||
* API additions:
|
* API additions:
|
||||||
* \li GSVehicle::BuildVehicleWithRefit
|
* \li GSVehicle::BuildVehicleWithRefit
|
||||||
* \li GSVehicle::GetBuildWithRefitCapacity
|
* \li GSVehicle::GetBuildWithRefitCapacity
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include <limits>
|
||||||
#include "currency.h"
|
#include "currency.h"
|
||||||
#include "screenshot.h"
|
#include "screenshot.h"
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
@@ -176,7 +177,8 @@ static size_t LookupManyOfMany(const char *many, const char *str)
|
|||||||
* @param maxitems the maximum number of elements the integerlist-array has
|
* @param maxitems the maximum number of elements the integerlist-array has
|
||||||
* @return returns the number of items found, or -1 on an error
|
* @return returns the number of items found, or -1 on an error
|
||||||
*/
|
*/
|
||||||
static int ParseIntList(const char *p, int *items, int maxitems)
|
template<typename T>
|
||||||
|
static int ParseIntList(const char *p, T *items, int maxitems)
|
||||||
{
|
{
|
||||||
int n = 0; // number of items read so far
|
int n = 0; // number of items read so far
|
||||||
bool comma = false; // do we accept comma?
|
bool comma = false; // do we accept comma?
|
||||||
@@ -196,9 +198,9 @@ static int ParseIntList(const char *p, int *items, int maxitems)
|
|||||||
default: {
|
default: {
|
||||||
if (n == maxitems) return -1; // we don't accept that many numbers
|
if (n == maxitems) return -1; // we don't accept that many numbers
|
||||||
char *end;
|
char *end;
|
||||||
long v = strtol(p, &end, 0);
|
unsigned long v = strtoul(p, &end, 0);
|
||||||
if (p == end) return -1; // invalid character (not a number)
|
if (p == end) return -1; // invalid character (not a number)
|
||||||
if (sizeof(int) < sizeof(long)) v = ClampToI32(v);
|
if (sizeof(T) < sizeof(v)) v = Clamp<unsigned long>(v, std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
|
||||||
items[n++] = v;
|
items[n++] = v;
|
||||||
p = end; // first non-number
|
p = end; // first non-number
|
||||||
comma = true; // we accept comma now
|
comma = true; // we accept comma now
|
||||||
@@ -224,7 +226,7 @@ static int ParseIntList(const char *p, int *items, int maxitems)
|
|||||||
*/
|
*/
|
||||||
static bool LoadIntList(const char *str, void *array, int nelems, VarType type)
|
static bool LoadIntList(const char *str, void *array, int nelems, VarType type)
|
||||||
{
|
{
|
||||||
int items[64];
|
unsigned long items[64];
|
||||||
int i, nitems;
|
int i, nitems;
|
||||||
|
|
||||||
if (str == nullptr) {
|
if (str == nullptr) {
|
||||||
@@ -273,7 +275,7 @@ static void MakeIntList(char *buf, const char *last, const void *array, int nele
|
|||||||
const byte *p = (const byte *)array;
|
const byte *p = (const byte *)array;
|
||||||
|
|
||||||
for (i = 0; i != nelems; i++) {
|
for (i = 0; i != nelems; i++) {
|
||||||
switch (type) {
|
switch (GetVarMemType(type)) {
|
||||||
case SLE_VAR_BL:
|
case SLE_VAR_BL:
|
||||||
case SLE_VAR_I8: v = *(const int8 *)p; p += 1; break;
|
case SLE_VAR_I8: v = *(const int8 *)p; p += 1; break;
|
||||||
case SLE_VAR_U8: v = *(const uint8 *)p; p += 1; break;
|
case SLE_VAR_U8: v = *(const uint8 *)p; p += 1; break;
|
||||||
@@ -283,7 +285,13 @@ static void MakeIntList(char *buf, const char *last, const void *array, int nele
|
|||||||
case SLE_VAR_U32: v = *(const uint32 *)p; p += 4; break;
|
case SLE_VAR_U32: v = *(const uint32 *)p; p += 4; break;
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
buf += seprintf(buf, last, (i == 0) ? "%d" : ",%d", v);
|
if (IsSignedVarMemType(type)) {
|
||||||
|
buf += seprintf(buf, last, (i == 0) ? "%d" : ",%d", v);
|
||||||
|
} else if (type & SLF_HEX) {
|
||||||
|
buf += seprintf(buf, last, (i == 0) ? "0x%X" : ",0x%X", v);
|
||||||
|
} else {
|
||||||
|
buf += seprintf(buf, last, (i == 0) ? "%u" : ",%u", v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,7 +704,7 @@ static void IniSaveSettings(IniFile *ini, const SettingDesc *sd, const char *grp
|
|||||||
|
|
||||||
switch (sdb->cmd) {
|
switch (sdb->cmd) {
|
||||||
case SDT_BOOLX: strecpy(buf, (i != 0) ? "true" : "false", lastof(buf)); break;
|
case SDT_BOOLX: strecpy(buf, (i != 0) ? "true" : "false", lastof(buf)); break;
|
||||||
case SDT_NUMX: seprintf(buf, lastof(buf), IsSignedVarMemType(sld->conv) ? "%d" : "%u", i); break;
|
case SDT_NUMX: seprintf(buf, lastof(buf), IsSignedVarMemType(sld->conv) ? "%d" : (sld->conv & SLF_HEX) ? "%X" : "%u", i); break;
|
||||||
case SDT_ONEOFMANY: MakeOneOfMany(buf, lastof(buf), sdb->many, i); break;
|
case SDT_ONEOFMANY: MakeOneOfMany(buf, lastof(buf), sdb->many, i); break;
|
||||||
case SDT_MANYOFMANY: MakeManyOfMany(buf, lastof(buf), sdb->many, i); break;
|
case SDT_MANYOFMANY: MakeManyOfMany(buf, lastof(buf), sdb->many, i); break;
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
@@ -724,7 +732,7 @@ static void IniSaveSettings(IniFile *ini, const SettingDesc *sd, const char *grp
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SDT_INTLIST:
|
case SDT_INTLIST:
|
||||||
MakeIntList(buf, lastof(buf), ptr, sld->length, GetVarMemType(sld->conv));
|
MakeIntList(buf, lastof(buf), ptr, sld->length, sld->conv);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
@@ -1703,7 +1711,7 @@ static GRFConfig *GRFLoadConfig(IniFile *ini, const char *grpname, bool is_stati
|
|||||||
|
|
||||||
/* Parse parameters */
|
/* Parse parameters */
|
||||||
if (!StrEmpty(item->value)) {
|
if (!StrEmpty(item->value)) {
|
||||||
int count = ParseIntList(item->value, (int*)c->param, lengthof(c->param));
|
int count = ParseIntList(item->value, c->param, lengthof(c->param));
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
SetDParamStr(0, filename);
|
SetDParamStr(0, filename);
|
||||||
ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY, WL_CRITICAL);
|
ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY, WL_CRITICAL);
|
||||||
|
@@ -4081,7 +4081,7 @@ void StationMonthlyLoop()
|
|||||||
void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius)
|
void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius)
|
||||||
{
|
{
|
||||||
ForAllStationsRadius(tile, radius, [&](Station *st) {
|
ForAllStationsRadius(tile, radius, [&](Station *st) {
|
||||||
if (st->owner == owner) {
|
if (st->owner == owner && DistanceManhattan(tile, st->xy) <= radius) {
|
||||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||||
GoodsEntry *ge = &st->goods[i];
|
GoodsEntry *ge = &st->goods[i];
|
||||||
|
|
||||||
|
@@ -45,6 +45,7 @@ var = engine_renew
|
|||||||
def = false
|
def = false
|
||||||
str = STR_CONFIG_SETTING_AUTORENEW_VEHICLE
|
str = STR_CONFIG_SETTING_AUTORENEW_VEHICLE
|
||||||
strhelp = STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT
|
strhelp = STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT
|
||||||
|
cat = SC_BASIC
|
||||||
|
|
||||||
[SDT_VAR]
|
[SDT_VAR]
|
||||||
base = CompanySettings
|
base = CompanySettings
|
||||||
|
@@ -176,6 +176,7 @@ static const NIVariable _niv_stations[] = {
|
|||||||
NIV(0x67, "land info of nearby tiles"),
|
NIV(0x67, "land info of nearby tiles"),
|
||||||
NIV(0x68, "station info of nearby tiles"),
|
NIV(0x68, "station info of nearby tiles"),
|
||||||
NIV(0x69, "information about cargo accepted in the past"),
|
NIV(0x69, "information about cargo accepted in the past"),
|
||||||
|
NIV(0x6A, "GRFID of nearby station tiles"),
|
||||||
NIV_END()
|
NIV_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user