If a local variable in a definition was set to a proplist inside the
Definition() callback, and that proplist contained cyclic references
then those references were leaked. Typically cyclic references for
script-created proplists are broken in
C4PropListScript::ClearScriptPropLists, however definition proplists
are changed to be static proplists in
C4PropList::FreezeAndMakeStaticRecursively.
To fix this, each script host maintains a list of proplists made static
by FreezeAndMakeStaticRecursively, and explicitly deletes all of these
proplists on Clear().
This leak also leads to an assertion failure inside
C4PropListScript::ClearScriptPropLists in debug mode, and can also be
observed by C4PropList::PropLists not being empty after game clear.
The definition in Objects.ocd/Helpers.ocd/UserAction.ocd constructs
cyclic proplists in its Definition() call. A simpler, more minimal way
to provoke the leak is the following (it provokes the leak but not the
assertion failure):
local bla;
func Definition(def)
{
bla = {};
bla.test = { Name="Test222" , Options = { Name="Test333" } };
bla.test.Options.Link = { Name="Test444", Blub=bla.test };
}
Use RegexSearch() instead, which is 100 times faster for large strings
(see benchmark results below).
Example benchmark:
global func TestFindSubstring(int iterations)
{
var result;
for (var i = 0; i < iterations; i++)
{
result = FindSubstring(hamlet, "and");
}
return result;
}
global func TestRegexSearch(int iterations)
{
var result;
for (var i = 0; i < iterations; i++)
{
result = RegexSearch(hamlet, "and");
}
return result;
}
global func RunBenchmark(int iterations)
{
StartScriptProfiler();
Log("FindSubstring: %d iterations", iterations);
var substr = TestFindSubstring(iterations);
Log("RegexSearch: %d iterations", iterations);
var regex = TestRegexSearch(iterations);
StopScriptProfiler();
if (!DeepEqual(regex, substr))
Log("Results differ: %v vs %v", substr, regex);
}
Results:
FindSubstring: 100 iterations
RegexSearch: 100 iterations
Profiler statistics:
==============================
48903ms Global.FindSubstring
48903ms Global.TestFindSubstring
47979ms Global.TakeString
00504ms Global.TestRegexSearch
00016ms Global.PushBack
==============================
As carrier-grade NATs are becoming common, many players cannot host
Clonk games at all. The simple STUN-like netpuncher from Clonk Rage
which was removed three years ago is already effective against some
DS-Lite NATs.
With some extensions, we should be able to make it work with more
restrictive NATs as well.
This reverts commit 72002cc366.