Skip to content

Commit

Permalink
Initial saving fix for Godot 4 and swapped randoms to xoshiro (#4959)
Browse files Browse the repository at this point in the history
* Removed some outdated comments

* New random converter for xoshiro based random

* style_guide.md update to not use `System.Random`

* Switched all Random instantiations that matter to xoshiro

* Fixed platform detection for new Linux name

* Added some max lengths to save list item fields

to prevent bad save data from messing up the GUI

* Fixed HUD save load crash

* Ignoring a bunch of new Godot node properties and disabled group saving

as there's currently no code relying on dynamically changing node group allocations

* Fixed callback converter trying to convert things infinitely

and just now write the method name like is used on load to determine the target

* Fixed saving a bunch of unintended things for cell stat indicators

* Fixed loading LocalizedStringBuilder from saves

* Fixed random converter loading randoms
  • Loading branch information
hhyyrylainen committed Mar 22, 2024
1 parent 13b2bbc commit f94fad4
Show file tree
Hide file tree
Showing 47 changed files with 610 additions and 170 deletions.
2 changes: 2 additions & 0 deletions LICENSE.txt
Expand Up @@ -44,6 +44,8 @@ System.Numerics.Vectors: MIT License Copyright (c) .NET Foundation and Contribut

SharpZipLib: MIT License Copyright © 2000-2018 SharpZipLib Contributors

XoshiroPRNG.Net: Released into the public domain by Pandu POLUAN

Nito.Collections.Deque: MIT License Copyright (c) 2015 Stephen Cleary

FastNoiseLite: MIT License Copyright(c) 2020 Jordan Peck (jordan.me2@gmail.com),
Expand Down
1 change: 1 addition & 0 deletions Thrive.csproj
Expand Up @@ -40,6 +40,7 @@
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="Nito.Collections.Deque" Version="1.2.1" />
<PackageReference Include="Lib.Harmony" Version="2.3.1.1" />
<PackageReference Include="XoshiroPRNG.Net" Version="1.6.0" />
<PackageReference Include="YamlDotNet" Version="15.1.2" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0" PrivateAssets="all" />
Expand Down
3 changes: 2 additions & 1 deletion Thrive.sln.DotSettings
Expand Up @@ -807,4 +807,5 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=vseparation/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Weblate/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Wigglyness/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=writability/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=writability/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=xoshiro/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
7 changes: 7 additions & 0 deletions doc/style_guide.md
Expand Up @@ -261,6 +261,13 @@ Code style rules

- `uint` type should not be used without a very good reason.

- `System.Random` should be avoided as its state cannot be
saved. Instead use the random number types in the `Xoshiro`
namespace (check the documentation on the types for which generators
are suitable for what kinds of numeric types). General advice is to
use 128-bit generators for 32-bit types (`int`, `float`) and 256-bit
generators for 64-bit types (`long`, `double`).

- Unrelated uses should not share the same variable. Instead they
should locally define their own variable instance.

Expand Down
4 changes: 3 additions & 1 deletion src/auto-evo/AutoEvoRun.cs
Expand Up @@ -6,6 +6,7 @@
using System.Threading.Tasks;
using AutoEvo;
using Godot;
using Xoshiro.PRNG64;
using Thread = System.Threading.Thread;

/// <summary>
Expand Down Expand Up @@ -369,7 +370,8 @@ public LocalizedStringBuilder MakeSummaryOfExternalEffects()
/// </summary>
protected virtual void GatherInfo(Queue<IRunStep> steps)
{
var random = new Random();
// TODO: allow passing in a seed
var random = new XoShiRo256starstar();

var alreadyHandledSpecies = new HashSet<Species>();

Expand Down
3 changes: 2 additions & 1 deletion src/auto-evo/simulation/PopulationSimulation.cs
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using Godot;
using Xoshiro.PRNG64;

/// <summary>
/// Main class for the population simulation part.
Expand All @@ -27,7 +28,7 @@ public static class PopulationSimulation
// to IRunStep.RunStep might not be worth the effort at all
var cache = existingCache ?? new SimulationCache(parameters.WorldSettings);

var random = new Random(randomSource.Next());
var random = new XoShiRo256starstar(randomSource.NextInt64());

var speciesToSimulate = CopyInitialPopulationsToResults(parameters);

Expand Down
6 changes: 4 additions & 2 deletions src/auto-evo/steps/CalculatePopulation.cs
@@ -1,7 +1,7 @@
namespace AutoEvo;

using System;
using System.Collections.Generic;
using Xoshiro.PRNG64;

/// <summary>
/// Step that calculate the populations for all species
Expand Down Expand Up @@ -50,7 +50,9 @@ public bool RunStep(RunResults results)

// Directly feed the population results to the main results object

PopulationSimulation.Simulate(config, null, new Random());
// TODO: allow passing in a random seed

PopulationSimulation.Simulate(config, null, new XoShiRo256starstar());

return true;
}
Expand Down
3 changes: 2 additions & 1 deletion src/auto-evo/steps/FindBestMigration.cs
Expand Up @@ -2,6 +2,7 @@

using System;
using System.Linq;
using Xoshiro.PRNG64;

/// <summary>
/// Step that finds the best migration for a single species
Expand All @@ -23,7 +24,7 @@ public class FindBestMigration : VariantTryingStep
this.worldSettings = worldSettings;
this.map = map;
this.species = species;
this.random = new Random(random.Next());
this.random = new XoShiRo256starstar(random.NextInt64());
cache = new SimulationCache(worldSettings);
}

