Decompiled source of World Gen Accelerator v1.0.0

worldGenAccelerator.dll

Decompiled 3 weeks ago
using 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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[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("0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = "")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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> val = config.Bind<bool>("Analytics", "Enabled", true, "Send a single anonymous ping when the game starts. No gameplay data is collected.");
				ConfigEntry<string> val2 = config.Bind<string>("Analytics", "InstanceID", Guid.NewGuid().ToString(), "Random anonymous ID. Change or delete to reset.");
				if (!val.Value)
				{
					worldGenAcceleratorPlugin.TemplateLogger.LogDebug((object)"Analytics disabled by config");
					return;
				}
				_hasSentPing = true;
				((MonoBehaviour)ThreadingHelper.Instance).StartCoroutine(SendPing(modId, modVersion, val2.Value));
			}
		}

		private static IEnumerator SendPing(string modId, string modVersion, string instanceId)
		{
			string json = "{\"mod_id\":\"" + Escape(modId) + "\",\"mod_version\":\"" + Escape(modVersion) + "\",\"instance_id\":\"" + Escape(instanceId) + "\"}";
			byte[] body = Encoding.UTF8.GetBytes(json);
			UnityWebRequest req = new UnityWebRequest("https://mod-analytics.vercel.app/api/ping", "POST");
			try
			{
				req.uploadHandler = (UploadHandler)new UploadHandlerRaw(body);
				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<Vector2i>> m_zonesByBiome = new Dictionary<Biome, List<Vector2i>>();

		private Dictionary<Vector2i, BiomeArea> m_zoneBiomeArea = new Dictionary<Vector2i, BiomeArea>();

		private int m_cachedZoneCount;

		private bool m_built;

		public static BiomeZoneCache Instance { get; private set; } = new BiomeZoneCache();


		public void Build()
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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;
			Vector2i val = default(Vector2i);
			for (int i = -num; i <= num; i++)
			{
				for (int j = -num; j <= num; j++)
				{
					((Vector2i)(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(zonePos);
						if (!m_zonesByBiome.TryGetValue(biome, out List<Vector2i> value))
						{
							value = new List<Vector2i>();
							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<Vector2i> GetCandidateZones(Biome biomeMask, BiomeArea biomeAreaMask)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Invalid comparison between Unknown and I4
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			List<Vector2i> list = new List<Vector2i>();
			foreach (KeyValuePair<Biome, List<Vector2i>> item in m_zonesByBiome)
			{
				if ((item.Key & biomeMask) == 0)
				{
					continue;
				}
				foreach (Vector2i 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
			{
				object value = radiusProperty.GetValue(null);
				if (value is float)
				{
					float num = (float)value;
					if (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;
			}
			Assembly assembly = ((object)value.Instance).GetType().Assembly;
			Type type = 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.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class worldGenAcceleratorPlugin : BaseUnityPlugin
	{
		private const string ModName = "worldGenAccelerator";

		private const string ModVersion = "1.0.0";

		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.0");
			_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)
		{
			ZoneSystem zoneSystem2 = zoneSystem;
			Stopwatch locationTimer = null;
			if (worldGenAcceleratorPlugin.TimingLogsEnabled)
			{
				locationTimer = Stopwatch.StartNew();
			}
			int seed = WorldGenerator.instance.GetSeed() + StringExtensionMethods.GetStableHashCode(location.m_prefab.Name);
			State state = Random.state;
			Random.InitState(seed);
			float maxRadius = Mathf.Max(location.m_exteriorRadius, location.m_interiorRadius);
			int iterations = 0;
			int placed = zoneSystem2.CountNrOfLocation(location);
			if (!location.m_unique || placed <= 0)
			{
				zoneSystem2.s_tempVeg.Clear();
				List<Vector2i> candidates = BiomeZoneCache.Instance.GetCandidateZones(location.m_biome, location.m_biomeArea);
				candidates.RemoveAll((Vector2i z) => zoneSystem2.m_locationInstances.ContainsKey(z) || zoneSystem2.m_generatedZones.Contains(z));
				int candidateCount = candidates.Count;
				if (location.m_centerFirst)
				{
					candidates.Sort(delegate(Vector2i a, Vector2i b)
					{
						//IL_0001: Unknown result type (might be due to invalid IL or missing references)
						//IL_0002: Unknown result type (might be due to invalid IL or missing references)
						//IL_0007: 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_0011: Unknown result type (might be due to invalid IL or missing references)
						//IL_0016: Unknown result type (might be due to invalid IL or missing references)
						Vector3 zonePos = ZoneSystem.GetZonePos(a);
						float magnitude2 = ((Vector3)(ref zonePos)).magnitude;
						zonePos = ZoneSystem.GetZonePos(b);
						float magnitude3 = ((Vector3)(ref zonePos)).magnitude;
						return magnitude2.CompareTo(magnitude3);
					});
				}
				else
				{
					for (int i = candidates.Count - 1; i > 0; i--)
					{
						int k = Random.Range(0, i + 1);
						Vector2i tmp = candidates[i];
						candidates[i] = candidates[k];
						candidates[k] = tmp;
					}
				}
				Color mask1 = default(Color);
				float delta = default(float);
				Vector3 slopeDir = default(Vector3);
				Color mask2 = default(Color);
				for (int j = 0; j < candidates.Count; j++)
				{
					if (placed >= location.m_quantity)
					{
						break;
					}
					Vector2i zoneID = candidates[j];
					if (timeSliceStopwatch.Elapsed.TotalSeconds >= (double)zoneSystem2.m_timeSlicedGenerationTimeBudget)
					{
						State insideState = Random.state;
						Random.state = state;
						yield return null;
						timeSliceStopwatch.Restart();
						state = Random.state;
						Random.state = insideState;
					}
					if (zoneSystem2.m_locationInstances.ContainsKey(zoneID))
					{
						continue;
					}
					for (int l = 0; l < 20; l++)
					{
						if (timeSliceStopwatch.Elapsed.TotalSeconds >= (double)zoneSystem2.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 mask1);
						float altitude = randomPointInZone.y - 30f;
						if ((double)altitude < (double)location.m_minAltitude || (double)altitude > (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 lengthXZ = Utils.LengthXZ(randomPointInZone);
							if (((double)location.m_minDistanceFromCenter > 0.0 && (double)lengthXZ < (double)location.m_minDistanceFromCenter) || ((double)location.m_maxDistanceFromCenter > 0.0 && (double)lengthXZ > (double)location.m_maxDistanceFromCenter))
							{
								continue;
							}
						}
						WorldGenerator.instance.GetTerrainDelta(randomPointInZone, location.m_exteriorRadius, ref delta, ref slopeDir);
						if ((double)delta > (double)location.m_maxTerrainDelta || (double)delta < (double)location.m_minTerrainDelta || ((double)location.m_minDistanceFromSimilar > 0.0 && zoneSystem2.HaveLocationInRange(location.m_prefab.Name, location.m_group, randomPointInZone, location.m_minDistanceFromSimilar, false)) || ((double)location.m_maxDistanceFromSimilar > 0.0 && !zoneSystem2.HaveLocationInRange(location.m_prefabName, location.m_groupMax, randomPointInZone, location.m_maxDistanceFromSimilar, true)))
						{
							continue;
						}
						float vegMask = mask1.a;
						if (((double)location.m_minimumVegetation > 0.0 && (double)vegMask <= (double)location.m_minimumVegetation) || ((double)location.m_maximumVegetation < 1.0 && (double)vegMask >= (double)location.m_maximumVegetation))
						{
							continue;
						}
						if (location.m_surroundCheckVegetation)
						{
							float num3 = 0f;
							for (int index1 = 0; index1 < location.m_surroundCheckLayers; index1++)
							{
								float num4 = (float)(index1 + 1) / (float)location.m_surroundCheckLayers * location.m_surroundCheckDistance;
								for (int index2 = 0; index2 < 6; index2++)
								{
									float f = (float)((double)index2 / 6.0 * 3.1415927410125732 * 2.0);
									Vector3 samplePos = randomPointInZone + new Vector3(Mathf.Sin(f) * num4, 0f, Mathf.Cos(f) * num4);
									WorldGenerator.instance.GetHeight(samplePos.x, samplePos.z, ref mask2);
									float num5 = (float)(((double)location.m_surroundCheckDistance - (double)num4) / ((double)location.m_surroundCheckDistance * 2.0));
									num3 += mask2.a * num5;
									mask2 = default(Color);
								}
							}
							zoneSystem2.s_tempVeg.Add(num3);
							if (zoneSystem2.s_tempVeg.Count < 10)
							{
								continue;
							}
							float maxVeg = zoneSystem2.s_tempVeg.Max();
							float avgVeg = zoneSystem2.s_tempVeg.Average();
							float threshold = avgVeg + (maxVeg - avgVeg) * location.m_surroundBetterThanAverage;
							if ((double)num3 < (double)threshold)
							{
								continue;
							}
						}
						zoneSystem2.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);
		}
	}
}