From 5df01bf95edc38bb43ce68f5a12f6c402436cf8b Mon Sep 17 00:00:00 2001 From: kiwitreekor Date: Thu, 30 Jan 2020 05:23:23 +0900 Subject: [PATCH 01/22] Add: [NewGRF] Station variable 6A, querying GRFID of nearby station tiles (#7956) --- src/newgrf_station.cpp | 10 ++++++++++ src/table/newgrf_debug_data.h | 1 + 2 files changed, 11 insertions(+) diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 312ca59d56..19f32bd754 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -368,6 +368,16 @@ TownScopeResolver *StationResolverObject::GetTown() 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 */ case 0x82: return 50; case 0x84: return this->st->string_id; diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index c5ed48df47..d14415051c 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -127,6 +127,7 @@ static const NIVariable _niv_stations[] = { NIV(0x67, "land info of nearby tiles"), NIV(0x68, "station info of nearby tiles"), NIV(0x69, "information about cargo accepted in the past"), + NIV(0x6A, "GRFID of nearby station tiles"), NIV_END() }; From be9ca4689ecfe0f463468bbdbba13dee455949a9 Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 30 Jan 2020 19:45:39 +0100 Subject: [PATCH 02/22] Update: Translations from eints korean: 4 changes by telk5093 --- src/lang/korean.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 511cada8e8..4150f32b4b 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -791,8 +791,8 @@ STR_NEWS_FIRST_SHIP_ARRIVAL :{BIG_FONT}{BLAC STR_NEWS_FIRST_AIRCRAFT_ARRIVAL :{BIG_FONT}{BLACK}시민들이 축하하고 있습니다 . . .{}{STATION}에 처음으로 항공기가 도착했습니다! STR_NEWS_TRAIN_CRASH :{BIG_FONT}{BLACK}열차 충돌 사고!{}충돌로 인한 폭발로 {COMMA}명의 사망자가 발생하였습니다! -STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER :{BIG_FONT}{BLACK}차량 충돌!{}열차와의 충돌로 인해 운전자가 사망했습니다! -STR_NEWS_ROAD_VEHICLE_CRASH :{BIG_FONT}{BLACK}차량 충돌!{}열차와의 충돌로 {COMMA}명이 사망했습니다! +STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER :{BIG_FONT}{BLACK}차량 충돌!{}열차 충돌로 운전자가 사망했습니다! +STR_NEWS_ROAD_VEHICLE_CRASH :{BIG_FONT}{BLACK}차량 충돌!{}열차 충돌로 {COMMA}명이 사망했습니다! STR_NEWS_AIRCRAFT_CRASH :{BIG_FONT}{BLACK}항공기 충돌사고 발생!{}{COMMA}명이 {STATION}공항에서 사망하였습니다! STR_NEWS_PLANE_CRASH_OUT_OF_FUEL :{BIG_FONT}{BLACK}항공기 추락사고 발생!{}연료 부족으로 인하여 {COMMA}명이 사망하였습니다! @@ -1588,7 +1588,7 @@ STR_CONFIG_SETTING_TOWN_LAYOUT_BETTER_ROADS :개선된 도 STR_CONFIG_SETTING_TOWN_LAYOUT_2X2_GRID :2x2 칸 STR_CONFIG_SETTING_TOWN_LAYOUT_3X3_GRID :3x3 칸 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_LEVEL_CROSSINGS :도시가 회사 소유의 선로에 건널목을 만드는 것을 허용: {STRING} STR_CONFIG_SETTING_ALLOW_TOWN_LEVEL_CROSSINGS_HELPTEXT :도시가 회사 소유의 선로에 건널목을 건설할 수 있도록 허용합니다. @@ -2136,7 +2136,7 @@ STR_COMPANY_PASSWORD_MAKE_DEFAULT_TOOLTIP :{BLACK}이 회 STR_COMPANY_VIEW_JOIN :{BLACK}참여 STR_COMPANY_VIEW_JOIN_TOOLTIP :{BLACK}이 회사로 참가해서 플레이합니다 STR_COMPANY_VIEW_PASSWORD :{BLACK}암호 -STR_COMPANY_VIEW_PASSWORD_TOOLTIP :{BLACK}다른 참가자가 이 회사로의 플레이를 하지 못하도록 암호로 보호합니다 +STR_COMPANY_VIEW_PASSWORD_TOOLTIP :{BLACK}다른 참가자가 이 회사에 참여하여 플레이하지 못 하도록 암호로 보호합니다 STR_COMPANY_VIEW_SET_PASSWORD :{BLACK}회사 암호 설정 # Network chat From 196157b29e3b654e2f700b657a4e706d02b26cd6 Mon Sep 17 00:00:00 2001 From: glx Date: Sat, 1 Feb 2020 01:31:23 +0100 Subject: [PATCH 03/22] Fix #7966: SQInteger is 64-bit, print it as 64-bit --- src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp | 6 +++--- src/3rdparty/squirrel/squirrel/sqbaselib.cpp | 2 +- src/3rdparty/squirrel/squirrel/sqdebug.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp index 540975fb5c..a4f4e21c33 100644 --- a/src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp +++ b/src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp @@ -38,7 +38,7 @@ void sqstd_printcallstack(HSQUIRRELVM v) 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=0; @@ -56,7 +56,7 @@ void sqstd_printcallstack(HSQUIRRELVM v) break; case OT_INTEGER: sq_getinteger(v,-1,&i); - pf(v,"[%s] %d\n",name,i); + pf(v,"[%s] " OTTD_PRINTF64 "\n",name,i); break; case OT_FLOAT: 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); 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); } } diff --git a/src/3rdparty/squirrel/squirrel/sqbaselib.cpp b/src/3rdparty/squirrel/squirrel/sqbaselib.cpp index 86a1b11858..e5de01a635 100644 --- a/src/3rdparty/squirrel/squirrel/sqbaselib.cpp +++ b/src/3rdparty/squirrel/squirrel/sqbaselib.cpp @@ -219,7 +219,7 @@ static SQInteger base_array(HSQUIRRELVM v) SQInteger nInitialSize = tointeger(stack_get(v,2)); SQInteger ret = 1; 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; ret = -1; } diff --git a/src/3rdparty/squirrel/squirrel/sqdebug.cpp b/src/3rdparty/squirrel/squirrel/sqdebug.cpp index 2f24e83b66..44f767c297 100644 --- a/src/3rdparty/squirrel/squirrel/sqdebug.cpp +++ b/src/3rdparty/squirrel/squirrel/sqdebug.cpp @@ -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); } } - 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)); } From 14af8701df46fb8f40a862ea5eff41e6ae1c2868 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 1 Feb 2020 18:19:57 +0000 Subject: [PATCH 04/22] Fix #6566: Fix signed integer overflow in viewport draw area chunking This caused drawing areas larger than 2097151 pixels at 8x zoom to not be subdivided into smaller chunks as required. This resulted in pathological performance issues in the sprite sorter. --- src/viewport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/viewport.cpp b/src/viewport.cpp index 06f5023795..1c9dca1ef6 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1728,7 +1728,7 @@ void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom */ static void ViewportDrawChk(const ViewPort *vp, int left, int top, int right, int bottom) { - if (ScaleByZoom(bottom - top, vp->zoom) * ScaleByZoom(right - left, vp->zoom) > (int)(180000 * ZOOM_LVL_BASE * ZOOM_LVL_BASE)) { + if ((int64)ScaleByZoom(bottom - top, vp->zoom) * (int64)ScaleByZoom(right - left, vp->zoom) > (int64)(180000 * ZOOM_LVL_BASE * ZOOM_LVL_BASE)) { if ((bottom - top) > (right - left)) { int t = (top + bottom) >> 1; ViewportDrawChk(vp, left, top, right, t); From ac7cc18ab9f5a06ac0261a69dc96a28e3f1136af Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 2 Feb 2020 19:45:40 +0100 Subject: [PATCH 05/22] Update: Translations from eints czech: 22 changes by djst --- src/lang/czech.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/lang/czech.txt b/src/lang/czech.txt index 189ecfd00d..4386ae1016 100644 --- a/src/lang/czech.txt +++ b/src/lang/czech.txt @@ -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_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_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_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_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_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_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} @@ -3478,8 +3484,17 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}{CURRENC # Industry directory STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}Průmysl 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_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_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 STR_INDUSTRY_VIEW_CAPTION :{WHITE}{INDUSTRY} @@ -4257,6 +4272,13 @@ STR_AI_LIST_ACCEPT_TOOLTIP :{BLACK}Vybrat o STR_AI_LIST_CANCEL :{BLACK}Zrušit 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 STR_AI_SETTINGS_CAPTION :{WHITE}{STRING} Parametry From b5d56559d2ec16512dd8a0346406bf36486ebf7c Mon Sep 17 00:00:00 2001 From: glx Date: Sat, 1 Feb 2020 22:08:05 +0100 Subject: [PATCH 06/22] Fix #7969: limit recursion during alias execution --- src/console.cpp | 16 +++++++++++----- src/console_func.h | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/console.cpp b/src/console.cpp index b777bf2c05..3c782357d2 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -21,6 +21,7 @@ #include "safeguards.h" 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 */ IConsoleCmd *_iconsole_cmds; ///< list of registered commands @@ -316,13 +317,18 @@ IConsoleAlias *IConsoleAliasGet(const char *name) * @param tokencount the number of parameters passed * @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_stream = alias_buffer; 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++) { switch (*cmdptr) { case '\'': // ' will double for "" @@ -330,7 +336,7 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char break; case ';': // Cmd separator; execute previous and start new command - IConsoleCmdExec(alias_buffer); + IConsoleCmdExec(alias_buffer, recurse_count); alias_stream = alias_buffer; *alias_stream = '\0'; // Make sure the new command is terminated. @@ -390,7 +396,7 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char } } - IConsoleCmdExec(alias_buffer); + IConsoleCmdExec(alias_buffer, recurse_count); } /** @@ -398,7 +404,7 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char * individual tokens (separated by spaces), then execute it if possible * @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; char *tokens[ICON_TOKEN_COUNT], tokenstream[ICON_MAX_STREAMSIZE]; @@ -504,7 +510,7 @@ void IConsoleCmdExec(const char *cmdstr) t_index--; IConsoleAlias *alias = IConsoleAliasGet(tokens[0]); if (alias != nullptr) { - IConsoleAliasExec(alias, t_index, &tokens[1]); + IConsoleAliasExec(alias, t_index, &tokens[1], recurse_count + 1); return; } diff --git a/src/console_func.h b/src/console_func.h index 1dad477b8a..6d634a4553 100644 --- a/src/console_func.h +++ b/src/console_func.h @@ -28,7 +28,7 @@ void IConsoleWarning(const char *string); void IConsoleError(const char *string); /* Parser */ -void IConsoleCmdExec(const char *cmdstr); +void IConsoleCmdExec(const char *cmdstr, const uint recurse_count = 0); bool IsValidConsoleColour(TextColour c); From 5880f1479f21157158dbe862e4cb1118e0cfbfae Mon Sep 17 00:00:00 2001 From: Bjarni Thor Date: Tue, 21 Jan 2020 15:39:10 +0000 Subject: [PATCH 07/22] Feature #7756: Allow server to supply a reason to kicked/banned clients This commit adds the missing feature of allowing the server owner to provide a reason for kicking/banning a client, which the client sees in a pop-up window after being kicked. The implementation extends the network protocol by adding a new network action called NETWORK_ACTION_KICKED that is capable of having an error string, unlike the other network error packages. Additionally, the kick function broadcasts a message to all clients about the kicked client and the reason for the kick. --- src/console_cmds.cpp | 40 +++++++++++++++++++++++++--------- src/lang/english.txt | 2 ++ src/network/network.cpp | 1 + src/network/network_client.cpp | 11 ++++++++-- src/network/network_func.h | 6 ++--- src/network/network_gui.cpp | 4 ++-- src/network/network_server.cpp | 25 ++++++++++++++------- src/network/network_server.h | 2 +- src/network/network_type.h | 1 + 9 files changed, 66 insertions(+), 26 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 748e4ab4cd..c4b454b519 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -470,7 +470,7 @@ DEF_CONSOLE_CMD(ConClearBuffer) * 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; @@ -494,14 +494,14 @@ static bool ConKickOrBan(const char *argv, bool ban) if (!ban) { /* Kick only this client, not all clients with that IP */ - NetworkServerKickClient(client_id); + NetworkServerKickClient(client_id, reason); return true; } /* When banning, kick+ban all clients with that IP */ - n = NetworkServerKickOrBanIP(client_id, ban); + n = NetworkServerKickOrBanIP(client_id, ban, reason); } else { - n = NetworkServerKickOrBanIP(argv, ban); + n = NetworkServerKickOrBanIP(argv, ban, reason); } if (n == 0) { @@ -516,28 +516,48 @@ static bool ConKickOrBan(const char *argv, bool ban) DEF_CONSOLE_CMD(ConKick) { if (argc == 0) { - IConsoleHelp("Kick a client from a network game. Usage: 'kick '"); + IConsoleHelp("Kick a client from a network game. Usage: 'kick []'"); IConsoleHelp("For client-id's, see the command 'clients'"); 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 */ + int 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) { if (argc == 0) { - IConsoleHelp("Ban a client from a network game. Usage: 'ban '"); + IConsoleHelp("Ban a client from a network game. Usage: 'ban []'"); IConsoleHelp("For client-id's, see the command 'clients'"); IConsoleHelp("If the client is no longer online, you can still ban his/her IP"); 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 */ + int 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) diff --git a/src/lang/english.txt b/src/lang/english.txt index 963fc3d28c..2a4ab1c280 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2168,6 +2168,7 @@ STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Wrong pa 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_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_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 @@ -2227,6 +2228,7 @@ STR_NETWORK_MESSAGE_GIVE_MONEY :*** {RAW_STRING STR_NETWORK_MESSAGE_GAVE_MONEY_AWAY :*** You gave {1:RAW_STRING} {2:CURRENCY_LONG} 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_KICKED :*** {RAW_STRING} was kicked. Reason: ({RAW_STRING}) # Content downloading window STR_CONTENT_TITLE :{WHITE}Content downloading diff --git a/src/network/network.cpp b/src/network/network.cpp index fe7e6a8552..e8c99c89bb 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -248,6 +248,7 @@ void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, case NETWORK_ACTION_GIVE_MONEY: strid = self_send ? STR_NETWORK_MESSAGE_GAVE_MONEY_AWAY : STR_NETWORK_MESSAGE_GIVE_MONEY; 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_KICKED: strid = STR_NETWORK_MESSAGE_KICKED; break; default: strid = STR_NETWORK_CHAT_ALL; break; } diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 08ec7823e1..74b802f919 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -687,8 +687,15 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p StringID err = STR_NETWORK_ERROR_LOSTCONNECTION; if (error < (ptrdiff_t)lengthof(network_error_strings)) err = network_error_strings[error]; - - ShowErrorMessage(err, INVALID_STRING_ID, WL_CRITICAL); + /* In case of kicking a client, we assume there is a kick message in the packet if we can read one byte */ + 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 */ if (this->status == STATUS_ACTIVE) ClientNetworkEmergencySave(); diff --git a/src/network/network_func.h b/src/network/network_func.h index d4a62ddd36..cbb89820cf 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -75,9 +75,9 @@ void NetworkServerDoMove(ClientID client_id, CompanyID company_id); 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, int64 data = 0, bool from_admin = false); -void NetworkServerKickClient(ClientID client_id); -uint NetworkServerKickOrBanIP(ClientID client_id, bool ban); -uint NetworkServerKickOrBanIP(const char *ip, bool ban); +void NetworkServerKickClient(ClientID client_id, const char *reason); +uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const char *reason); +uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason); void NetworkInitChatMessage(); void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *message, ...) WARN_FORMAT(3, 4); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 2faf5a3950..c4488f35d9 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1687,12 +1687,12 @@ static WindowDesc _client_list_popup_desc( /* Here we start to define the options out of the menu */ static void ClientList_Kick(const NetworkClientInfo *ci) { - NetworkServerKickClient(ci->client_id); + NetworkServerKickClient(ci->client_id, nullptr); } static void ClientList_Ban(const NetworkClientInfo *ci) { - NetworkServerKickOrBanIP(ci->client_id, true); + NetworkServerKickOrBanIP(ci->client_id, true, nullptr); } static void ClientList_GiveMoney(const NetworkClientInfo *ci) diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index f68cfd05ca..dd88042a12 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -407,13 +407,15 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo() /** * Send an error to the client, and close its connection. * @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]; Packet *p = new Packet(PACKET_SERVER_ERROR); p->Send_uint8(error); + if (reason != nullptr) p->Send_string(reason); this->SendPacket(p); StringID strid = GetNetworkErrorMsg(error); @@ -427,7 +429,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendError(NetworkErrorCode err 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()) { if (new_cs->status > STATUS_AUTHORIZED && new_cs != this) { @@ -2039,29 +2045,32 @@ void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const cha /** * Kick a single client. * @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; - 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. * @param client_id The client to check for. * @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. * @param ip The IP address/range to ban/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 */ if (ban) { @@ -2081,7 +2090,7 @@ uint NetworkServerKickOrBanIP(const char *ip, bool ban) for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) { if (cs->client_id == CLIENT_ID_SERVER) continue; if (cs->client_address.IsInNetmask(ip)) { - NetworkServerKickClient(cs->client_id); + NetworkServerKickClient(cs->client_id, reason); n++; } } diff --git a/src/network/network_server.h b/src/network/network_server.h index 9a1873520c..3dfcf5594f 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -89,7 +89,7 @@ public: NetworkRecvStatus SendMove(ClientID client_id, CompanyID company_id); NetworkRecvStatus SendClientInfo(NetworkClientInfo *ci); - NetworkRecvStatus SendError(NetworkErrorCode error); + NetworkRecvStatus SendError(NetworkErrorCode error, const char *reason = nullptr); NetworkRecvStatus SendChat(NetworkAction action, ClientID client_id, bool self_send, const char *msg, int64 data); NetworkRecvStatus SendJoin(ClientID client_id); NetworkRecvStatus SendFrame(); diff --git a/src/network/network_type.h b/src/network/network_type.h index 595eaad0f0..5f796b83d7 100644 --- a/src/network/network_type.h +++ b/src/network/network_type.h @@ -85,6 +85,7 @@ enum DestType { enum NetworkAction { NETWORK_ACTION_JOIN, NETWORK_ACTION_LEAVE, + NETWORK_ACTION_KICKED, NETWORK_ACTION_SERVER_MESSAGE, NETWORK_ACTION_CHAT, NETWORK_ACTION_CHAT_COMPANY, From 58c8ff456e13908718ec871c1af6d8d6257ee062 Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 5 Feb 2020 19:45:39 +0100 Subject: [PATCH 08/22] Update: Translations from eints korean: 2 changes by telk5093 --- src/lang/korean.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 4150f32b4b..eae3d2cb1b 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -2169,6 +2169,7 @@ STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}잘못 STR_NETWORK_ERROR_SERVER_FULL :{WHITE}서버에 인원이 가득 찼습니다 STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}서버 관리자에 의해 접속이 차단되었습니다 STR_NETWORK_ERROR_KICKED :{WHITE}서버에서 강제로 추방되었습니다 +STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}사유: {STRING} STR_NETWORK_ERROR_CHEATER :{WHITE}이 서버에서 치트를 사용할 수 없습니다 STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{WHITE}서버에 너무 많은 명령을 보냈습니다 STR_NETWORK_ERROR_TIMEOUT_PASSWORD :{WHITE}비밀번호 입력 시간을 초과하였습니다 @@ -2228,6 +2229,7 @@ STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} STR_NETWORK_MESSAGE_GAVE_MONEY_AWAY :*** {1:STRING} 님에게 {2:CURRENCY_LONG}만큼의 돈을 보냈습니다 STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}서버가 게임을 종료하였습니다 STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}서버가 재시작되고 있습니다...{}기다려주세요... +STR_NETWORK_MESSAGE_KICKED :*** {STRING} - 서버에서 강제로 추방되었습니다. 사유: ({STRING}) # Content downloading window STR_CONTENT_TITLE :{WHITE}콘텐츠 다운로드 From 3fcb240f8e4d02aace63a7ba4a96284b3aedef86 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Thu, 6 Feb 2020 16:27:58 +0100 Subject: [PATCH 09/22] Fix d84b67e5: Station rating effects affecting too large area --- src/station_cmd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index adc2b0084e..385072b956 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -3858,7 +3858,7 @@ void StationMonthlyLoop() void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius) { 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++) { GoodsEntry *ge = &st->goods[i]; From 805ecd32be64e14d8555ebc06eadf673bdf401ee Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Thu, 6 Feb 2020 16:44:54 +0100 Subject: [PATCH 10/22] Fix 5880f147: Integer width warnings --- src/console_cmds.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index c4b454b519..30982d8214 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -527,7 +527,7 @@ DEF_CONSOLE_CMD(ConKick) if (argc == 2) return ConKickOrBan(argv[1], false, nullptr); /* Reason for kicking supplied */ - int kick_message_length = strlen(argv[2]); + 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; @@ -551,7 +551,7 @@ DEF_CONSOLE_CMD(ConBan) if (argc == 2) return ConKickOrBan(argv[1], true, nullptr); /* Reason for kicking supplied */ - int kick_message_length = strlen(argv[2]); + 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; From 492d2704f1503303b7eaea15559649c71b747c87 Mon Sep 17 00:00:00 2001 From: stormcone <48624099+stormcone@users.noreply.github.com> Date: Tue, 4 Feb 2020 23:26:59 +0100 Subject: [PATCH 11/22] Fix #7974: Crash when CTRL+click to show a vehicle group that is collapsed --- src/group_gui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/group_gui.cpp b/src/group_gui.cpp index e28e10bb2c..0bf8589ac5 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -1017,6 +1017,7 @@ public: } this->groups.ForceRebuild(); this->BuildGroupList(this->owner); + this->group_sb->SetCount((uint)this->groups.size()); id_g = find_index(this->groups, g); } this->group_sb->ScrollTowards(id_g); From 3089c625e403e59dec4d88707792551e567e6f89 Mon Sep 17 00:00:00 2001 From: Samu Date: Thu, 24 Jan 2019 17:00:20 +0000 Subject: [PATCH 12/22] Fix #7088: close AI/GS textfile window when their data are invalid --- src/ai/ai_gui.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp index a684e4a350..a0552628cd 100644 --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -179,6 +179,7 @@ struct AIListWindow : public Window { InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_AI); InvalidateWindowClassesData(WC_AI_SETTINGS); DeleteWindowByClass(WC_QUERY_STRING); + InvalidateWindowClassesData(WC_TEXTFILE); } 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) { - const char *textfile = GetConfig(slot)->GetTextfile(file_type, slot); - this->LoadTextfile(textfile, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR); + this->OnInvalidateData(); } void SetStringParameters(int widget) const override { if (widget == WID_TF_CAPTION) { 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); } } }; From 76eab18f02e35aca5dc1010ac7b94128eeacffa7 Mon Sep 17 00:00:00 2001 From: "Johannes E. Krause" Date: Fri, 22 Mar 2019 03:18:58 +0100 Subject: [PATCH 13/22] Fix: Saving SDT_INTLIST handle unsigned values properly --- src/settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings.cpp b/src/settings.cpp index 0a7ac89ac3..c60ab6c9f2 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -276,7 +276,7 @@ static void MakeIntList(char *buf, const char *last, const void *array, int nele case SLE_VAR_U32: v = *(const uint32 *)p; p += 4; break; default: NOT_REACHED(); } - buf += seprintf(buf, last, (i == 0) ? "%d" : ",%d", v); + buf += seprintf(buf, last, IsSignedVarMemType(type) ? ((i == 0) ? "%d" : ",%d") : ((i == 0) ? "%u" : ",%u"), v); } } From f389d66e36ceda578d30bde5f8ae94fdf2103704 Mon Sep 17 00:00:00 2001 From: "Johannes E. Krause" Date: Fri, 22 Mar 2019 04:16:21 +0100 Subject: [PATCH 14/22] Fix: Loading SDT_INTLIST similar to loading SDT_NUMX --- src/settings.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index c60ab6c9f2..e6fbbfcf2c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -22,6 +22,7 @@ */ #include "stdafx.h" +#include #include "currency.h" #include "screenshot.h" #include "network/network.h" @@ -169,7 +170,8 @@ static size_t LookupManyOfMany(const char *many, const char *str) * @param maxitems the maximum number of elements the integerlist-array has * @return returns the number of items found, or -1 on an error */ -static int ParseIntList(const char *p, int *items, int maxitems) +template +static int ParseIntList(const char *p, T *items, int maxitems) { int n = 0; // number of items read so far bool comma = false; // do we accept comma? @@ -189,9 +191,9 @@ static int ParseIntList(const char *p, int *items, int maxitems) default: { if (n == maxitems) return -1; // we don't accept that many numbers 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 (sizeof(int) < sizeof(long)) v = ClampToI32(v); + if (sizeof(T) < sizeof(v)) v = Clamp(v, std::numeric_limits::min(), std::numeric_limits::max()); items[n++] = v; p = end; // first non-number comma = true; // we accept comma now @@ -217,7 +219,7 @@ static int ParseIntList(const char *p, int *items, int maxitems) */ static bool LoadIntList(const char *str, void *array, int nelems, VarType type) { - int items[64]; + unsigned long items[64]; int i, nitems; if (str == nullptr) { @@ -1534,7 +1536,7 @@ static GRFConfig *GRFLoadConfig(IniFile *ini, const char *grpname, bool is_stati /* Parse parameters */ 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) { SetDParamStr(0, filename); ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY, WL_CRITICAL); From 107283748ab599a1ae8a01f91c09e9f9a3e4bd06 Mon Sep 17 00:00:00 2001 From: "Johannes E. Krause" Date: Fri, 22 Mar 2019 04:37:53 +0100 Subject: [PATCH 15/22] Feature: SLF_HEX to print hexadecimal numbers in the config file --- src/saveload/saveload.h | 3 ++- src/settings.cpp | 14 ++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index c06e8fddaa..14c8c32315 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -471,7 +471,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_ALLOW_CONTROL = 1 << 11, ///< allow control codes 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; diff --git a/src/settings.cpp b/src/settings.cpp index e6fbbfcf2c..7fb2e72491 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -268,7 +268,7 @@ static void MakeIntList(char *buf, const char *last, const void *array, int nele const byte *p = (const byte *)array; for (i = 0; i != nelems; i++) { - switch (type) { + switch (GetVarMemType(type)) { case SLE_VAR_BL: case SLE_VAR_I8: v = *(const int8 *)p; p += 1; break; case SLE_VAR_U8: v = *(const uint8 *)p; p += 1; break; @@ -278,7 +278,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; default: NOT_REACHED(); } - buf += seprintf(buf, last, IsSignedVarMemType(type) ? ((i == 0) ? "%d" : ",%d") : ((i == 0) ? "%u" : ",%u"), 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); + } } } @@ -673,7 +679,7 @@ static void IniSaveSettings(IniFile *ini, const SettingDesc *sd, const char *grp switch (sdb->cmd) { 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_MANYOFMANY: MakeManyOfMany(buf, lastof(buf), sdb->many, i); break; default: NOT_REACHED(); @@ -701,7 +707,7 @@ static void IniSaveSettings(IniFile *ini, const SettingDesc *sd, const char *grp break; case SDT_INTLIST: - MakeIntList(buf, lastof(buf), ptr, sld->length, GetVarMemType(sld->conv)); + MakeIntList(buf, lastof(buf), ptr, sld->length, sld->conv); break; default: NOT_REACHED(); From 04ce1f0713952131014c4347e9fa9f265aebcea3 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Fri, 7 Feb 2020 17:06:48 +0100 Subject: [PATCH 16/22] Fix #7885: [Fluidsynth] Use recommended method of setting sample rate --- src/music/fluidsynth.cpp | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/music/fluidsynth.cpp b/src/music/fluidsynth.cpp index 89cb7273f5..64abe0e538 100644 --- a/src/music/fluidsynth.cpp +++ b/src/music/fluidsynth.cpp @@ -15,11 +15,13 @@ #include "midifile.hpp" #include #include "../mixer.h" +#include static struct { fluid_settings_t* settings; ///< FluidSynth settings handle fluid_synth_t* synth; ///< FluidSynth synthesizer 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. /** Factory for the FluidSynth driver. */ @@ -42,12 +44,16 @@ static const char *default_sf[] = { static void RenderMusicStream(int16 *buffer, size_t samples) { - if (!_midi.synth || !_midi.player) return; + std::unique_lock 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); } const char *MusicDriver_FluidSynth::Start(const char * const *param) { + std::lock_guard lock{ _midi.synth_mutex }; + const char *sfont_name = GetDriverParam(param, "soundfont"); 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 */ 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. */ _midi.synth = new_fluid_synth(_midi.settings); if (!_midi.synth) return "Could not open synth"; @@ -81,19 +92,23 @@ const char *MusicDriver_FluidSynth::Start(const char * const *param) _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; } void MusicDriver_FluidSynth::Stop() { MxSetMusicSource(nullptr); - this->StopSong(); - delete_fluid_synth(_midi.synth); - delete_fluid_settings(_midi.settings); + + std::lock_guard lock{ _midi.synth_mutex }; + + 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) @@ -106,6 +121,8 @@ void MusicDriver_FluidSynth::PlaySong(const MusicSongInfo &song) return; } + std::lock_guard lock{ _midi.synth_mutex }; + _midi.player = new_fluid_player(_midi.synth); if (!_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() { + std::lock_guard lock{ _midi.synth_mutex }; + if (!_midi.player) return; fluid_player_stop(_midi.player); @@ -142,6 +161,7 @@ void MusicDriver_FluidSynth::StopSong() bool MusicDriver_FluidSynth::IsSongPlaying() { + std::lock_guard lock{ _midi.synth_mutex }; if (!_midi.player) return false; return fluid_player_get_status(_midi.player) == FLUID_PLAYER_PLAYING; @@ -149,6 +169,9 @@ bool MusicDriver_FluidSynth::IsSongPlaying() void MusicDriver_FluidSynth::SetVolume(byte vol) { + std::lock_guard lock{ _midi.synth_mutex }; + if (_midi.settings == nullptr) return; + /* Allowed range of synth.gain is 0.0 to 10.0 */ /* fluidsynth's default gain is 0.2, so use this as "full * volume". Set gain using OpenTTD's volume, as a number between 0 From 9e632355f14aef4696730267d1682e7f2ba0f3a9 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Sun, 8 Sep 2019 11:04:43 +0200 Subject: [PATCH 17/22] Fix #7525: Move autorenew setting to Basic category --- src/table/company_settings.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/src/table/company_settings.ini b/src/table/company_settings.ini index e853810a17..86035b9d77 100644 --- a/src/table/company_settings.ini +++ b/src/table/company_settings.ini @@ -41,6 +41,7 @@ var = engine_renew def = false str = STR_CONFIG_SETTING_AUTORENEW_VEHICLE strhelp = STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT +cat = SC_BASIC [SDT_VAR] base = CompanySettings From 1a88fb5c910ed8badc9b7535487ff78fbdc7a38b Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Thu, 6 Feb 2020 21:23:42 +0100 Subject: [PATCH 18/22] Fix #7592: Do not cache road vehicle path within 8 tiles of destination with multiple entrances Ported from jgrpp commit 79d5be7e265df3be8b73d484f0c7261b3c23229d --- src/pathfinder/pathfinder_type.h | 3 +++ src/pathfinder/yapf/yapf_road.cpp | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/pathfinder/pathfinder_type.h b/src/pathfinder/pathfinder_type.h index f837f4840b..eb0381d8a3 100644 --- a/src/pathfinder/pathfinder_type.h +++ b/src/pathfinder/pathfinder_type.h @@ -44,6 +44,9 @@ static const int YAPF_SHIP_PATH_CACHE_LENGTH = 32; /** Maximum segments of road vehicle path cache */ static const int YAPF_ROADVEH_PATH_CACHE_SEGMENTS = 8; +/** 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 */ diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp index 248bf1a40a..1b85c8d4ec 100644 --- a/src/pathfinder/yapf/yapf_road.cpp +++ b/src/pathfinder/yapf/yapf_road.cpp @@ -251,6 +251,11 @@ public: } } + const Station *GetDestinationStation() const + { + return m_dest_station != INVALID_STATION ? Station::GetIfValid(m_dest_station) : nullptr; + } + protected: /** to access inherited path finder */ Tpf& Yapf() @@ -402,6 +407,22 @@ public: path_cache.td.pop_back(); path_cache.tile.pop_back(); } + + /* Check if target is a station, and cached path ends within 8 tiles of the dest tile */ + const Station *st = Yapf().GetDestinationStation(); + if (st) { + const RoadStop *stop = st->GetPrimaryRoadStop(v); + 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, + * 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; + non_cached_area.Expand(YAPF_ROADVEH_PATH_CACHE_DESTINATION_LIMIT); + while (!path_cache.empty() && non_cached_area.Contains(path_cache.tile.back())) { + path_cache.td.pop_back(); + path_cache.tile.pop_back(); + } + } + } } return next_trackdir; } From 2b1a7ceb4ee64292526ba4883f9cef9061992ba1 Mon Sep 17 00:00:00 2001 From: glx Date: Fri, 7 Feb 2020 23:19:57 +0100 Subject: [PATCH 19/22] Fix #7976: Don't kick the client doing the rcon --- src/network/network_server.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index dd88042a12..36a15d3ae3 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -2086,9 +2086,14 @@ uint NetworkServerKickOrBanIP(const char *ip, bool ban, const char *reason) 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()) { if (cs->client_id == CLIENT_ID_SERVER) continue; + if (cs->client_id == _redirect_console_to_client) continue; if (cs->client_address.IsInNetmask(ip)) { NetworkServerKickClient(cs->client_id, reason); n++; From a499e9acdd385b57dd43caf88af3a6f7f53716ba Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 8 Feb 2020 19:45:39 +0100 Subject: [PATCH 20/22] Update: Translations from eints russian: 2 changes by Lone_Wolf --- src/lang/russian.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 253815a159..e0815a435f 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -2320,6 +2320,7 @@ STR_NETWORK_ERROR_WRONG_PASSWORD :{WHITE}Неве STR_NETWORK_ERROR_SERVER_FULL :{WHITE}Сервер переполнен STR_NETWORK_ERROR_SERVER_BANNED :{WHITE}Вас забанили на этом сервере STR_NETWORK_ERROR_KICKED :{WHITE}Вас выкинули из игры +STR_NETWORK_ERROR_KICK_MESSAGE :{WHITE}Причина: {STRING} STR_NETWORK_ERROR_CHEATER :{WHITE}Чит-коды не разрешены на этом сервере STR_NETWORK_ERROR_TOO_MANY_COMMANDS :{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_SERVER_SHUTDOWN :{WHITE}Сервер закрыл сессию STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Сервер перезапускается...{}Пожалуйста, подождите... +STR_NETWORK_MESSAGE_KICKED :*** {STRING} был исключён из игры. Причина: ({STRING}) # Content downloading window STR_CONTENT_TITLE :{WHITE}Загрузка контента From 2f264f2c92d202608cb54cf6f06abf8e2aa0e875 Mon Sep 17 00:00:00 2001 From: glx Date: Sat, 8 Feb 2020 22:44:31 +0100 Subject: [PATCH 21/22] Change: Heading for 1.11 now --- bin/ai/compat_1.10.nut | 2 ++ bin/ai/compat_1.11.nut | 6 ++++++ bin/ai/regression/regression_info.nut | 2 +- bin/game/compat_1.10.nut | 2 ++ bin/game/compat_1.11.nut | 6 ++++++ os/os2/installer/make_installer.cmd | 2 +- os/rpm/openttd.spec | 4 ++-- os/windows/installer/install.nsi | 6 +++--- src/ai/ai_info.cpp | 3 ++- src/game/game_info.cpp | 3 ++- src/os/windows/ottdres.rc.in | 4 ++-- src/rev.cpp.in | 2 +- src/saveload/saveload.h | 2 +- src/script/api/ai_changelog.hpp | 4 +++- src/script/api/game_changelog.hpp | 4 +++- 15 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 bin/ai/compat_1.11.nut create mode 100644 bin/game/compat_1.11.nut diff --git a/bin/ai/compat_1.10.nut b/bin/ai/compat_1.10.nut index 3081fb58e8..2baaddb836 100644 --- a/bin/ai/compat_1.10.nut +++ b/bin/ai/compat_1.10.nut @@ -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. * 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 . */ + +AILog.Info("1.10 API compatibility in effect."); diff --git a/bin/ai/compat_1.11.nut b/bin/ai/compat_1.11.nut new file mode 100644 index 0000000000..3081fb58e8 --- /dev/null +++ b/bin/ai/compat_1.11.nut @@ -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 . + */ diff --git a/bin/ai/regression/regression_info.nut b/bin/ai/regression/regression_info.nut index 020b186faf..758754cfe7 100644 --- a/bin/ai/regression/regression_info.nut +++ b/bin/ai/regression/regression_info.nut @@ -4,7 +4,7 @@ class Regression extends AIInfo { 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 GetVersion() { return 1; } - function GetAPIVersion() { return "1.10"; } + function GetAPIVersion() { return "1.11"; } function GetDate() { return "2007-03-18"; } function CreateInstance() { return "Regression"; } } diff --git a/bin/game/compat_1.10.nut b/bin/game/compat_1.10.nut index 3081fb58e8..1c85766c0f 100644 --- a/bin/game/compat_1.10.nut +++ b/bin/game/compat_1.10.nut @@ -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. * 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 . */ + +GSLog.Info("1.10 API compatibility in effect."); diff --git a/bin/game/compat_1.11.nut b/bin/game/compat_1.11.nut new file mode 100644 index 0000000000..3081fb58e8 --- /dev/null +++ b/bin/game/compat_1.11.nut @@ -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 . + */ diff --git a/os/os2/installer/make_installer.cmd b/os/os2/installer/make_installer.cmd index 3addeca1ae..885b2dc623 100644 --- a/os/os2/installer/make_installer.cmd +++ b/os/os2/installer/make_installer.cmd @@ -1,6 +1,6 @@ @echo off -set OPENTTD_VERSION=1.10.0 +set OPENTTD_VERSION=1.11.0 set OPENSFX_VERSION=0.8.0 set NOSOUND_VERSION=0.8.0 set OPENGFX_VERSION=1.2.0 diff --git a/os/rpm/openttd.spec b/os/rpm/openttd.spec index 340a9886b9..134caad38e 100644 --- a/os/rpm/openttd.spec +++ b/os/rpm/openttd.spec @@ -17,9 +17,9 @@ # Name: openttd -Version: 1.10.beta2 +Version: 1.11.beta1 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 License: GPL-2.0 Group: Amusements/Games/Strategy/Other diff --git a/os/windows/installer/install.nsi b/os/windows/installer/install.nsi index 2561b76d55..b6837c559e 100644 --- a/os/windows/installer/install.nsi +++ b/os/windows/installer/install.nsi @@ -1,9 +1,9 @@ # Version numbers to update !define APPV_MAJOR 1 -!define APPV_MINOR 10 +!define APPV_MINOR 11 !define APPV_MAINT 0 -!define APPV_BUILD 1 -!define APPV_EXTRA "-beta2" +!define APPV_BUILD 0 +!define APPV_EXTRA "-beta1" !define APPNAME "OpenTTD" ; Define application name !define APPVERSION "${APPV_MAJOR}.${APPV_MINOR}.${APPV_MAINT}${APPV_EXTRA}" ; Define application version diff --git a/src/ai/ai_info.cpp b/src/ai/ai_info.cpp index 2d80003f6b..6e1ef6cecd 100644 --- a/src/ai/ai_info.cpp +++ b/src/ai/ai_info.cpp @@ -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 || 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.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) diff --git a/src/game/game_info.cpp b/src/game/game_info.cpp index 91a463bed5..a039401b32 100644 --- a/src/game/game_info.cpp +++ b/src/game/game_info.cpp @@ -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 || 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) diff --git a/src/os/windows/ottdres.rc.in b/src/os/windows/ottdres.rc.in index 5b375790a3..af27de4bdf 100644 --- a/src/os/windows/ottdres.rc.in +++ b/src/os/windows/ottdres.rc.in @@ -77,8 +77,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,10,0,!!ISODATE!! - PRODUCTVERSION 1,10,0,!!ISODATE!! + FILEVERSION 1,11,0,!!ISODATE!! + PRODUCTVERSION 1,11,0,!!ISODATE!! FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L diff --git a/src/rev.cpp.in b/src/rev.cpp.in index 003fb5556e..48b29f349d 100644 --- a/src/rev.cpp.in +++ b/src/rev.cpp.in @@ -80,4 +80,4 @@ const byte _openttd_revision_tagged = !!ISTAG!!; * final release will always have a lower version number than the released * 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; diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 14c8c32315..eeb0c58f27 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -301,7 +301,7 @@ enum SaveLoadVersion : uint16 { SLV_SCRIPT_MEMLIMIT, ///< 215 PR#7516 Limit on AI/GS memory consumption. SLV_MULTITILE_DOCKS, ///< 216 PR#7380 Multiple docks per station. 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 }; diff --git a/src/script/api/ai_changelog.hpp b/src/script/api/ai_changelog.hpp index 9eea9ab152..bcb7df67f2 100644 --- a/src/script/api/ai_changelog.hpp +++ b/src/script/api/ai_changelog.hpp @@ -13,10 +13,12 @@ * functions may still be available if you return an older API version * 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. * + * \b 1.10.0 + * * API additions: * \li AIGroup::SetPrimaryColour * \li AIGroup::SetSecondaryColour diff --git a/src/script/api/game_changelog.hpp b/src/script/api/game_changelog.hpp index 235dcee986..df8c663a03 100644 --- a/src/script/api/game_changelog.hpp +++ b/src/script/api/game_changelog.hpp @@ -13,10 +13,12 @@ * functions may still be available if you return an older API version * 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. * + * \b 1.10.0 + * * API additions: * \li GSVehicle::BuildVehicleWithRefit * \li GSVehicle::GetBuildWithRefitCapacity From e340934d04a26a8917f23f73141556e85fbae0b1 Mon Sep 17 00:00:00 2001 From: Charles Pigott Date: Sun, 9 Feb 2020 11:44:45 +0000 Subject: [PATCH 22/22] Fix #7988: Memory leak when using custom depot names --- src/depot.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/depot.cpp b/src/depot.cpp index 05e2af3d4a..9207c63629 100644 --- a/src/depot.cpp +++ b/src/depot.cpp @@ -27,6 +27,8 @@ INSTANTIATE_POOL_METHODS(Depot) */ Depot::~Depot() { + free(this->name); + if (CleaningPool()) return; if (!IsDepotTile(this->xy) || GetDepotIndex(this->xy) != this->index) {