Expand Down
3 changes: 2 additions & 1 deletion src/auto-evo/steps/FindBestMutation.cs
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Xoshiro.PRNG64;

/// <summary>
/// Step that finds the best mutation for a single species
Expand Down Expand Up @@ -32,7 +33,7 @@ public class FindBestMutation : VariantTryingStep
this.worldSettings = worldSettings;
this.map = map;
this.species = species;
this.random = new Random(random.Next());
this.random = new XoShiRo256starstar(random.NextInt64());
this.splitThresholdFraction = splitThresholdFraction;
this.splitThresholdAmount = splitThresholdAmount;
cache = new SimulationCache(worldSettings);
Expand Down
3 changes: 2 additions & 1 deletion src/auto-evo/steps/IncreaseBiodiversity.cs
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Xoshiro.PRNG64;

/// <summary>
/// Attempts to increase the biodiversity of a patch by force-splitting an existing species there or creating a
Expand Down Expand Up @@ -32,7 +33,7 @@ public class IncreaseBiodiversity : IRunStep
this.map = map;
this.patch = patch;
this.configuration = configuration;
this.random = new Random(random.Next());
this.random = new XoShiRo256starstar(random.NextInt64());
cache = new SimulationCache(worldSettings);
}

Expand Down
5 changes: 3 additions & 2 deletions src/benchmark/microbe/MicrobeBenchmark.cs
Expand Up @@ -6,6 +6,7 @@
using Components;
using DefaultEcs;
using Godot;
using Xoshiro.PRNG64;

/// <summary>
/// Benchmarking tool for the microbe stage. Used for checking performance impact of changes or for players to see
Expand Down Expand Up @@ -125,7 +126,7 @@ public partial class MicrobeBenchmark : Node

private EntitySet? microbeEntities;

private Random random = new(RANDOM_SEED);
private XoShiRo256starstar random = new(RANDOM_SEED);

private int aiGroup1Seed;
private int aiGroup2Seed;
Expand Down Expand Up @@ -439,7 +440,7 @@ protected override void Dispose(bool disposing)
private void StartBenchmark()
{
internalPhaseCounter = 0;
random = new Random(RANDOM_SEED);
random = new XoShiRo256starstar(RANDOM_SEED);

microbeStationaryResult = 0;
microbeAIResult = 0;
Expand Down
7 changes: 0 additions & 7 deletions src/engine/DebugOverlays.PerformanceMetrics.cs
Expand Up @@ -114,13 +114,6 @@ private void UpdateMetrics(double delta)
Constants.MEBIBYTE, 1);
var mibFormat = Localization.Translate("MIB_VALUE");

// These don't seem to work:
// Performance.GetMonitor(Performance.Monitor.Physics3dActiveObjects),
// Performance.GetMonitor(Performance.Monitor.Physics3dCollisionPairs),
// Performance.GetMonitor(Performance.Monitor.Physics3dIslandCount),

// TODO: check if memory use can finally be gotten on Windows

