Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of World Gen Accelerator v1.0.1
worldGenAccelerator.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("worldGenAccelerator")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("worldGenAccelerator")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("FBB901EA-0092-4689-8EE8-776E5CBFBC26")] [assembly: AssemblyFileVersion("1.0.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace worldGenAccelerator { public static class Analytics { private const string PingUrl = "https://mod-analytics.vercel.app/api/ping"; private static bool _hasSentPing; public static void Init(ConfigFile config, string modId, string modVersion) { if (!_hasSentPing) { ConfigEntry<bool> obj = config.Bind<bool>("Analytics", "Enabled", true, "Send a single anonymous ping when the game starts. No gameplay data is collected."); ConfigEntry<string> val = config.Bind<string>("Analytics", "InstanceID", Guid.NewGuid().ToString(), "Random anonymous ID. Change or delete to reset."); if (!obj.Value) { worldGenAcceleratorPlugin.TemplateLogger.LogDebug((object)"Analytics disabled by config"); return; } _hasSentPing = true; ((MonoBehaviour)ThreadingHelper.Instance).StartCoroutine(SendPing(modId, modVersion, val.Value)); } } private static IEnumerator SendPing(string modId, string modVersion, string instanceId) { string s = "{\"mod_id\":\"" + Escape(modId) + "\",\"mod_version\":\"" + Escape(modVersion) + "\",\"instance_id\":\"" + Escape(instanceId) + "\"}"; byte[] bytes = Encoding.UTF8.GetBytes(s); UnityWebRequest req = new UnityWebRequest("https://mod-analytics.vercel.app/api/ping", "POST"); try { req.uploadHandler = (UploadHandler)new UploadHandlerRaw(bytes); req.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); req.SetRequestHeader("Content-Type", "application/json"); req.timeout = 10; yield return req.SendWebRequest(); if ((int)req.result == 1) { worldGenAcceleratorPlugin.TemplateLogger.LogDebug((object)"Analytics ping sent"); } else { worldGenAcceleratorPlugin.TemplateLogger.LogDebug((object)("Analytics ping failed: " + req.error)); } } finally { ((IDisposable)req)?.Dispose(); } } private static string Escape(string s) { return s.Replace("\\", "\\\\").Replace("\"", "\\\""); } } public class BiomeZoneCache { private Dictionary<Biome, List<Vector2s>> m_zonesByBiome = new Dictionary<Biome, List<Vector2s>>(); private Dictionary<Vector2s, BiomeArea> m_zoneBiomeArea = new Dictionary<Vector2s, BiomeArea>(); private int m_cachedZoneCount; private bool m_built; public static BiomeZoneCache Instance { get; private set; } = new BiomeZoneCache(); public void Build() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (m_built) { return; } Stopwatch stopwatch = Stopwatch.StartNew(); m_zonesByBiome.Clear(); m_zoneBiomeArea.Clear(); m_cachedZoneCount = 0; WorldGenerator instance = WorldGenerator.instance; float zoneSize = ZoneSystem.instance.m_zoneSize; float worldRadius = ExpandWorldSizeBridge.GetWorldRadius(); int num = Mathf.CeilToInt(worldRadius / zoneSize); double num2 = (double)worldRadius * (double)worldRadius; Vector2s val = default(Vector2s); for (int i = -num; i <= num; i++) { for (int j = -num; j <= num; j++) { ((Vector2s)(ref val))..ctor(i, j); Vector3 zonePos = ZoneSystem.GetZonePos(val); if (!((double)((Vector3)(ref zonePos)).sqrMagnitude >= num2)) { Biome biome = instance.GetBiome(zonePos); BiomeArea biomeArea = instance.GetBiomeArea(ZoneSystem.GetZoneCenter(val)); if (!m_zonesByBiome.TryGetValue(biome, out List<Vector2s> value)) { value = new List<Vector2s>(); m_zonesByBiome[biome] = value; } value.Add(val); m_zoneBiomeArea[val] = biomeArea; m_cachedZoneCount++; } } } stopwatch.Stop(); m_built = true; worldGenAcceleratorPlugin.TemplateLogger.LogInfo((object)($"BiomeZoneCache built in {stopwatch.ElapsedMilliseconds}ms " + $"({m_cachedZoneCount} zones cached, worldRadius={worldRadius}m, gridRadius={num})")); } public List<Vector2s> GetCandidateZones(Biome biomeMask, BiomeArea biomeAreaMask) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) List<Vector2s> list = new List<Vector2s>(); foreach (KeyValuePair<Biome, List<Vector2s>> item in m_zonesByBiome) { if ((item.Key & biomeMask) == 0) { continue; } foreach (Vector2s item2 in item.Value) { if ((m_zoneBiomeArea[item2] & biomeAreaMask) != 0) { list.Add(item2); } } } return list; } public void Reset() { m_zonesByBiome.Clear(); m_zoneBiomeArea.Clear(); m_cachedZoneCount = 0; m_built = false; } } public static class ExpandWorldSizeBridge { private const string PluginGuid = "expand_world_size"; private const string ConfigTypeName = "ExpandWorldSize.Configuration"; private const string RadiusPropertyName = "WorldRadius"; public const float VanillaWorldRadius = 10000f; private static bool s_resolved; private static PropertyInfo? s_radiusProperty; public static float GetWorldRadius() { PropertyInfo radiusProperty = GetRadiusProperty(); if (radiusProperty == null) { return 10000f; } try { if (radiusProperty.GetValue(null) is float num && num > 0f) { return num; } } catch (Exception ex) { worldGenAcceleratorPlugin.TemplateLogger.LogWarning((object)("Failed to read ExpandWorldSize.Configuration.WorldRadius from ExpandWorldSize: " + ex.Message + ". Falling back to vanilla radius.")); } return 10000f; } private static PropertyInfo? GetRadiusProperty() { if (s_resolved) { return s_radiusProperty; } s_resolved = true; if (!Chainloader.PluginInfos.TryGetValue("expand_world_size", out var value)) { return null; } Type type = ((object)value.Instance).GetType().Assembly.GetType("ExpandWorldSize.Configuration"); if (type == null) { worldGenAcceleratorPlugin.TemplateLogger.LogWarning((object)"ExpandWorldSize is loaded but type ExpandWorldSize.Configuration was not found. Falling back to vanilla radius."); return null; } PropertyInfo property = type.GetProperty("WorldRadius", BindingFlags.Static | BindingFlags.Public); if (property == null) { worldGenAcceleratorPlugin.TemplateLogger.LogWarning((object)"ExpandWorldSize is loaded but ExpandWorldSize.Configuration.WorldRadius was not found. Falling back to vanilla radius."); return null; } s_radiusProperty = property; return property; } } [BepInPlugin("warpalicious.worldGenAccelerator", "worldGenAccelerator", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class worldGenAcceleratorPlugin : BaseUnityPlugin { private const string ModName = "worldGenAccelerator"; private const string ModVersion = "1.0.1"; private const string Author = "warpalicious"; private const string ModGUID = "warpalicious.worldGenAccelerator"; private static string ConfigFileName = "warpalicious.worldGenAccelerator.cfg"; private static string ConfigFileFullPath; private readonly Harmony HarmonyInstance = new Harmony("warpalicious.worldGenAccelerator"); public static readonly ManualLogSource TemplateLogger; private static ConfigEntry<bool> _enableOptimization; private static ConfigEntry<bool> _enableTimingLogs; private DateTime _lastReloadTime; private const long RELOAD_DELAY = 10000000L; public static bool OptimizationEnabled => _enableOptimization.Value; public static bool TimingLogsEnabled => _enableTimingLogs.Value; public void Awake() { Analytics.Init(((BaseUnityPlugin)this).Config, "warpalicious.worldGenAccelerator", "1.0.1"); _enableOptimization = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableOptimization", true, "Enable the biome zone cache optimization for faster world generation. Disabling this uses vanilla generation logic. Note: Optimized worlds will have different layouts than vanilla for the same seed."); _enableTimingLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableTimingLogs", true, "Log detailed timing information for each location placement and total generation time."); Assembly executingAssembly = Assembly.GetExecutingAssembly(); HarmonyInstance.PatchAll(executingAssembly); SetupWatcher(); } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetupWatcher() { _lastReloadTime = DateTime.Now; FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { DateTime now = DateTime.Now; long num = now.Ticks - _lastReloadTime.Ticks; if (File.Exists(ConfigFileFullPath) && num >= 10000000) { try { TemplateLogger.LogInfo((object)"Attempting to reload configuration..."); ((BaseUnityPlugin)this).Config.Reload(); TemplateLogger.LogInfo((object)"Configuration reloaded successfully!"); } catch { TemplateLogger.LogError((object)("There was an issue loading " + ConfigFileName)); return; } _lastReloadTime = now; if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsDedicated()) { TemplateLogger.LogInfo((object)"Updating runtime configurations..."); } } } static worldGenAcceleratorPlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; TemplateLogger = Logger.CreateLogSource("worldGenAccelerator"); _enableOptimization = null; _enableTimingLogs = null; } } [HarmonyPatch] public static class ZoneSystemPatch { private static Stopwatch s_totalGenerationTimer = new Stopwatch(); [HarmonyPatch(typeof(ZoneSystem), "GenerateLocations")] [HarmonyPrefix] private static void GenerateLocations_Prefix() { if (worldGenAcceleratorPlugin.TimingLogsEnabled) { s_totalGenerationTimer.Restart(); } if (worldGenAcceleratorPlugin.OptimizationEnabled) { BiomeZoneCache.Instance.Reset(); BiomeZoneCache.Instance.Build(); } } [HarmonyPatch(typeof(ZoneSystem), "set_LocationsGenerated")] [HarmonyPostfix] private static void LocationsGenerated_Postfix(bool value) { if (value && worldGenAcceleratorPlugin.TimingLogsEnabled && s_totalGenerationTimer.IsRunning) { s_totalGenerationTimer.Stop(); worldGenAcceleratorPlugin.TemplateLogger.LogInfo((object)$"Total location generation completed in {s_totalGenerationTimer.ElapsedMilliseconds}ms"); } } [HarmonyPatch(typeof(ZoneSystem), "GenerateLocationsTimeSliced", new Type[] { typeof(ZoneLocation), typeof(Stopwatch), typeof(ZPackage) })] [HarmonyPrefix] private static bool GenerateLocationsTimeSliced_Prefix(ZoneSystem __instance, ZoneLocation location, Stopwatch timeSliceStopwatch, ZPackage iterationsPkg, ref IEnumerator __result) { if (!worldGenAcceleratorPlugin.OptimizationEnabled) { return true; } __result = OptimizedGenerateLocationsTimeSliced(__instance, location, timeSliceStopwatch, iterationsPkg); return false; } private static IEnumerator OptimizedGenerateLocationsTimeSliced(ZoneSystem zoneSystem, ZoneLocation location, Stopwatch timeSliceStopwatch, ZPackage iterationsPkg) { Stopwatch locationTimer = null; if (worldGenAcceleratorPlugin.TimingLogsEnabled) { locationTimer = Stopwatch.StartNew(); } int num = WorldGenerator.instance.GetSeed() + StringExtensionMethods.GetStableHashCode(location.m_prefab.Name); State state = Random.state; Random.InitState(num); float maxRadius = Mathf.Max(location.m_exteriorRadius, location.m_interiorRadius); int iterations = 0; int placed = zoneSystem.CountNrOfLocation(location); if (!location.m_unique || placed <= 0) { zoneSystem.s_tempVeg.Clear(); List<Vector2s> candidates = BiomeZoneCache.Instance.GetCandidateZones(location.m_biome, location.m_biomeArea); candidates.RemoveAll((Vector2s z) => zoneSystem.m_locationInstances.ContainsKey(z) || zoneSystem.m_generatedZones.Contains(z)); int candidateCount = candidates.Count; if (location.m_centerFirst) { candidates.Sort(delegate(Vector2s val5, Vector2s b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) Vector3 zonePos = ZoneSystem.GetZonePos(val5); float magnitude2 = ((Vector3)(ref zonePos)).magnitude; zonePos = ZoneSystem.GetZonePos(b); float magnitude3 = ((Vector3)(ref zonePos)).magnitude; return magnitude2.CompareTo(magnitude3); }); } else { for (int num2 = candidates.Count - 1; num2 > 0; num2--) { int index = Random.Range(0, num2 + 1); Vector2s value = candidates[num2]; candidates[num2] = candidates[index]; candidates[index] = value; } } Color val = default(Color); float num5 = default(float); Vector3 val2 = default(Vector3); Color val4 = default(Color); for (int i = 0; i < candidates.Count; i++) { if (placed >= location.m_quantity) { break; } Vector2s zoneID = candidates[i]; if (timeSliceStopwatch.Elapsed.TotalSeconds >= (double)zoneSystem.m_timeSlicedGenerationTimeBudget) { State insideState = Random.state; Random.state = state; yield return null; timeSliceStopwatch.Restart(); state = Random.state; Random.state = insideState; } if (zoneSystem.m_locationInstances.ContainsKey(zoneID)) { continue; } for (int j = 0; j < 20; j++) { if (timeSliceStopwatch.Elapsed.TotalSeconds >= (double)zoneSystem.m_timeSlicedGenerationTimeBudget) { State insideState = Random.state; Random.state = state; yield return null; timeSliceStopwatch.Restart(); state = Random.state; Random.state = insideState; } iterations++; Vector3 randomPointInZone = ZoneSystem.GetRandomPointInZone(zoneID, maxRadius); float magnitude = ((Vector3)(ref randomPointInZone)).magnitude; if (((double)location.m_minDistance != 0.0 && (double)magnitude < (double)location.m_minDistance) || ((double)location.m_maxDistance != 0.0 && (double)magnitude > (double)location.m_maxDistance) || (location.m_biome & WorldGenerator.instance.GetBiome(randomPointInZone)) == 0) { continue; } randomPointInZone.y = WorldGenerator.instance.GetHeight(randomPointInZone.x, randomPointInZone.z, ref val); float num3 = randomPointInZone.y - 30f; if ((double)num3 < (double)location.m_minAltitude || (double)num3 > (double)location.m_maxAltitude) { continue; } if (location.m_inForest) { float forestFactor = WorldGenerator.GetForestFactor(randomPointInZone); if ((double)forestFactor < (double)location.m_forestTresholdMin || (double)forestFactor > (double)location.m_forestTresholdMax) { continue; } } if ((double)location.m_minDistanceFromCenter > 0.0 || (double)location.m_maxDistanceFromCenter > 0.0) { float num4 = Utils.LengthXZ(randomPointInZone); if (((double)location.m_minDistanceFromCenter > 0.0 && (double)num4 < (double)location.m_minDistanceFromCenter) || ((double)location.m_maxDistanceFromCenter > 0.0 && (double)num4 > (double)location.m_maxDistanceFromCenter)) { continue; } } WorldGenerator.instance.GetTerrainDelta(randomPointInZone, location.m_exteriorRadius, ref num5, ref val2); if ((double)num5 > (double)location.m_maxTerrainDelta || (double)num5 < (double)location.m_minTerrainDelta || ((double)location.m_minDistanceFromSimilar > 0.0 && zoneSystem.HaveLocationInRange(location.m_prefab.m_assetID, location.m_group, randomPointInZone, location.m_minDistanceFromSimilar, false)) || ((double)location.m_maxDistanceFromSimilar > 0.0 && !zoneSystem.HaveLocationInRange(location.m_prefab.m_assetID, location.m_groupMax, randomPointInZone, location.m_maxDistanceFromSimilar, true))) { continue; } float a = val.a; if (((double)location.m_minimumVegetation > 0.0 && (double)a <= (double)location.m_minimumVegetation) || ((double)location.m_maximumVegetation < 1.0 && (double)a >= (double)location.m_maximumVegetation)) { continue; } BiomeSector biomeSector = WorldGenerator.instance.GetBiomeSector(randomPointInZone, false); if ((location.AltBiomeParent != null && !biomeSector.AltBiomes.Any((AltBiome biome) => biome.m_name == location.AltBiomeParent)) || biomeSector.AltBiomes.Any((AltBiome biome) => biome.m_blockLocationNames.Contains(location.m_name))) { continue; } if (location.m_surroundCheckVegetation) { float num6 = 0f; for (int num7 = 0; num7 < location.m_surroundCheckLayers; num7++) { float num8 = (float)(num7 + 1) / (float)location.m_surroundCheckLayers * location.m_surroundCheckDistance; for (int num9 = 0; num9 < 6; num9++) { float num10 = (float)((double)num9 / 6.0 * 3.1415927410125732 * 2.0); Vector3 val3 = randomPointInZone + new Vector3(Mathf.Sin(num10) * num8, 0f, Mathf.Cos(num10) * num8); WorldGenerator.instance.GetHeight(val3.x, val3.z, ref val4); float num11 = (float)(((double)location.m_surroundCheckDistance - (double)num8) / ((double)location.m_surroundCheckDistance * 2.0)); num6 += val4.a * num11; } } zoneSystem.s_tempVeg.Add(num6); if (zoneSystem.s_tempVeg.Count < 10) { continue; } float num12 = zoneSystem.s_tempVeg.Max(); float num13 = zoneSystem.s_tempVeg.Average(); float num14 = num13 + (num12 - num13) * location.m_surroundBetterThanAverage; if ((double)num6 < (double)num14) { continue; } } zoneSystem.RegisterLocation(location, randomPointInZone, false); placed++; break; } } if (placed < location.m_quantity) { worldGenAcceleratorPlugin.TemplateLogger.LogWarning((object)$" {location.m_prefab.Name}: placed {placed}/{location.m_quantity} (incomplete)"); } if (worldGenAcceleratorPlugin.TimingLogsEnabled && locationTimer != null) { worldGenAcceleratorPlugin.TemplateLogger.LogInfo((object)($" {location.m_prefab.Name}: placed {placed}/{location.m_quantity} " + $"({candidateCount} candidate zones, {iterations} point iterations) " + $"in {locationTimer.ElapsedMilliseconds}ms")); } } Random.state = state; iterationsPkg.Write(iterations); iterationsPkg.SetPos(0); } } }