diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj
index 6453d62b86..29921e387c 100644
--- a/projects/openttd_vs140.vcxproj
+++ b/projects/openttd_vs140.vcxproj
@@ -1094,6 +1094,7 @@
+
@@ -1161,6 +1162,7 @@
+
diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters
index 0405740d4c..1c6422b7fa 100644
--- a/projects/openttd_vs140.vcxproj.filters
+++ b/projects/openttd_vs140.vcxproj.filters
@@ -2370,6 +2370,9 @@
Script API
+
+ Script API
+
Script API
@@ -2571,6 +2574,9 @@
Script API Implementation
+
+ Script API Implementation
+
Script API Implementation
diff --git a/projects/openttd_vs141.vcxproj b/projects/openttd_vs141.vcxproj
index ecfed4a038..aea1947d8f 100644
--- a/projects/openttd_vs141.vcxproj
+++ b/projects/openttd_vs141.vcxproj
@@ -1094,6 +1094,7 @@
+
@@ -1161,6 +1162,7 @@
+
diff --git a/projects/openttd_vs141.vcxproj.filters b/projects/openttd_vs141.vcxproj.filters
index 0405740d4c..1c6422b7fa 100644
--- a/projects/openttd_vs141.vcxproj.filters
+++ b/projects/openttd_vs141.vcxproj.filters
@@ -2370,6 +2370,9 @@
Script API
+
+ Script API
+
Script API
@@ -2571,6 +2574,9 @@
Script API Implementation
+
+ Script API Implementation
+
Script API Implementation
diff --git a/projects/openttd_vs142.vcxproj b/projects/openttd_vs142.vcxproj
index 49858a3e1d..e9b31a3d77 100644
--- a/projects/openttd_vs142.vcxproj
+++ b/projects/openttd_vs142.vcxproj
@@ -1094,6 +1094,7 @@
+
@@ -1161,6 +1162,7 @@
+
diff --git a/projects/openttd_vs142.vcxproj.filters b/projects/openttd_vs142.vcxproj.filters
index 0405740d4c..1c6422b7fa 100644
--- a/projects/openttd_vs142.vcxproj.filters
+++ b/projects/openttd_vs142.vcxproj.filters
@@ -2370,6 +2370,9 @@
Script API
+
+ Script API
+
Script API
@@ -2571,6 +2574,9 @@
Script API Implementation
+
+ Script API Implementation
+
Script API Implementation
diff --git a/source.list b/source.list
index ce3c50729a..e4b0e23f6b 100644
--- a/source.list
+++ b/source.list
@@ -826,6 +826,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
@@ -895,6 +896,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 57b2213ea9..fa9ead1774 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"
@@ -170,6 +171,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..a2885ab3e2
--- /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.DefSQMethod(engine, &ScriptPriorityQueue::Insert, "Insert", 3, "xii");
+ SQAIPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::Pop, "Pop", 1, "x");
+ SQAIPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::Peek, "Peek", 1, "x");
+ SQAIPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::Exists, "Exists", 2, "xi");
+ SQAIPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::Clear, "Clear", 1, "x");
+ 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/game/game_priorityqueue.hpp.sq b/src/script/api/game/game_priorityqueue.hpp.sq
new file mode 100644
index 0000000000..8bd1ac6466
--- /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.DefSQMethod(engine, &ScriptPriorityQueue::Insert, "Insert", 3, "xii");
+ SQGSPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::Pop, "Pop", 1, "x");
+ SQGSPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::Peek, "Peek", 1, "x");
+ SQGSPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::Exists, "Exists", 2, "xi");
+ SQGSPriorityQueue.DefSQMethod(engine, &ScriptPriorityQueue::Clear, "Clear", 1, "x");
+ 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/script_priorityqueue.cpp b/src/script/api/script_priorityqueue.cpp
new file mode 100644
index 0000000000..7b5c170aa7
--- /dev/null
+++ b/src/script/api/script_priorityqueue.cpp
@@ -0,0 +1,61 @@
+/*
+ * 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 "../../debug.h"
+
+#include "../../safeguards.h"
+
+
+bool ScriptPriorityQueue::Insert(int64 item, int64 priority)
+{
+ auto inserted = this->items.insert(item);
+ if (inserted.second) this->queue.emplace(priority, item);
+ return inserted.second;
+}
+
+int64 ScriptPriorityQueue::Pop()
+{
+ EnforcePrecondition(INT64_MAX, !this->IsEmpty());
+
+ int64 item = this->queue.top().second;
+ this->queue.pop();
+ this->items.erase(item);
+ return item;
+}
+
+int64 ScriptPriorityQueue::Peek()
+{
+ EnforcePrecondition(INT64_MAX, !this->IsEmpty());
+
+ return this->queue.top().second;
+}
+
+bool ScriptPriorityQueue::Exists(int64 item)
+{
+ return this->items.find(item) != this->items.end();
+}
+
+void ScriptPriorityQueue::Clear()
+{
+ this->items.clear();
+ this->queue = ItemQueue();
+}
+
+bool ScriptPriorityQueue::IsEmpty()
+{
+ return this->items.empty();
+}
+
+int32 ScriptPriorityQueue::Count()
+{
+ return (int32)this->items.size();
+}
diff --git a/src/script/api/script_priorityqueue.hpp b/src/script/api/script_priorityqueue.hpp
new file mode 100644
index 0000000000..82b03defb2
--- /dev/null
+++ b/src/script/api/script_priorityqueue.hpp
@@ -0,0 +1,85 @@
+/*
+ * 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 {
+private:
+ typedef std::pair PriorityItem;
+ struct PriorityComparator {
+ bool operator()(const PriorityItem &lhs, const PriorityItem &rhs)
+ {
+ return lhs.first > rhs.first;
+ }
+ };
+
+ typedef std::priority_queue, PriorityComparator> ItemQueue;
+ typedef std::unordered_set ItemSet;
+
+ ItemSet items; ///< The items in the queue
+ ItemQueue queue; ///< The priority list
+
+public:
+ /**
+ * Add a single item to the queue.
+ * @param item The item to add. 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(int64 item, int64 priority);
+
+ /**
+ * Remove and return the item with the lowest priority.
+ * @return The item with the lowest priority, removed from the queue.
+ * @pre !IsEmpty()
+ */
+ int64 Pop();
+
+ /**
+ * Get the item with the lowest priority, keeping it in the queue.
+ * @return The item with the lowest priority.
+ * @pre !IsEmpty()
+ */
+ int64 Peek();
+
+ /**
+ * Check if an items is already included in the queue.
+ * @return true if the items is already in the queue.
+ */
+ bool Exists(int64 item);
+
+ /**
+ * Clear the queue, making Count() returning 0 and IsEmpty() returning true.
+ */
+ void Clear();
+
+ /**
+ * 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.
+ */
+ int32 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