From ee789a1197ceaa034ef48963911d07d5c3bbaad8 Mon Sep 17 00:00:00 2001 From: glx22 Date: Sat, 29 Nov 2025 02:05:40 +0100 Subject: [PATCH] Change: [Script] ScriptList::[Remove|Keep][XXXValue|List] are now suspendable --- src/script/api/script_controller.cpp | 6 +++ src/script/api/script_controller.hpp | 6 +++ src/script/api/script_list.cpp | 45 +++++++++--------- src/script/api/script_list.hpp | 70 +++++++++++++++++++++++++++- 4 files changed, 102 insertions(+), 25 deletions(-) diff --git a/src/script/api/script_controller.cpp b/src/script/api/script_controller.cpp index 7c22aab52c..f0a382f60a 100644 --- a/src/script/api/script_controller.cpp +++ b/src/script/api/script_controller.cpp @@ -84,6 +84,12 @@ ScriptController::ScriptController(::CompanyID company) : return ScriptObject::GetActiveInstance().GetOpsTillSuspend(); } +/* static */ void ScriptController::DecreaseOps(int amount) +{ + Squirrel &engine = *ScriptObject::GetActiveInstance().engine; + Squirrel::DecreaseOps(engine.GetVM(), amount); +} + /* static */ int ScriptController::GetSetting(const std::string &name) { return ScriptObject::GetActiveInstance().GetSetting(name); diff --git a/src/script/api/script_controller.hpp b/src/script/api/script_controller.hpp index 38e3ab5476..249ec446bc 100644 --- a/src/script/api/script_controller.hpp +++ b/src/script/api/script_controller.hpp @@ -120,6 +120,12 @@ public: */ static int GetOpsTillSuspend(); + /** + * Remove \c amount ops from the number of ops till suspend. + * @api none + */ + static void DecreaseOps(int amount); + /** * Get the value of one of your settings you set via info.nut. * @param name The name of the setting. diff --git a/src/script/api/script_list.cpp b/src/script/api/script_list.cpp index c72703a215..7049a90c4c 100644 --- a/src/script/api/script_list.cpp +++ b/src/script/api/script_list.cpp @@ -8,7 +8,6 @@ /** @file script_list.cpp Implementation of ScriptList. */ #include "../../stdafx.h" -#include "script_controller.hpp" #include "script_list.hpp" #include "../../debug.h" #include "../../script/squirrel.hpp" @@ -631,24 +630,24 @@ void ScriptList::SwapList(ScriptList *list) list->sorter->Retarget(list); } -void ScriptList::RemoveAboveValue(SQInteger value) +bool ScriptList::RemoveAboveValue(SQInteger value) { - this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v > value; }); + return this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v > value; }); } -void ScriptList::RemoveBelowValue(SQInteger value) +bool ScriptList::RemoveBelowValue(SQInteger value) { - this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v < value; }); + return this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v < value; }); } -void ScriptList::RemoveBetweenValue(SQInteger start, SQInteger end) +bool ScriptList::RemoveBetweenValue(SQInteger start, SQInteger end) { - this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v > start && v < end; }); + return this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v > start && v < end; }); } -void ScriptList::RemoveValue(SQInteger value) +bool ScriptList::RemoveValue(SQInteger value) { - this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v == value; }); + return this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v == value; }); } void ScriptList::RemoveTop(SQInteger count) @@ -709,33 +708,33 @@ void ScriptList::RemoveBottom(SQInteger count) } } -void ScriptList::RemoveList(ScriptList *list) +bool ScriptList::RemoveList(ScriptList *list) { if (list == this) { this->Clear(); - return; + return false; } - this->RemoveItems([&](const SQInteger &k, const SQInteger &) { return list->HasItem(k); }); + return this->RemoveItems([&](const SQInteger &k, const SQInteger &) { return list->HasItem(k); }); } -void ScriptList::KeepAboveValue(SQInteger value) +bool ScriptList::KeepAboveValue(SQInteger value) { - this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v <= value; }); + return this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v <= value; }); } -void ScriptList::KeepBelowValue(SQInteger value) +bool ScriptList::KeepBelowValue(SQInteger value) { - this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v >= value; }); + return this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v >= value; }); } -void ScriptList::KeepBetweenValue(SQInteger start, SQInteger end) +bool ScriptList::KeepBetweenValue(SQInteger start, SQInteger end) { - this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v <= start && v >= end; }); + return this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v <= start && v >= end; }); } -void ScriptList::KeepValue(SQInteger value) +bool ScriptList::KeepValue(SQInteger value) { - this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v != value; }); + return this->RemoveItems([&](const SQInteger &, const SQInteger &v) { return v != value; }); } void ScriptList::KeepTop(SQInteger count) @@ -752,10 +751,10 @@ void ScriptList::KeepBottom(SQInteger count) this->RemoveTop(this->Count() - count); } -void ScriptList::KeepList(ScriptList *list) +bool ScriptList::KeepList(ScriptList *list) { - if (list == this) return; - this->RemoveItems([&](const SQInteger &k, const SQInteger &) { return !list->HasItem(k); }); + if (list == this) return false; + return this->RemoveItems([&](const SQInteger &k, const SQInteger &) { return !list->HasItem(k); }); } SQInteger ScriptList::_get(HSQUIRRELVM vm) const diff --git a/src/script/api/script_list.hpp b/src/script/api/script_list.hpp index c3cc0382eb..67259e4bda 100644 --- a/src/script/api/script_list.hpp +++ b/src/script/api/script_list.hpp @@ -12,6 +12,7 @@ #define SCRIPT_LIST_HPP #include "script_object.hpp" +#include "script_controller.hpp" /** Maximum number of operations allowed for valuating a list. */ static const int MAX_VALUATE_OPS = 1000000; @@ -155,14 +156,29 @@ protected: void CopyList(const ScriptList *list); template - void RemoveItems(ValueFilter value_filter) + bool RemoveItems(ValueFilter value_filter) { this->modifications++; - for (ScriptListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { + ScriptObject::DisableDoCommandScope disabler{}; + + auto begin = this->items.begin(); + if (disabler.GetOriginalValue() && this->resume_item.has_value()) { + begin = this->items.lower_bound(this->resume_item.value()); + } + + for (ScriptListMap::iterator next_iter, iter = begin; iter != this->items.end(); iter = next_iter) { + if (disabler.GetOriginalValue() && iter->first != this->resume_item && ScriptController::GetOpsTillSuspend() < 0) { + this->resume_item = iter->first; + return true; + } next_iter = std::next(iter); if (value_filter(iter->first, iter->second)) this->RemoveItem(iter->first); + ScriptController::DecreaseOps(5); } + + this->resume_item.reset(); + return false; } public: @@ -282,27 +298,47 @@ public: /** * Removes all items with a higher value than 'value'. * @param value the value above which all items are removed. + * @suspendable */ +#ifdef DOXYGEN_API void RemoveAboveValue(SQInteger value); +#else + bool RemoveAboveValue(SQInteger value); +#endif /* DOXYGEN_API */ /** * Removes all items with a lower value than 'value'. * @param value the value below which all items are removed. + * @suspendable */ +#ifdef DOXYGEN_API void RemoveBelowValue(SQInteger value); +#else + bool RemoveBelowValue(SQInteger value); +#endif /* DOXYGEN_API */ /** * Removes all items with a value above start and below end. * @param start the lower bound of the to be removed values (exclusive). * @param end the upper bound of the to be removed values (exclusive). + * @suspendable */ +#ifdef DOXYGEN_API void RemoveBetweenValue(SQInteger start, SQInteger end); +#else + bool RemoveBetweenValue(SQInteger start, SQInteger end); +#endif /* DOXYGEN_API */ /** * Remove all items with this value. * @param value the value to remove. + * @suspendable */ +#ifdef DOXYGEN_API void RemoveValue(SQInteger value); +#else + bool RemoveValue(SQInteger value); +#endif /* DOXYGEN_API */ /** * Remove the first count items. @@ -320,33 +356,58 @@ public: * Remove everything that is in the given list from this list (same item index that is). * @param list the list of items to remove. * @pre list != null + * @suspendable */ +#ifdef DOXYGEN_API void RemoveList(ScriptList *list); +#else + bool RemoveList(ScriptList *list); +#endif /* DOXYGEN_API */ /** * Keep all items with a higher value than 'value'. * @param value the value above which all items are kept. + * @suspendable */ +#ifdef DOXYGEN_API void KeepAboveValue(SQInteger value); +#else + bool KeepAboveValue(SQInteger value); +#endif /* DOXYGEN_API */ /** * Keep all items with a lower value than 'value'. * @param value the value below which all items are kept. + * @suspendable */ +#ifdef DOXYGEN_API void KeepBelowValue(SQInteger value); +#else + bool KeepBelowValue(SQInteger value); +#endif /* DOXYGEN_API */ /** * Keep all items with a value above start and below end. * @param start the lower bound of the to be kept values (exclusive). * @param end the upper bound of the to be kept values (exclusive). + * @suspendable */ +#ifdef DOXYGEN_API void KeepBetweenValue(SQInteger start, SQInteger end); +#else + bool KeepBetweenValue(SQInteger start, SQInteger end); +#endif /* DOXYGEN_API */ /** * Keep all items with this value. * @param value the value to keep. + * @suspendable */ +#ifdef DOXYGEN_API void KeepValue(SQInteger value); +#else + bool KeepValue(SQInteger value); +#endif /* DOXYGEN_API */ /** * Keep the first count items, i.e. remove everything except the first count items. @@ -364,8 +425,13 @@ public: * Keeps everything that is in the given list from this list (same item index that is). * @param list the list of items to keep. * @pre list != null + * @suspendable */ +#ifdef DOXYGEN_API void KeepList(ScriptList *list); +#else + bool KeepList(ScriptList *list); +#endif /* DOXYGEN_API */ #ifndef DOXYGEN_API /**