metricsText.Text =
new LocalizedString("METRICS_CONTENT", Performance.GetMonitor(Performance.Monitor.TimeProcess),
Performance.GetMonitor(Performance.Monitor.TimePhysicsProcess),
Expand Down
39 changes: 26 additions & 13 deletions src/engine/FeatureInformation.cs
Expand Up @@ -7,27 +7,45 @@
/// </summary>
public static class FeatureInformation
{
public const string PlatformWindows = "Windows";
public const string PlatformLinux = "Linux";
public const string PlatformMac = "OSX";
private const string PlatformWindows = "windows";
private const string PlatformLinux = "linux";

// TODO: check that this is correct for Godot 4
private const string PlatformMac = "osx";

private static readonly Lazy<OS.RenderingDriver> CachedDriver = new(DetectRenderer);

private static readonly Lazy<string> ResolvedOS = new(GetOSHelper);

private static readonly string[] SimpleFeaturePlatforms =
{
"Android",
"HTML5",
PlatformLinux,
PlatformWindows,
PlatformMac,

// TODO: check that these are correct for Godot 4
"android",
"html5",
"iOS",
};

public static string GetOS()
{
// TODO: fix this for Godot 4
if (OS.HasFeature("X11"))
return PlatformLinux;
return ResolvedOS.Value;
}

public static OS.RenderingDriver GetVideoDriver()
{
return CachedDriver.Value;
}

public static bool IsLinux()
{
return GetOS() == PlatformLinux;
}

private static string GetOSHelper()
{
foreach (var feature in SimpleFeaturePlatforms)
{
if (OS.HasFeature(feature))
Expand All @@ -38,11 +56,6 @@ public static string GetOS()
return "unknown";
}

public static OS.RenderingDriver GetVideoDriver()
{
return CachedDriver.Value;
}

private static OS.RenderingDriver DetectRenderer()
{
// TODO: switch to a proper approach when Godot adds support for reading this
Expand Down
6 changes: 5 additions & 1 deletion src/engine/LocalizedStringBuilder.cs
Expand Up @@ -19,8 +19,12 @@
[JSONDynamicTypeAllowed]
public class LocalizedStringBuilder : IFormattable
{
/// <summary>
/// Things to format into this builder. This is no longer <see cref="IFormattable"/> as string would throw an
/// error on JSON load.
/// </summary>
[JsonProperty]
private readonly List<IFormattable> items = new();
private readonly List<object> items = new();

private readonly StringBuilder stringBuilder;
private string formatString = string.Empty;
Expand Down
2 changes: 1 addition & 1 deletion src/engine/StartupActions.cs
Expand Up @@ -128,7 +128,7 @@ private StartupActions()
GD.PrintErr("Please do not report to us the next unhandled exception error about this, unless " +
"this is an official Thrive release that has this issue");

if (FeatureInformation.GetOS() == FeatureInformation.PlatformLinux)
if (FeatureInformation.IsLinux())
{
GD.PrintErr("On Linux please verify you have new enough GLIBC version as otherwise the library " +
"is unloadable. Updating your distro to the latest version should resolve the issue as long " +
Expand Down
14 changes: 12 additions & 2 deletions src/general/GameWorld.cs
Expand Up @@ -4,6 +4,7 @@
using AutoEvo;
using Godot;
using Newtonsoft.Json;
using Xoshiro.PRNG64;

/// <summary>
/// All data regarding the game world of a thrive playthrough
Expand Down Expand Up @@ -252,9 +253,18 @@ public MicrobeSpecies CreatePlayerSpecies()
/// <summary>
/// Generates a few random species in all patches
/// </summary>
public void GenerateRandomSpeciesForFreeBuild()
public void GenerateRandomSpeciesForFreeBuild(long seed = 0)
{
var random = new Random();
Random random;

if (seed == 0)
{
random = new XoShiRo256starstar();
}
else
{
random = new XoShiRo256starstar(seed);
}

var workMemory1 = new List<Hex>();
var workMemory2 = new List<Hex>();
Expand Down
7 changes: 3 additions & 4 deletions src/general/HelpScreen.cs
@@ -1,5 +1,6 @@
using System;
using Godot;
using Xoshiro.PRNG32;

/// <summary>
/// Manages the help screen GUI
Expand Down Expand Up @@ -29,14 +30,14 @@ public partial class HelpScreen : Control
[Export]
public PackedScene HelpBoxScene = null!;

private readonly Random random = new XoShiRo128starstar();

private VBoxContainer leftColumn = null!;
private VBoxContainer rightColumn = null!;
private Label tipMessageLabel = null!;
private Timer timer = null!;
#pragma warning restore CA2213

private Random random = null!;

[Signal]
public delegate void HelpScreenClosedEventHandler();

Expand All @@ -47,8 +48,6 @@ public override void _Ready()
tipMessageLabel = GetNode<Label>(TipMessageLabelPath);
timer = GetNode<Timer>(TimerPath);

random = new Random();

if (!string.IsNullOrEmpty(Category))
{
BuildHelpTexts(Category);
Expand Down
3 changes: 2 additions & 1 deletion src/general/Jukebox.cs
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using Godot;
using Xoshiro.PRNG32;

/// <summary>
/// Manages playing music. Autoload singleton
Expand Down Expand Up @@ -563,7 +564,7 @@ private void PlayNextTrackFromList(TrackList list, Func<int, AudioPlayer> getPla
}
else
{
var random = new Random();
var random = new XoShiRo128starstar();
int nextIndex;

if (mode == TrackList.Order.Random)
Expand Down
3 changes: 2 additions & 1 deletion src/general/MainMenu.cs
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using Godot;
using Godot.Collections;
using Xoshiro.PRNG32;

/// <summary>
/// Class managing the main menu and everything in it
Expand Down Expand Up @@ -535,7 +536,7 @@ private void RunMenuSetup()
/// </summary>
private void RandomizeBackground()
{
var random = new Random();
var random = new XoShiRo128starstar();

// Some of the 3D backgrounds render very incorrectly in GLES2 so they are disabled
// TODO: check if the 3D backgrounds look now fine in opengl mode
Expand Down

0 comments on commit f94fad4

Please sign in to comment.