From f11cd8f2d07b69eeedb5c3d3dc7c9ade37151707 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 27 May 2020 21:09:31 +0100 Subject: [PATCH 1/9] Fix: Compilation warnings in story_gui and script_story_page See: #7896 --- src/script/api/script_story_page.cpp | 8 ++++++++ src/story_gui.cpp | 8 ++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/script/api/script_story_page.cpp b/src/script/api/script_story_page.cpp index 39ae3d53ff..8fda69e6f5 100644 --- a/src/script/api/script_story_page.cpp +++ b/src/script/api/script_story_page.cpp @@ -83,6 +83,10 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) case SPET_BUTTON_VEHICLE: refid = reference; break; + case SPET_TEXT: + break; + default: + NOT_REACHED(); } if (!ScriptObject::DoCommand(reftile, @@ -124,6 +128,10 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) case SPET_BUTTON_VEHICLE: refid = reference; break; + case SPET_TEXT: + break; + default: + NOT_REACHED(); } return ScriptObject::DoCommand(reftile, diff --git a/src/story_gui.cpp b/src/story_gui.cpp index 96c411fe9c..2de96a1a52 100644 --- a/src/story_gui.cpp +++ b/src/story_gui.cpp @@ -459,7 +459,7 @@ protected: } } /* Position element in main column */ - LayoutCacheElement ce{ pe }; + LayoutCacheElement ce{ pe, {} }; ce.bounds.left = left_offset; ce.bounds.right = max_width - right_offset; ce.bounds.top = main_y; @@ -479,7 +479,7 @@ protected: std::vector &cur_floats = (fl == ElementFloat::Left) ? left_floats : right_floats; /* Position element */ cur_width = max(cur_width, this->GetPageElementFloatWidth(*pe)); - LayoutCacheElement ce{ pe }; + LayoutCacheElement ce{ pe, {} }; ce.bounds.left = (fl == ElementFloat::Left) ? 0 : (max_width - cur_width); ce.bounds.right = (fl == ElementFloat::Left) ? cur_width : max_width; ce.bounds.top = cur_y; @@ -745,11 +745,7 @@ public: case SPET_BUTTON_PUSH: case SPET_BUTTON_TILE: case SPET_BUTTON_VEHICLE: { - const int height = FONT_HEIGHT_NORMAL; const int tmargin = WD_BEVEL_TOP + WD_FRAMETEXT_TOP; - const int bmargin = WD_BEVEL_BOTTOM + WD_FRAMETEXT_BOTTOM; - const int width = ce.bounds.right - ce.bounds.left; - const int hmargin = width / 5; const FrameFlags frame = this->active_button_id == ce.pe->index ? FR_LOWERED : FR_NONE; const Colours bgcolour = StoryPageButtonData{ ce.pe->referenced_id }.GetColour(); From 16e5f610f77cccca097d3df735104578571b81ef Mon Sep 17 00:00:00 2001 From: TechGeekNZ Date: Thu, 28 May 2020 15:15:59 +1200 Subject: [PATCH 2/9] Cleanup: Correct typographic errors in code comments. --- src/engine_base.h | 2 +- src/script/api/script_order.hpp | 2 +- src/station_base.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine_base.h b/src/engine_base.h index f388e894ba..2e434b589e 100644 --- a/src/engine_base.h +++ b/src/engine_base.h @@ -29,7 +29,7 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> { uint16 reliability_final; ///< Final reliability of the engine. uint16 duration_phase_1; ///< First reliability phase in months, increasing reliability from #reliability_start to #reliability_max. uint16 duration_phase_2; ///< Second reliability phase in months, keeping #reliability_max. - uint16 duration_phase_3; ///< Third reliability phase on months, decaying to #reliability_final. + uint16 duration_phase_3; ///< Third reliability phase in months, decaying to #reliability_final. byte flags; ///< Flags of the engine. @see EngineFlags CompanyMask preview_asked; ///< Bit for each company which has already been offered a preview. CompanyID preview_company; ///< Company which is currently being offered a preview \c INVALID_COMPANY means no company. diff --git a/src/script/api/script_order.hpp b/src/script/api/script_order.hpp index cce74fa5dc..0086e39ca2 100644 --- a/src/script/api/script_order.hpp +++ b/src/script/api/script_order.hpp @@ -29,7 +29,7 @@ public: /** No more space for orders */ ERR_ORDER_TOO_MANY, // [STR_ERROR_NO_MORE_SPACE_FOR_ORDERS] - /** Destination of new order is to far away from the previous order */ + /** Destination of new order is too far away from the previous order */ ERR_ORDER_TOO_FAR_AWAY_FROM_PREVIOUS_DESTINATION, // [STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION] /** Aircraft has not enough range to copy/share orders. */ diff --git a/src/station_base.h b/src/station_base.h index 75b1c1112f..4f16469766 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -42,7 +42,7 @@ public: /** * Invalid constructor. This can't be called as a FlowStat must not be * empty. However, the constructor must be defined and reachable for - * FlwoStat to be used in a std::map. + * FlowStat to be used in a std::map. */ inline FlowStat() {NOT_REACHED();} From 281d93f60052703b82394ab63fcb063ba700e004 Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 30 May 2020 19:45:39 +0200 Subject: [PATCH 3/9] Update: Translations from eints croatian: 1 change by VoyagerOne --- src/lang/croatian.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/croatian.txt b/src/lang/croatian.txt index 7f20426f48..0bf3fab71a 100644 --- a/src/lang/croatian.txt +++ b/src/lang/croatian.txt @@ -1031,6 +1031,7 @@ STR_GAME_OPTIONS_CURRENCY_MXN :Meksički Pesos STR_GAME_OPTIONS_CURRENCY_NTD :Novi Tajvanski Dolar (NTD) STR_GAME_OPTIONS_CURRENCY_CNY :Kineski Renminbi (CNY) STR_GAME_OPTIONS_CURRENCY_HKD :Hongkonški Dolar (HKD) +STR_GAME_OPTIONS_CURRENCY_INR :Indijska Rupija (INR) ############ end of currency region STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME :{BLACK}Cestovna vozila From a9b3312d1a4962d07a2e7976e8352c7113201a9e Mon Sep 17 00:00:00 2001 From: Yexo Date: Mon, 1 Jun 2020 10:19:47 +0200 Subject: [PATCH 4/9] Fix #8024: make online content gui more responsive while loading Previously the internal content list was invalidated and sorted for every new item added. Now the sorting is delayed until the GUI is drawn, which means we only sort once per GUI tick. Since the amount of incoming items per GUI tick is not controlled by the GUI but rather by network speed, we were previously doing a lot of duplicate work per tick, causing the mouse cursor to lag while the list was initialized. --- src/network/network_content_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index 6083396eeb..dd87a4948b 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -951,7 +951,7 @@ public: { if (this->auto_select && !rci->IsSelected()) _network_content_client.ToggleSelectedState(rci); this->content.ForceRebuild(); - this->InvalidateData(); + this->InvalidateData(0, false); } void OnDownloadComplete(ContentID cid) override From f827bc8c1ae83ea4f71347da9c8cb0468f386452 Mon Sep 17 00:00:00 2001 From: Yexo Date: Mon, 1 Jun 2020 11:25:58 +0200 Subject: [PATCH 5/9] Fix #8166: don't crash on loading an invalid roadtype newgrf Initialization code for GRFFile::roadtype_map was copied from railtype_map. But while RailType is a byte-sized enum and could thus be initialized via memset, RoadType doesn't have a defined size. --- src/newgrf.cpp | 6 +++--- src/newgrf.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 6b5a2f9ce1..6f12fbbf9f 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -8718,18 +8718,18 @@ GRFFile::GRFFile(const GRFConfig *config) } /* Initialise rail type map with default rail types */ - memset(this->railtype_map, INVALID_RAILTYPE, sizeof(this->railtype_map)); + std::fill(std::begin(this->railtype_map), std::end(this->railtype_map), INVALID_RAILTYPE); this->railtype_map[0] = RAILTYPE_RAIL; this->railtype_map[1] = RAILTYPE_ELECTRIC; this->railtype_map[2] = RAILTYPE_MONO; this->railtype_map[3] = RAILTYPE_MAGLEV; /* Initialise road type map with default road types */ - memset(this->roadtype_map, INVALID_ROADTYPE, sizeof(this->roadtype_map)); + std::fill(std::begin(this->roadtype_map), std::end(this->roadtype_map), INVALID_ROADTYPE); this->roadtype_map[0] = ROADTYPE_ROAD; /* Initialise tram type map with default tram types */ - memset(this->tramtype_map, INVALID_ROADTYPE, sizeof(this->tramtype_map)); + std::fill(std::begin(this->tramtype_map), std::end(this->tramtype_map), INVALID_ROADTYPE); this->tramtype_map[0] = ROADTYPE_TRAM; /* Copy the initial parameter list diff --git a/src/newgrf.h b/src/newgrf.h index 00394c681c..65df3698e4 100644 --- a/src/newgrf.h +++ b/src/newgrf.h @@ -132,7 +132,7 @@ struct GRFFile : ZeroedMemoryAllocator { std::vector roadtype_list; ///< Roadtype translation table (road) RoadType roadtype_map[ROADTYPE_END]; - std::vector tramtype_list; ///, Roadtype translation table (tram) + std::vector tramtype_list; ///< Roadtype translation table (tram) RoadType tramtype_map[ROADTYPE_END]; CanalProperties canal_local_properties[CF_END]; ///< Canal properties as set by this NewGRF From b5ca2161d93e634f9938af7d9ca1fb1ddab3d501 Mon Sep 17 00:00:00 2001 From: glx Date: Fri, 29 May 2020 16:14:53 +0200 Subject: [PATCH 6/9] Fix #7970: [Win32] Disable event loop on crash to prevent recursive faults --- src/os/windows/crashlog_win.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/os/windows/crashlog_win.cpp b/src/os/windows/crashlog_win.cpp index 9585bdf20f..7a1a524aa5 100644 --- a/src/os/windows/crashlog_win.cpp +++ b/src/os/windows/crashlog_win.cpp @@ -540,6 +540,9 @@ void *_safe_esp = nullptr; static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep) { + /* Disable our event loop. */ + SetWindowLongPtr(GetActiveWindow(), GWLP_WNDPROC, (LONG_PTR)&DefWindowProc); + if (CrashLogWindows::current != nullptr) { CrashLog::AfterCrashLogCleanup(); ExitProcess(2); From b3ddf2c9072b0dc0a81943acad9d97e5977ccd5e Mon Sep 17 00:00:00 2001 From: glx Date: Fri, 29 May 2020 19:22:22 +0200 Subject: [PATCH 7/9] Fix: [Win32] Crash message not fitting in crash dialog --- src/os/windows/ottdres.rc.in | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/os/windows/ottdres.rc.in b/src/os/windows/ottdres.rc.in index 8116de9035..a2f8c28f57 100644 --- a/src/os/windows/ottdres.rc.in +++ b/src/os/windows/ottdres.rc.in @@ -44,17 +44,17 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT // Dialog // -100 DIALOG DISCARDABLE 0, 0, 305, 99 +100 DIALOG DISCARDABLE 0, 0, 305, 101 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Fatal Application Failure" FONT 8, "MS Sans Serif" BEGIN - PUSHBUTTON "&Close",12,7,80,50,14 - PUSHBUTTON "&Emergency save",13,155,80,68,14 - PUSHBUTTON "",15,243,80,55,14 - EDITTEXT 11,7,101,291,118,ES_MULTILINE | ES_READONLY | WS_VSCROLL | + PUSHBUTTON "&Close",12,7,82,60,14 + PUSHBUTTON "&Emergency save",13,158,82,60,14 + PUSHBUTTON "",15,238,82,60,14 + EDITTEXT 11,7,103,291,118,ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP - LTEXT "",10,36,7,262,65 + LTEXT "",10,36,5,262,72 ICON 100,IDC_STATIC,9,9,20,20 END From 764497206ab9457ab5dff3ea7851546da9259cc4 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Mon, 1 Jun 2020 19:26:23 +0200 Subject: [PATCH 8/9] Fix #8066: Try another fallback colourspace if first one fails --- src/video/cocoa/wnd_quartz.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video/cocoa/wnd_quartz.mm b/src/video/cocoa/wnd_quartz.mm index 8549100d90..edc9c50081 100644 --- a/src/video/cocoa/wnd_quartz.mm +++ b/src/video/cocoa/wnd_quartz.mm @@ -318,6 +318,8 @@ bool WindowQuartzSubdriver::SetVideoMode(int width, int height, int bpp) [this->window setColorSpace:[NSColorSpace sRGBColorSpace]]; this->color_space = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); + if (this->color_space == nullptr) this->color_space = CGColorSpaceCreateDeviceRGB(); + if (this->color_space == nullptr) error("Could not get a valid colour space for drawing."); bool ret = WindowResized(); this->UpdatePalette(0, 256); From 1c0ba07c3cb4f393b56063e2d631fbb2d73219b1 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Sun, 19 Apr 2020 00:53:30 +0200 Subject: [PATCH 9/9] Add: [Script] Native priority queue; useful e.g. for pathfinders. --- projects/openttd_vs140.vcxproj | 2 + projects/openttd_vs140.vcxproj.filters | 6 + projects/openttd_vs141.vcxproj | 2 + projects/openttd_vs141.vcxproj.filters | 6 + projects/openttd_vs142.vcxproj | 2 + projects/openttd_vs142.vcxproj.filters | 6 + source.list | 2 + src/ai/ai_instance.cpp | 2 + src/game/game_instance.cpp | 2 + src/script/api/ai/ai_priorityqueue.hpp.sq | 31 +++++ src/script/api/ai_changelog.hpp | 3 + src/script/api/game/game_priorityqueue.hpp.sq | 31 +++++ src/script/api/game_changelog.hpp | 1 + src/script/api/script_priorityqueue.cpp | 107 ++++++++++++++++++ src/script/api/script_priorityqueue.hpp | 94 +++++++++++++++ .../template/template_priorityqueue.hpp.sq | 19 ++++ src/script/script_instance.cpp | 8 ++ src/script/script_instance.hpp | 12 ++ 18 files changed, 336 insertions(+) create mode 100644 src/script/api/ai/ai_priorityqueue.hpp.sq create mode 100644 src/script/api/game/game_priorityqueue.hpp.sq create mode 100644 src/script/api/script_priorityqueue.cpp create mode 100644 src/script/api/script_priorityqueue.hpp create mode 100644 src/script/api/template/template_priorityqueue.hpp.sq diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj index 4e7f7b7c8d..20253a2065 100644 --- a/projects/openttd_vs140.vcxproj +++ b/projects/openttd_vs140.vcxproj @@ -1096,6 +1096,7 @@ + @@ -1163,6 +1164,7 @@ + diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters index fd5c07157c..11e9821ffe 100644 --- a/projects/openttd_vs140.vcxproj.filters +++ b/projects/openttd_vs140.vcxproj.filters @@ -2379,6 +2379,9 @@ Script API + + Script API + Script API @@ -2580,6 +2583,9 @@ Script API Implementation + + Script API Implementation + Script API Implementation diff --git a/projects/openttd_vs141.vcxproj b/projects/openttd_vs141.vcxproj index 4ab1ad85df..7b0da9569c 100644 --- a/projects/openttd_vs141.vcxproj +++ b/projects/openttd_vs141.vcxproj @@ -1096,6 +1096,7 @@ + @@ -1163,6 +1164,7 @@ + diff --git a/projects/openttd_vs141.vcxproj.filters b/projects/openttd_vs141.vcxproj.filters index fd5c07157c..11e9821ffe 100644 --- a/projects/openttd_vs141.vcxproj.filters +++ b/projects/openttd_vs141.vcxproj.filters @@ -2379,6 +2379,9 @@ Script API + + Script API + Script API @@ -2580,6 +2583,9 @@ Script API Implementation + + Script API Implementation + Script API Implementation diff --git a/projects/openttd_vs142.vcxproj b/projects/openttd_vs142.vcxproj index 2539fe1d5f..db497537db 100644 --- a/projects/openttd_vs142.vcxproj +++ b/projects/openttd_vs142.vcxproj @@ -1096,6 +1096,7 @@ + @@ -1163,6 +1164,7 @@ + diff --git a/projects/openttd_vs142.vcxproj.filters b/projects/openttd_vs142.vcxproj.filters index fd5c07157c..11e9821ffe 100644 --- a/projects/openttd_vs142.vcxproj.filters +++ b/projects/openttd_vs142.vcxproj.filters @@ -2379,6 +2379,9 @@ Script API + + Script API + Script API @@ -2580,6 +2583,9 @@ Script API Implementation + + Script API Implementation + Script API Implementation diff --git a/source.list b/source.list index cc9d10c998..b023b9ba4b 100644 --- a/source.list +++ b/source.list @@ -830,6 +830,7 @@ script/api/script_marine.hpp script/api/script_news.hpp script/api/script_object.hpp script/api/script_order.hpp +script/api/script_priorityqueue.hpp script/api/script_rail.hpp script/api/script_railtypelist.hpp script/api/script_road.hpp @@ -899,6 +900,7 @@ script/api/script_marine.cpp script/api/script_news.cpp script/api/script_object.cpp script/api/script_order.cpp +script/api/script_priorityqueue.cpp script/api/script_rail.cpp script/api/script_railtypelist.cpp script/api/script_road.cpp diff --git a/src/ai/ai_instance.cpp b/src/ai/ai_instance.cpp index a4d06763fa..49f8cff64d 100644 --- a/src/ai/ai_instance.cpp +++ b/src/ai/ai_instance.cpp @@ -57,6 +57,7 @@ #include "../script/api/ai/ai_map.hpp.sq" #include "../script/api/ai/ai_marine.hpp.sq" #include "../script/api/ai/ai_order.hpp.sq" +#include "../script/api/ai/ai_priorityqueue.hpp.sq" #include "../script/api/ai/ai_rail.hpp.sq" #include "../script/api/ai/ai_railtypelist.hpp.sq" #include "../script/api/ai/ai_road.hpp.sq" @@ -164,6 +165,7 @@ void AIInstance::RegisterAPI() SQAIMap_Register(this->engine); SQAIMarine_Register(this->engine); SQAIOrder_Register(this->engine); + SQAIPriorityQueue_Register(this->engine); SQAIRail_Register(this->engine); SQAIRailTypeList_Register(this->engine); SQAIRoad_Register(this->engine); diff --git a/src/game/game_instance.cpp b/src/game/game_instance.cpp index 4424c801c6..47d51e28ee 100644 --- a/src/game/game_instance.cpp +++ b/src/game/game_instance.cpp @@ -59,6 +59,7 @@ #include "../script/api/game/game_marine.hpp.sq" #include "../script/api/game/game_news.hpp.sq" #include "../script/api/game/game_order.hpp.sq" +#include "../script/api/game/game_priorityqueue.hpp.sq" #include "../script/api/game/game_rail.hpp.sq" #include "../script/api/game/game_railtypelist.hpp.sq" #include "../script/api/game/game_road.hpp.sq" @@ -173,6 +174,7 @@ void GameInstance::RegisterAPI() SQGSMarine_Register(this->engine); SQGSNews_Register(this->engine); SQGSOrder_Register(this->engine); + SQGSPriorityQueue_Register(this->engine); SQGSRail_Register(this->engine); SQGSRailTypeList_Register(this->engine); SQGSRoad_Register(this->engine); diff --git a/src/script/api/ai/ai_priorityqueue.hpp.sq b/src/script/api/ai/ai_priorityqueue.hpp.sq new file mode 100644 index 0000000000..6e5fcf82e9 --- /dev/null +++ b/src/script/api/ai/ai_priorityqueue.hpp.sq @@ -0,0 +1,31 @@ +/* + * 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 . + */ + +/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */ + +#include "../script_priorityqueue.hpp" +#include "../template/template_priorityqueue.hpp.sq" + + +template <> const char *GetClassName() { return "AIPriorityQueue"; } + +void SQAIPriorityQueue_Register(Squirrel *engine) +{ + DefSQClass SQAIPriorityQueue("AIPriorityQueue"); + SQAIPriorityQueue.PreRegister(engine); + SQAIPriorityQueue.AddConstructor(engine, "x"); + + SQAIPriorityQueue.DefSQAdvancedMethod(engine, &ScriptPriorityQueue::Insert, "Insert"); + SQAIPriorityQueue.DefSQAdvancedMethod(engine, &ScriptPriorityQueue::Pop, "Pop"); + SQAIPriorityQueue.DefSQAdvancedMethod(engine, &ScriptPriorityQueue::Peek, "Peek"); + SQAIPriorityQueue.DefSQAdvancedMethod(engine, &ScriptPriorityQueue::Exists, "Exists"); + SQAIPriorityQueue.DefSQAdvancedMethod(engine, &ScriptPriorityQueue::Clear, "Clear"); + SQAIPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::IsEmpty, "IsEmpty", 1, "x"); + SQAIPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::Count, "Count", 1, "x"); + + SQAIPriorityQueue.PostRegister(engine); +} diff --git a/src/script/api/ai_changelog.hpp b/src/script/api/ai_changelog.hpp index bcb7df67f2..a579bb27bc 100644 --- a/src/script/api/ai_changelog.hpp +++ b/src/script/api/ai_changelog.hpp @@ -17,6 +17,9 @@ * * This version is not yet released. The following changes are not set in stone yet. * + * API additions: + * \li AIPriorityQueue + * * \b 1.10.0 * * API additions: diff --git a/src/script/api/game/game_priorityqueue.hpp.sq b/src/script/api/game/game_priorityqueue.hpp.sq new file mode 100644 index 0000000000..fade5e2a1e --- /dev/null +++ b/src/script/api/game/game_priorityqueue.hpp.sq @@ -0,0 +1,31 @@ +/* + * 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 . + */ + +/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */ + +#include "../script_priorityqueue.hpp" +#include "../template/template_priorityqueue.hpp.sq" + + +template <> const char *GetClassName() { return "GSPriorityQueue"; } + +void SQGSPriorityQueue_Register(Squirrel *engine) +{ + DefSQClass SQGSPriorityQueue("GSPriorityQueue"); + SQGSPriorityQueue.PreRegister(engine); + SQGSPriorityQueue.AddConstructor(engine, "x"); + + SQGSPriorityQueue.DefSQAdvancedMethod(engine, &ScriptPriorityQueue::Insert, "Insert"); + SQGSPriorityQueue.DefSQAdvancedMethod(engine, &ScriptPriorityQueue::Pop, "Pop"); + SQGSPriorityQueue.DefSQAdvancedMethod(engine, &ScriptPriorityQueue::Peek, "Peek"); + SQGSPriorityQueue.DefSQAdvancedMethod(engine, &ScriptPriorityQueue::Exists, "Exists"); + SQGSPriorityQueue.DefSQAdvancedMethod(engine, &ScriptPriorityQueue::Clear, "Clear"); + SQGSPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::IsEmpty, "IsEmpty", 1, "x"); + SQGSPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::Count, "Count", 1, "x"); + + SQGSPriorityQueue.PostRegister(engine); +} diff --git a/src/script/api/game_changelog.hpp b/src/script/api/game_changelog.hpp index 69c4d971a5..fc917a0120 100644 --- a/src/script/api/game_changelog.hpp +++ b/src/script/api/game_changelog.hpp @@ -24,6 +24,7 @@ * \li GSStoryPage::MakePushButtonReference * \li GSStoryPage::MakeTileButtonReference * \li GSStoryPage::MakeVehicleButtonReference + * \li GSPriorityQueue * * \b 1.10.0 * diff --git a/src/script/api/script_priorityqueue.cpp b/src/script/api/script_priorityqueue.cpp new file mode 100644 index 0000000000..3130084126 --- /dev/null +++ b/src/script/api/script_priorityqueue.cpp @@ -0,0 +1,107 @@ +/* + * 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 . + */ + +/** @file script_priorityqueue.cpp Implementation of ScriptPriorityQueue. */ + +#include "../../stdafx.h" +#include "script_priorityqueue.hpp" +#include "script_error.hpp" +#include "../squirrel_helper.hpp" +#include "../script_instance.hpp" +#include "../../debug.h" +#include + +#include "../../safeguards.h" + + +static bool operator==(const ScriptPriorityQueue::PriorityItem &lhs, const HSQOBJECT &rhs) +{ + return lhs.second._type == rhs._type && lhs.second._unVal.raw == rhs._unVal.raw; +} + + +ScriptPriorityQueue::~ScriptPriorityQueue() +{ + /* Release reference to stored objects. */ + auto inst = ScriptObject::GetActiveInstance(); + if (!inst->InShutdown()) { + for (auto &i : this->queue) inst->ReleaseSQObject(const_cast(&i.second)); + } +} + +SQInteger ScriptPriorityQueue::Insert(HSQUIRRELVM vm) +{ + HSQOBJECT item; + int64 priority; + sq_resetobject(&item); + sq_getstackobj(vm, 2, &item); + sq_getinteger(vm, 3, &priority); + + sq_addref(vm, &item); // Keep object alive. + + this->queue.emplace_back(priority, item); + std::push_heap(this->queue.begin(), this->queue.end(), this->comp); + + return SQConvert::Return(vm, true); +} + +SQInteger ScriptPriorityQueue::Pop(HSQUIRRELVM vm) +{ + if (this->IsEmpty()) { + ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); + sq_pushnull(vm); + return 1; + } + + HSQOBJECT item = this->queue.front().second; + std::pop_heap(this->queue.begin(), this->queue.end(), this->comp); + this->queue.pop_back(); + + /* Store the object on the Squirrel stack before releasing it to make sure the ref count can't drop to zero. */ + auto ret = SQConvert::Return(vm, item); + sq_release(vm, &item); + return ret; +} + +SQInteger ScriptPriorityQueue::Peek(HSQUIRRELVM vm) +{ + if (this->IsEmpty()) { + ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); + sq_pushnull(vm); + return 1; + } + + return SQConvert::Return(vm, this->queue.front().second); +} + +SQInteger ScriptPriorityQueue::Exists(HSQUIRRELVM vm) +{ + HSQOBJECT item; + sq_resetobject(&item); + sq_getstackobj(vm, 2, &item); + + return SQConvert::Return(vm, std::find(this->queue.cbegin(), this->queue.cend(), item) != this->queue.cend()); +} + +SQInteger ScriptPriorityQueue::Clear(HSQUIRRELVM vm) +{ + /* Release reference to stored objects. */ + for (auto &i : this->queue) sq_release(vm, const_cast(&i.second)); + this->queue.clear(); + + return 0; +} + +bool ScriptPriorityQueue::IsEmpty() +{ + return this->queue.empty(); +} + +SQInteger ScriptPriorityQueue::Count() +{ + return (SQInteger)this->queue.size(); +} diff --git a/src/script/api/script_priorityqueue.hpp b/src/script/api/script_priorityqueue.hpp new file mode 100644 index 0000000000..5f8718e424 --- /dev/null +++ b/src/script/api/script_priorityqueue.hpp @@ -0,0 +1,94 @@ +/* + * 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 . + */ + +/** @file script_priorityqueue.hpp A queue that keeps a list of items sorted by a priority. */ +/** @defgroup ScriptPriorityQueue Classes that create a priority queue of items. */ + +#ifndef SCRIPT_PRIORITYQUEUE_HPP +#define SCRIPT_PRIORITYQUEUE_HPP + +#include "script_object.hpp" +#include +#include + +/** + * Class that creates a queue which keeps its items ordered by an item priority. + * @api ai game + */ +class ScriptPriorityQueue : public ScriptObject { +public: + typedef std::pair PriorityItem; +private: + struct PriorityComparator { + bool operator()(const PriorityItem &lhs, const PriorityItem &rhs) const noexcept + { + return lhs.first > rhs.first; + } + }; + + PriorityComparator comp; + std::vector queue; ///< The priority list + +public: + ~ScriptPriorityQueue(); + +#ifdef DOXYGEN_API + /** + * Add a single item to the queue. + * @param item The item to add. Can be any Squirrel type. Should be unique, otherwise it is ignored. + * @param priority The priority to assign the item. + * @return True if the item was inserted, false if it was already in the queue. + */ + bool Insert(void *item, int64 priority); + + /** + * Remove and return the item with the lowest priority. + * @return The item with the lowest priority, removed from the queue. Returns null on an empty queue. + * @pre !IsEmpty() + */ + void *Pop(); + + /** + * Get the item with the lowest priority, keeping it in the queue. + * @return The item with the lowest priority. Returns null on an empty queue. + * @pre !IsEmpty() + */ + void *Peek(); + + /** + * Check if an items is already included in the queue. + * @return true if the items is already in the queue. + * @note Performance is O(n), use only when absolutely required. + */ + bool Exists(void *item); + + /** + * Clear the queue, making Count() returning 0 and IsEmpty() returning true. + */ + void Clear(); +#else + SQInteger Insert(HSQUIRRELVM vm); + SQInteger Pop(HSQUIRRELVM vm); + SQInteger Peek(HSQUIRRELVM vm); + SQInteger Exists(HSQUIRRELVM vm); + SQInteger Clear(HSQUIRRELVM vm); +#endif + + /** + * Check if the queue is empty. + * @return true if the queue is empty. + */ + bool IsEmpty(); + + /** + * Returns the amount of items in the queue. + * @return amount of items in the queue. + */ + SQInteger Count(); +}; + +#endif /* SCRIPT_PRIORITYQUEUE_HPP */ diff --git a/src/script/api/template/template_priorityqueue.hpp.sq b/src/script/api/template/template_priorityqueue.hpp.sq new file mode 100644 index 0000000000..14c63324fb --- /dev/null +++ b/src/script/api/template/template_priorityqueue.hpp.sq @@ -0,0 +1,19 @@ +/* + * 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 . + */ + +/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */ + +#include "../script_priorityqueue.hpp" + +namespace SQConvert { + /* Allow ScriptPriorityQueue to be used as Squirrel parameter */ + template <> inline ScriptPriorityQueue *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptPriorityQueue *)instance; } + template <> inline ScriptPriorityQueue &GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptPriorityQueue *)instance; } + template <> inline const ScriptPriorityQueue *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptPriorityQueue *)instance; } + template <> inline const ScriptPriorityQueue &GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptPriorityQueue *)instance; } + template <> inline int Return(HSQUIRRELVM vm, ScriptPriorityQueue *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "PriorityQueue", res, nullptr, DefSQDestructorCallback, true); return 1; } +} // namespace SQConvert diff --git a/src/script/script_instance.cpp b/src/script/script_instance.cpp index a38a315ffc..81283cb772 100644 --- a/src/script/script_instance.cpp +++ b/src/script/script_instance.cpp @@ -58,6 +58,7 @@ ScriptInstance::ScriptInstance(const char *APIName) : is_save_data_on_stack(false), suspend(0), is_paused(false), + in_shutdown(false), callback(nullptr) { this->storage = new ScriptStorage(); @@ -136,6 +137,7 @@ bool ScriptInstance::LoadCompatibilityScripts(const char *api_version, Subdirect ScriptInstance::~ScriptInstance() { ScriptObject::ActiveInstance active(this); + this->in_shutdown = true; if (instance != nullptr) this->engine->ReleaseObject(this->instance); if (engine != nullptr) delete this->engine; @@ -154,6 +156,7 @@ void ScriptInstance::Died() { DEBUG(script, 0, "The script died unexpectedly."); this->is_dead = true; + this->in_shutdown = true; this->last_allocated_memory = this->GetAllocatedMemory(); // Update cache @@ -718,3 +721,8 @@ size_t ScriptInstance::GetAllocatedMemory() const if (this->engine == nullptr) return this->last_allocated_memory; return this->engine->GetAllocatedMemory(); } + +void ScriptInstance::ReleaseSQObject(HSQOBJECT *obj) +{ + if (!this->in_shutdown) this->engine->ReleaseObject(obj); +} diff --git a/src/script/script_instance.hpp b/src/script/script_instance.hpp index e5024c80bc..c097e0eb7b 100644 --- a/src/script/script_instance.hpp +++ b/src/script/script_instance.hpp @@ -200,6 +200,17 @@ public: size_t GetAllocatedMemory() const; + /** + * Indicate whether this instance is currently being destroyed. + */ + inline bool InShutdown() const { return this->in_shutdown; } + + /** + * Decrease the ref count of a squirrel object. + * @param obj The object to release. + **/ + void ReleaseSQObject(HSQOBJECT *obj); + protected: class Squirrel *engine; ///< A wrapper around the squirrel vm. const char *versionAPI; ///< Current API used by this script. @@ -242,6 +253,7 @@ private: bool is_save_data_on_stack; ///< Is the save data still on the squirrel stack? int suspend; ///< The amount of ticks to suspend this script before it's allowed to continue. bool is_paused; ///< Is the script paused? (a paused script will not be executed until unpaused) + bool in_shutdown; ///< Is this instance currently being destructed? Script_SuspendCallbackProc *callback; ///< Callback that should be called in the next tick the script runs. size_t last_allocated_memory; ///< Last known allocated memory value (for display for crashed scripts)