Decompiled source of SprayFactory v0.1.1

BepInEx/plugins/SprayFactory/SprayFactory.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using CommonAPI;
using CommonAPI.Systems.ModLocalization;
using HarmonyLib;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;
using crecheng.DSPModSave;
using xiaoye97;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Spray Factory")]
[assembly: AssemblyProduct("Spray Factory")]
[assembly: AssemblyCompany("Comonad")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.1.1.0")]
namespace SprayFactory;

internal static class FactoryBuildMenu
{
	internal static void Place(ItemProto item, ItemProto coater)
	{
		HashSet<int> hashSet = new HashSet<int>(from i in ((ProtoSet<ItemProto>)(object)LDB.items).dataArray
			where ((Proto)i).ID != ((Proto)item).ID
			select i.BuildIndex);
		ItemProto[,] array = (ItemProto[,])AccessTools.Field(typeof(UIBuildMenu), "protos").GetValue(null);
		int num = coater.BuildIndex / 100;
		int[] array2 = (from c in new int[2] { num, 4 }.Concat(Enumerable.Range(1, 9)).Distinct()
			where c >= 1 && c <= 9
			select c).ToArray();
		int[] array5;
		if (Chainloader.PluginInfos.TryGetValue("Gnimaerd.DSP.plugin.BuildBarTool", out var value))
		{
			Type type = ((object)value.Instance).GetType();
			ItemProto[,] array3 = (ItemProto[,])AccessTools.Field(type, "protos").GetValue(null);
			int[,] array4 = (int[,])AccessTools.Field(type, "protoIds").GetValue(null);
			int num2 = coater.BuildIndex % 100;
			if (num2 > 20)
			{
				num2 -= 20;
			}
			IEnumerable<int> enumerable = from n in new int[1] { num2 }.Concat(Enumerable.Range(1, 10)).Distinct()
				where n >= 1 && n <= 10
				select n;
			array5 = array2;
			for (int num3 = 0; num3 < array5.Length; num3++)
			{
				int num4 = array5[num3];
				foreach (int item2 in enumerable)
				{
					int num5 = num4 * 100 + 20 + item2;
					if (!hashSet.Contains(num5) && array3[num4, item2] == null && array4[num4, item2] == 0 && (bool)AccessTools.Method(AccessTools.TypeByName("BuildBarTool.BuildBarTool"), "SetBuildBar", new Type[4]
					{
						typeof(int),
						typeof(int),
						typeof(int),
						typeof(bool)
					}, (Type[])null).Invoke(null, new object[4]
					{
						num4,
						item2,
						((Proto)item).ID,
						true
					}))
					{
						item.BuildIndex = num5;
						AccessTools.Method(type, "LoadFromBuildIndex", (Type[])null, (Type[])null).Invoke(null, null);
						Plugin.Log.LogInfo((object)("Factory build menu: category=" + num4 + " row=upper slot=" + item2));
						return;
					}
				}
			}
		}
		UIButton[] array6 = UIRoot.instance?.uiGame?.buildMenu?.childButtons;
		int num6 = ((array6 == null) ? 10 : Math.Min(10, array6.Length - 1));
		array5 = array2;
		for (int num3 = 0; num3 < array5.Length; num3++)
		{
			int num7 = array5[num3];
			for (int num8 = 1; num8 <= num6; num8++)
			{
				int num9 = num7 * 100 + num8;
				if (!hashSet.Contains(num9) && (array[num7, num8] == null || ((Proto)array[num7, num8]).ID == ((Proto)item).ID) && (array6 == null || !((Object)(object)array6[num8] == (Object)null)))
				{
					item.BuildIndex = num9;
					LDBTool.SetBuildBar(num7, num8, ((Proto)item).ID);
					Plugin.Log.LogInfo((object)("Factory build menu: category=" + num7 + " row=lower slot=" + num8));
					return;
				}
			}
		}
		throw new InvalidOperationException("No free factory build menu slot.");
	}
}
internal static class FactoryEffects
{
	private sealed class Batch
	{
		internal readonly List<uint> Ids = new List<uint>();

		internal Material Material;

		internal ComputeBuffer IdBuffer;

		internal ComputeBuffer Args;

		internal int Capacity;

		internal void Free()
		{
			ComputeBuffer idBuffer = IdBuffer;
			if (idBuffer != null)
			{
				idBuffer.Release();
			}
			ComputeBuffer args = Args;
			if (args != null)
			{
				args.Release();
			}
			if ((Object)(object)Material != (Object)null)
			{
				Object.Destroy((Object)(object)Material);
			}
		}
	}

	private sealed class Group
	{
		internal Batch Liquid;

		internal Batch Spray;
	}

	private static readonly Dictionary<int, Group> groups = new Dictionary<int, Group>();

	private static readonly Plane[] planes = (Plane[])(object)new Plane[6];

	private static readonly uint[] args = new uint[5];

	private static readonly FieldInfo stateBuffer = AccessTools.Field(typeof(LabRenderer), "stateBuffer");

	private static int liquidSlot = -1;

	private static int spraySlot = -1;

	internal static void Draw(PlanetFactory factory, Camera camera)
	{
		FactoryModel val = ((factory == null) ? null : factory.planet?.factoryModel);
		if (!((Object)(object)val == (Object)null) && !((Object)(object)camera == (Object)null) && val.gpuiManager != null && !val.disableFactoryEntities && val.gpuiManager.renderEntity)
		{
			Draw(factory, camera, val.gpuiManager.GetObjectRenderer(Prototypes.ModelId), val.entityAnimBuffer);
		}
	}

	private static Batch CreateBatch(Material original, Color color, bool spray)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Expected O, but got Unknown
		Material val = new Material(original);
		color.a = 1f;
		string[] array = new string[3] { "_Color1", "_Color2", "_Color4" };
		foreach (string text in array)
		{
			if (val.HasProperty(text))
			{
				val.SetColor(text, color);
			}
		}
		if (spray)
		{
			val.SetColor("_TintColor", new Color(1f, 1f, 1f, 0.5f));
			val.SetFloat("_SprayBrightness", 0.5f);
			val.SetFloat("_SprayBrightnessBg", 0.05f);
		}
		else
		{
			val.SetFloat("_EmissionSwitch", 1f);
			val.SetFloat("_EmissionMultiplier", 0.25f);
		}
		return new Batch
		{
			Material = val,
			Args = new ComputeBuffer(5, 4, (ComputeBufferType)256)
		};
	}

	private static Group GetGroup(int item, PrefabDesc source)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: 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)
		if (groups.TryGetValue(item, out var value))
		{
			return value;
		}
		Color color = RecipeColors.ForItem(item);
		value = new Group
		{
			Liquid = CreateBatch(source.lodMaterials[0][liquidSlot], color, spray: false),
			Spray = CreateBatch(source.lodMaterials[0][spraySlot], color, spray: true)
		};
		groups.Add(item, value);
		return value;
	}

	internal static int Draw(PlanetFactory factory, Camera camera, ObjectRenderer renderer, ComputeBuffer animations)
	{
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		if (factory?.cargoTraffic == null || (Object)(object)camera == (Object)null || renderer == null || animations == null)
		{
			return 0;
		}
		PrefabDesc prefabDesc = ((ProtoSet<ItemProto>)(object)LDB.items).Select(2313).prefabDesc;
		if (liquidSlot < 0 || spraySlot < 0)
		{
			for (int i = 0; i < prefabDesc.lodMaterials[0].Length; i++)
			{
				Material obj = prefabDesc.lodMaterials[0][i];
				string text = ((obj != null) ? ((Object)obj).name : null);
				if (text != null)
				{
					if (text.IndexOf("water", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						liquidSlot = i;
					}
					if (text.IndexOf("effect", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						spraySlot = i;
					}
				}
			}
		}
		if (liquidSlot < 0 || spraySlot < 0)
		{
			return 0;
		}
		foreach (Group value in groups.Values)
		{
			value.Liquid.Ids.Clear();
			value.Spray.Ids.Clear();
		}
		GeometryUtility.CalculateFrustumPlanes(camera, planes);
		CargoTraffic cargoTraffic = factory.cargoTraffic;
		int num = 0;
		for (int j = 1; j < cargoTraffic.spraycoaterCursor; j++)
		{
			SpraycoaterComponent val = cargoTraffic.spraycoaterPool[j];
			if (val.id != j || !FactoryRuntime.IsFactory(factory, val.entityId) || !FactoryStore.TryGet(factory.planetId, val.entityId, out var state))
			{
				continue;
			}
			EntityData val2 = factory.entityPool[val.entityId];
			if (val2.modelId <= 0 || val2.modelId >= renderer.instCursor || renderer.instPool[val2.modelId].objId != val2.id)
			{
				continue;
			}
			Vector3 val3 = val2.pos - ((Component)camera).transform.position;
			if (!(((Vector3)(ref val3)).sqrMagnitude > 10000f) && GeometryUtility.TestPlanesAABB(planes, new Bounds(val2.pos, Vector3.one * 6f)))
			{
				int recipeId;
				int num2;
				lock (state.Sync)
				{
					recipeId = state.RecipeId;
					num2 = ((state.SprayTicks > 0) ? state.SprayItemId : 0);
				}
				RecipeProto val4 = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(recipeId);
				if (val4 != null && val4.Results.Length != 0)
				{
					GetGroup(val4.Results[0], prefabDesc).Liquid.Ids.Add((uint)val2.modelId);
					num++;
				}
				if (num2 > 0)
				{
					GetGroup(num2, prefabDesc).Spray.Ids.Add((uint)val2.modelId);
				}
			}
		}
		BatchRenderer batch = renderer.lodBatches[0];
		ComputeBuffer states = (ComputeBuffer)((renderer is LabRenderer) ? /*isinst with value type is only supported in some contexts*/: null);
		foreach (Group value2 in groups.Values)
		{
			Render(value2.Liquid, liquidSlot, batch, animations, states, camera);
			Render(value2.Spray, spraySlot, batch, animations, states, camera);
		}
		return num;
	}

	private static void Render(Batch group, int slot, BatchRenderer batch, ComputeBuffer animations, ComputeBuffer states, Camera camera)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Expected O, but got Unknown
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		if (group.Ids.Count == 0)
		{
			return;
		}
		if (group.Capacity < group.Ids.Count)
		{
			ComputeBuffer idBuffer = group.IdBuffer;
			if (idBuffer != null)
			{
				idBuffer.Release();
			}
			group.Capacity = Mathf.NextPowerOfTwo(group.Ids.Count);
			group.IdBuffer = new ComputeBuffer(group.Capacity, 4);
		}
		group.IdBuffer.SetData<uint>(group.Ids);
		args[0] = batch.mesh.GetIndexCount(slot);
		args[1] = (uint)group.Ids.Count;
		args[2] = batch.mesh.GetIndexStart(slot);
		args[3] = batch.mesh.GetBaseVertex(slot);
		args[4] = 0u;
		group.Args.SetData((Array)args);
		group.Material.SetBuffer("_InstBuffer", batch.instBuffer);
		group.Material.SetBuffer("_IdBuffer", group.IdBuffer);
		group.Material.SetBuffer("_AnimBuffer", animations);
		if (states != null)
		{
			group.Material.SetBuffer("_StateBuffer", states);
		}
		VertaBuffer vertaBuffer = batch.vertaBuffer;
		if (vertaBuffer != null)
		{
			vertaBuffer.SetToAnimMaterial(group.Material);
		}
		Graphics.DrawMeshInstancedIndirect(batch.mesh, slot, group.Material, new Bounds(Vector3.zero, Vector3.one * 10000f), group.Args, 0, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false, 0, camera, (LightProbeUsage)1);
	}

	internal static void Clear()
	{
		foreach (Group value in groups.Values)
		{
			value.Liquid.Free();
			value.Spray.Free();
		}
		groups.Clear();
		liquidSlot = (spraySlot = -1);
	}
}
internal static class FactoryIcon
{
	private static Sprite sprite;

	private static Texture2D texture;

	internal static void Apply()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Expected O, but got Unknown
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)sprite == (Object)null)
		{
			Sprite iconSprite = ((ProtoSet<ItemProto>)(object)LDB.items).Select(2313).iconSprite;
			Rect textureRect = iconSprite.textureRect;
			RenderTexture temporary = RenderTexture.GetTemporary(80, 80, 0, (RenderTextureFormat)0);
			RenderTexture active = RenderTexture.active;
			try
			{
				Graphics.Blit((Texture)(object)iconSprite.texture, temporary, new Vector2(((Rect)(ref textureRect)).width / (float)((Texture)iconSprite.texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)iconSprite.texture).height), new Vector2(((Rect)(ref textureRect)).x / (float)((Texture)iconSprite.texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)iconSprite.texture).height));
				RenderTexture.active = temporary;
				texture = new Texture2D(80, 80, (TextureFormat)5, false)
				{
					name = "spray-factory-icon"
				};
				texture.ReadPixels(new Rect(0f, 0f, 80f, 80f), 0, 0);
				Color[] pixels = texture.GetPixels();
				for (int i = 0; i < pixels.Length; i++)
				{
					Color val = pixels[i];
					float num = ((val.a > 0f) ? ((Color)(ref val)).grayscale : 0f);
					pixels[i] = new Color(num, num, num, val.a);
				}
				texture.SetPixels(pixels);
				texture.Apply();
				Texture2D obj = texture;
				Rect val2 = new Rect(0f, 0f, 80f, 80f);
				Vector2 pivot = iconSprite.pivot;
				Rect rect = iconSprite.rect;
				sprite = Sprite.Create(obj, val2, pivot / ((Rect)(ref rect)).size, iconSprite.pixelsPerUnit);
				((Object)sprite).name = "spray-factory-icon";
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}
		AccessTools.Field(typeof(ItemProto), "_iconSprite").SetValue(((ProtoSet<ItemProto>)(object)LDB.items).Select(Prototypes.ItemId), sprite);
		((ProtoSet<ModelProto>)(object)LDB.models).Select(Prototypes.ModelId).OverrideIconSprite(sprite);
	}

	internal static void Clear()
	{
		if ((Object)(object)sprite != (Object)null)
		{
			Object.Destroy((Object)(object)sprite);
		}
		if ((Object)(object)texture != (Object)null)
		{
			Object.Destroy((Object)(object)texture);
		}
		sprite = null;
		texture = null;
	}
}
internal static class FactoryParameters
{
	internal static bool IsFactory(PlanetFactory factory, int id)
	{
		if (id <= 0)
		{
			if (factory != null && id < 0 && -id < factory.prebuildPool.Length && factory.prebuildPool[-id].id == -id)
			{
				return factory.prebuildPool[-id].protoId == Prototypes.ItemId;
			}
			return false;
		}
		return FactoryRuntime.IsFactory(factory, id);
	}

	internal static int[] Encode(int recipe, bool accelerate)
	{
		return new int[4]
		{
			1048576,
			1,
			recipe,
			accelerate ? 1 : 0
		};
	}

	internal static bool Decode(int[] data, out int recipe, out bool accelerate)
	{
		recipe = 0;
		accelerate = false;
		if (data == null || data.Length < 4 || data[0] != 1048576 || data[1] != 1)
		{
			return false;
		}
		recipe = data[2];
		accelerate = data[3] != 0;
		return true;
	}

	internal static void Read(PlanetFactory factory, int id, out int recipe, out bool accelerate)
	{
		recipe = 0;
		accelerate = false;
		FactoryState state;
		if (id < 0)
		{
			recipe = factory.prebuildPool[-id].recipeId;
			if (Decode(factory.prebuildPool[-id].parameters, out var recipe2, out accelerate))
			{
				recipe = recipe2;
			}
		}
		else if (FactoryStore.TryGet(factory.planetId, id, out state))
		{
			lock (state.Sync)
			{
				recipe = state.RecipeId;
				accelerate = state.ForceAccMode;
			}
		}
	}

	internal static bool Allowed(PlanetFactory factory, int recipe)
	{
		if (recipe != 0)
		{
			if (((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(recipe) != null)
			{
				GameHistoryData obj = factory.gameData?.history ?? GameMain.history;
				if (obj == null)
				{
					return false;
				}
				return obj.RecipeUnlocked(recipe);
			}
			return false;
		}
		return true;
	}

	internal static void Apply(PlanetFactory factory, int id, int recipe, bool accelerate)
	{
		if (id < 0)
		{
			factory.prebuildPool[-id].recipeId = recipe;
			factory.prebuildPool[-id].parameters = Encode(recipe, accelerate);
			factory.prebuildPool[-id].paramCount = 4;
			return;
		}
		FactoryState factoryState = FactoryStore.Get(factory.planetId, id);
		lock (factoryState.Sync)
		{
			factoryState.ChangeRecipe(recipe);
			factoryState.ForceAccMode = accelerate;
		}
		FactoryRuntime.UpdateSign(factory, id, ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(recipe), working: false);
	}
}
[HarmonyPatch(typeof(BuildingParameters), "CopyFromFactoryObject")]
internal static class CopyFactoryParameters
{
	private static bool Prefix(ref BuildingParameters __instance, int objectId, PlanetFactory factory, ref bool __result)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		if (!FactoryParameters.IsFactory(factory, objectId))
		{
			return true;
		}
		((BuildingParameters)(ref __instance)).SetEmpty();
		__instance.type = (BuildingType)99;
		__instance.itemId = Prototypes.ItemId;
		__instance.modelIndex = ((objectId > 0) ? factory.entityPool[objectId].modelIndex : factory.prebuildPool[-objectId].modelIndex);
		Vector3 val = ((objectId > 0) ? factory.entityPool[objectId].pos : factory.prebuildPool[-objectId].pos);
		Quaternion val2 = ((objectId > 0) ? factory.entityPool[objectId].rot : factory.prebuildPool[-objectId].rot);
		Quaternion val3 = Quaternion.Inverse(Maths.SphericalRotation(val, 0f)) * val2;
		__instance.yaw = Mathf.Round(((Quaternion)(ref val3)).eulerAngles.y / 3f) * 3f;
		FactoryParameters.Read(factory, objectId, out var recipe, out var accelerate);
		__instance.recipeId = recipe;
		RecipeProto obj = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(recipe);
		__instance.recipeType = (ERecipeType)((obj != null) ? ((int)obj.Type) : 0);
		__instance.mode0 = (accelerate ? 1 : 0);
		__instance.parameters = FactoryParameters.Encode(recipe, accelerate);
		__result = true;
		return false;
	}
}
[HarmonyPatch(typeof(BuildingParameters), "ToParamsArray")]
internal static class EncodeFactoryParameters
{
	private static bool Prefix(ref BuildingParameters __instance, ref int[] _parameters, ref int _paramCount)
	{
		if (__instance.itemId != Prototypes.ItemId)
		{
			return true;
		}
		_parameters = FactoryParameters.Encode(__instance.recipeId, __instance.mode0 != 0);
		_paramCount = 4;
		return false;
	}
}
[HarmonyPatch(typeof(BuildingParameters), "FromParamsArray")]
internal static class DecodeFactoryParameters
{
	private static bool Prefix(ref BuildingParameters __instance, int[] _parameters)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		if (__instance.itemId != Prototypes.ItemId)
		{
			return true;
		}
		if (FactoryParameters.Decode(_parameters, out var recipe, out var accelerate))
		{
			__instance.recipeId = recipe;
			RecipeProto obj = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(recipe);
			__instance.recipeType = (ERecipeType)((obj != null) ? ((int)obj.Type) : 0);
			__instance.mode0 = (accelerate ? 1 : 0);
			__instance.parameters = (int[])_parameters.Clone();
		}
		return false;
	}
}
[HarmonyPatch(typeof(BuildingParameters), "CanPasteToFactoryObject")]
internal static class CanPasteFactoryParameters
{
	private static bool Prefix(ref BuildingParameters __instance, int objectId, PlanetFactory factory, ref bool __result)
	{
		if (__instance.itemId != Prototypes.ItemId && !FactoryParameters.IsFactory(factory, objectId))
		{
			return true;
		}
		__result = __instance.itemId == Prototypes.ItemId && FactoryParameters.IsFactory(factory, objectId) && FactoryParameters.Allowed(factory, __instance.recipeId);
		return false;
	}
}
[HarmonyPatch(typeof(BuildingParameters), "PasteToFactoryObject")]
internal static class PasteFactoryParameters
{
	private static bool Prefix(ref BuildingParameters __instance, int objectId, PlanetFactory factory, ref bool __result)
	{
		if (__instance.itemId != Prototypes.ItemId && !FactoryParameters.IsFactory(factory, objectId))
		{
			return true;
		}
		__result = __instance.itemId == Prototypes.ItemId && FactoryParameters.IsFactory(factory, objectId) && FactoryParameters.Allowed(factory, __instance.recipeId);
		if (__result)
		{
			FactoryParameters.Apply(factory, objectId, __instance.recipeId, __instance.mode0 != 0);
		}
		return false;
	}
}
[HarmonyPatch(typeof(BuildingParameters), "ApplyPrebuildParametersToEntity")]
internal static class RestoreFactoryParameters
{
	private static bool Prefix(int entityId, int recipeId, int[] parameters, PlanetFactory factory)
	{
		if (!FactoryRuntime.IsFactory(factory, entityId))
		{
			return true;
		}
		bool accelerate = false;
		if (FactoryParameters.Decode(parameters, out var recipe, out accelerate))
		{
			recipeId = recipe;
		}
		if (FactoryParameters.Allowed(factory, recipeId))
		{
			FactoryParameters.Apply(factory, entityId, recipeId, accelerate);
		}
		return false;
	}
}
[HarmonyPatch(typeof(BuildTool_Addon), "DeterminePreviews")]
internal static class FactoryAddonPreview
{
	private static void Postfix(BuildTool_Addon __instance)
	{
		if (((Proto)(__instance.handItem?)).ID != Prototypes.ItemId)
		{
			return;
		}
		List<BuildPreview> list = ((BuildTool)__instance).actionBuild?.templatePreviews;
		if (list == null || list.Count == 0 || ((Proto)(list[0].item?)).ID != Prototypes.ItemId)
		{
			return;
		}
		BuildPreview obj = list[0];
		bool accelerate = false;
		int num = obj.recipeId;
		if (FactoryParameters.Decode(obj.parameters, out var recipe, out accelerate))
		{
			num = recipe;
		}
		foreach (BuildPreview buildPreview in ((BuildTool)__instance).buildPreviews)
		{
			if (((Proto)(buildPreview.item?)).ID == Prototypes.ItemId)
			{
				buildPreview.recipeId = num;
				buildPreview.SetParameters(4, FactoryParameters.Encode(num, accelerate));
			}
		}
	}
}
internal static class FactoryPower
{
	internal static float Ratio(PowerSystem system, int consumerId)
	{
		if (system == null || consumerId <= 0 || consumerId >= system.consumerPool.Length || system.consumerPool[consumerId].id != consumerId)
		{
			return 0f;
		}
		int networkId = system.consumerPool[consumerId].networkId;
		if (networkId <= 0 || networkId >= system.netPool.Length || system.netPool[networkId] == null)
		{
			return 0f;
		}
		return Mathf.Clamp01((float)system.netPool[networkId].consumerRatio);
	}

	internal static void Restore(PlanetFactory factory)
	{
		CargoTraffic cargoTraffic = factory.cargoTraffic;
		PowerSystem powerSystem = factory.powerSystem;
		if (cargoTraffic == null || powerSystem == null)
		{
			return;
		}
		for (int i = 1; i < cargoTraffic.spraycoaterCursor; i++)
		{
			ref SpraycoaterComponent reference = ref cargoTraffic.spraycoaterPool[i];
			if (reference.id == i && FactoryRuntime.IsFactory(factory, reference.entityId))
			{
				int num = factory.entityPool[reference.entityId].powerConId;
				if (num <= 0 || num >= powerSystem.consumerPool.Length || powerSystem.consumerPool[num].id != num || powerSystem.consumerPool[num].entityId != reference.entityId)
				{
					num = powerSystem.NewConsumerComponent(reference.entityId, 5000L, 167L);
				}
				reference.pcId = num;
				ref PowerConsumerComponent reference2 = ref powerSystem.consumerPool[num];
				reference2.workEnergyPerTick = 5000L;
				reference2.idleEnergyPerTick = 167L;
				((PowerConsumerComponent)(ref reference2)).SetRequiredEnergy(false);
			}
		}
	}
}
[HarmonyPatch(typeof(PlanetFactory), "Import")]
internal static class RestoreFactoryPower
{
	private static void Postfix(PlanetFactory __instance)
	{
		FactoryPower.Restore(__instance);
	}
}
internal static class FactoryRecipePicker
{
	private static UIRecipePicker owned;

	private static UIWindowDrag drag;

	private static Text title;

	private static Vector2 titleSize;

	private static bool titleRaycast;

	internal static void Open(RectTransform origin, Action<RecipeProto> onReturn)
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		UIRecipePicker recipePicker = UIRoot.instance.uiGame.recipePicker;
		if (((ManualBehaviour)recipePicker).active)
		{
			if ((Object)(object)owned == (Object)(object)recipePicker)
			{
				Close();
			}
		}
		else if (((ManualBehaviour)recipePicker).inited)
		{
			title = ((Component)((Component)recipePicker).transform.Find("title-text")).GetComponent<Text>();
			titleSize = ((Graphic)title).rectTransform.sizeDelta;
			titleRaycast = ((Graphic)title).raycastTarget;
			if ((Object)(object)drag == (Object)null)
			{
				drag = ((Component)recipePicker).gameObject.AddComponent<UIWindowDrag>();
				((Behaviour)drag).enabled = false;
				drag.dragTrigger = ((Component)title).gameObject.AddComponent<EventTrigger>();
				drag.dragTrans = (drag.refTrans = recipePicker.pickerTrans);
				UIWindowDrag component = ((Component)UIRoot.instance.uiGame.assemblerWindow).GetComponent<UIWindowDrag>();
				drag.screenRect = component.screenRect;
				drag.dragThreshold = component.dragThreshold;
				drag.damping = component.damping;
				drag.spring = component.spring;
				drag.hasPopupAudio = false;
			}
			RectTransform rectTransform = ((Graphic)title).rectTransform;
			Rect rect = recipePicker.pickerTrans.rect;
			rectTransform.SetSizeWithCurrentAnchors((Axis)0, ((Rect)(ref rect)).width - ((Graphic)title).rectTransform.anchoredPosition.x - 50f);
			((Graphic)title).raycastTarget = true;
			owned = recipePicker;
			((Behaviour)drag).enabled = true;
			UIRecipePicker.Popup(Vector2.zero, onReturn, (ERecipeType)0);
			Align(recipePicker.pickerTrans, origin, drag.screenRect);
		}
	}

	private static void Align(RectTransform target, RectTransform origin, RectTransform screen)
	{
		//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_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)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: 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_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: 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_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		Rect rect = origin.rect;
		float xMin = ((Rect)(ref rect)).xMin;
		rect = origin.rect;
		Vector3 val = ((Transform)origin).TransformPoint(new Vector3(xMin, ((Rect)(ref rect)).yMax, 0f));
		Vector3 position = ((Transform)target).position;
		rect = target.rect;
		float xMin2 = ((Rect)(ref rect)).xMin;
		rect = target.rect;
		((Transform)target).position = position + (val - ((Transform)target).TransformPoint(new Vector3(xMin2, ((Rect)(ref rect)).yMax, 0f)));
		Vector3[] array = (Vector3[])(object)new Vector3[4];
		target.GetWorldCorners(array);
		Vector3 val2 = ((Transform)screen).InverseTransformPoint(array[0]);
		Vector3 val3 = ((Transform)screen).InverseTransformPoint(array[2]);
		float x = val2.x;
		rect = screen.rect;
		float num;
		if (!(x < ((Rect)(ref rect)).xMin))
		{
			rect = screen.rect;
			num = Mathf.Min(0f, ((Rect)(ref rect)).xMax - val3.x);
		}
		else
		{
			rect = screen.rect;
			num = ((Rect)(ref rect)).xMin - val2.x;
		}
		float num2 = num;
		float y = val3.y;
		rect = screen.rect;
		float num3;
		if (!(y > ((Rect)(ref rect)).yMax))
		{
			rect = screen.rect;
			num3 = Mathf.Max(0f, ((Rect)(ref rect)).yMin - val2.y);
		}
		else
		{
			rect = screen.rect;
			num3 = ((Rect)(ref rect)).yMax - val3.y;
		}
		float num4 = num3;
		((Transform)target).position = ((Transform)target).position + ((Transform)screen).TransformVector(new Vector3(num2, num4, 0f));
	}

	internal static void Close()
	{
		if (!((Object)(object)owned == (Object)null))
		{
			if (((ManualBehaviour)owned).active)
			{
				UIRecipePicker.Close();
			}
			else
			{
				Release(owned);
			}
		}
	}

	internal static void Release(UIRecipePicker picker)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)owned != (Object)(object)picker))
		{
			((Behaviour)drag).enabled = false;
			((Graphic)title).rectTransform.sizeDelta = titleSize;
			((Graphic)title).raycastTarget = titleRaycast;
			owned = null;
		}
	}
}
[HarmonyPatch(typeof(UIRecipePicker), "_OnClose")]
internal static class RecipePickerClosePatch
{
	private static void Postfix(UIRecipePicker __instance)
	{
		FactoryRecipePicker.Release(__instance);
	}
}
public static class FactoryRuntime
{
	public static bool IsFactory(PlanetFactory factory, int entity)
	{
		if (factory != null && entity > 0 && entity < factory.entityPool.Length && factory.entityPool[entity].id == entity)
		{
			return factory.entityPool[entity].protoId == Prototypes.ItemId;
		}
		return false;
	}

	public static int OutputStackLimit()
	{
		return Math.Max(1, Math.Min(255, GameMain.history?.stationPilerLevel ?? 1));
	}

	public static void SetPower(ref SpraycoaterComponent component, PowerConsumerComponent[] consumers)
	{
		if (component.incCapacity != 1048576)
		{
			((SpraycoaterComponent)(ref component)).SetPCState(consumers);
		}
		else if (component.pcId > 0 && component.pcId < consumers.Length && consumers[component.pcId].id == component.pcId)
		{
			((PowerConsumerComponent)(ref consumers[component.pcId])).SetRequiredEnergy(component.incUsed);
		}
	}

	public static void UpdateSign(PlanetFactory factory, int entity, RecipeProto recipe, bool working)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		if (factory.entitySignPool != null && entity > 0 && entity < factory.entitySignPool.Length)
		{
			ref SignData reference = ref factory.entitySignPool[entity];
			if (reference.w <= 0f)
			{
				EntityData val = factory.entityPool[entity];
				PrefabDesc prefabDesc = ((ProtoSet<ItemProto>)(object)LDB.items).Select(Prototypes.ItemId).prefabDesc;
				((SignData)(ref reference)).Reset(val.pos, val.rot, prefabDesc.signHeight, prefabDesc.signSize);
			}
			reference.iconId0 = (uint)(((Proto)(recipe?)).ID ?? 0);
			reference.iconType = ((recipe != null) ? 2u : 0u);
			reference.signType = ((recipe == null) ? 4u : ((!working) ? 6u : 0u));
		}
	}

	public static void Tick(ref SpraycoaterComponent component, CargoTraffic traffic, AnimData[] animations, int[] consumeRegister)
	{
		PlanetFactory factory = traffic.factory;
		FactoryState factoryState = FactoryStore.Get(factory.planetId, component.entityId);
		lock (factoryState.Sync)
		{
			if (factoryState.SprayTicks > 0)
			{
				factoryState.SprayTicks--;
			}
			RecipeProto val = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(factoryState.RecipeId);
			bool flag = val != null && GameMain.history != null && GameMain.history.RecipeUnlocked(((Proto)val).ID);
			float num = FactoryPower.Ratio(factory.powerSystem, component.pcId);
			if (flag && num >= 0.1f)
			{
				Receive(traffic, component.incBeltId, factoryState, val);
			}
			bool flag2 = false;
			component.incUsed = flag && factoryState.CanWork(val);
			if (flag && num >= 0.1f)
			{
				int[] productRegister = GameMain.statistics.production.factoryStatPool[factory.index].productRegister;
				flag2 = factoryState.Tick(val, delegate(int id, int count)
				{
					lock (consumeRegister)
					{
						consumeRegister[id] += count;
					}
				}, delegate(int id, int count)
				{
					lock (productRegister)
					{
						productRegister[id] += count;
					}
				}, num);
			}
			if (!flag)
			{
				factoryState.Status = ((val == null) ? "未选择配方" : "配方尚未解锁");
			}
			else if (num < 0.1f)
			{
				factoryState.Status = "未供电";
			}
			else if (flag2 && num < 0.999f)
			{
				factoryState.Status = "供电不足";
			}
			UpdateSign(factory, component.entityId, val, flag2);
			if (num < 0.5f && factory.entitySignPool != null)
			{
				int num2 = ((component.pcId > 0 && component.pcId < factory.powerSystem.consumerPool.Length) ? factory.powerSystem.consumerPool[component.pcId].networkId : 0);
				factory.entitySignPool[component.entityId].signType = ((num2 == 0) ? 1u : ((num < 0.1f) ? 2u : 3u));
			}
			if (num >= 0.1f)
			{
				Send(traffic, component.cargoBeltId, factoryState);
			}
			if (animations != null)
			{
				ref AnimData reference = ref animations[component.entityId];
				UpdateAnimation(ref reference, factoryState, val);
				reference.power = num;
			}
		}
	}

	public static void UpdateAnimation(ref AnimData animation, FactoryState state, RecipeProto recipe)
	{
		float num = 0f;
		float num2 = 0f;
		if (recipe != null)
		{
			for (int i = 0; i < recipe.Items.Length; i++)
			{
				num += (float)FactoryState.InputLimit(recipe.ItemCounts[i]);
				if (state.Input.TryGetValue(recipe.Items[i], out var value))
				{
					num2 += (float)value.Count;
				}
				if (state.Pending.TryGetValue(recipe.Items[i], out var value2))
				{
					num2 += (float)value2.Count;
				}
			}
		}
		animation.state = ((recipe == null && state.SprayTicks == 0) ? 1u : 41u);
		if (state.SprayTicks > 0)
		{
			animation.state += (uint)(100 + state.SprayTicks * 1000);
		}
		animation.time = ((recipe == null) ? 0f : Mathf.Lerp(0.35f, 0.9f, (num > 0f) ? Mathf.Clamp01(num2 / num) : 0f));
		animation.power = 1f;
	}

	public static void Receive(CargoTraffic traffic, int belt, FactoryState state, RecipeProto recipe)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: 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)
		if (belt <= 0 || belt >= traffic.beltPool.Length || traffic.beltPool[belt].id != belt)
		{
			return;
		}
		BeltComponent val = traffic.beltPool[belt];
		CargoPath cargoPath = traffic.GetCargoPath(val.segPathId);
		if (cargoPath == null)
		{
			return;
		}
		lock (cargoPath.buffer)
		{
			int num = val.segIndex + val.segPivotOffset;
			int cargoIdAtIndex = cargoPath.GetCargoIdAtIndex(num - 2, 5);
			if (cargoIdAtIndex < 0)
			{
				return;
			}
			ref Cargo reference = ref traffic.container.cargoPool[cargoIdAtIndex];
			if (reference.stack <= 0)
			{
				return;
			}
			int num2 = Math.Min(state.Acceptable(recipe, reference.item), reference.stack);
			if (num2 <= 0)
			{
				return;
			}
			if (num2 < reference.stack)
			{
				int num3 = reference.inc * num2 / reference.stack;
				FactoryState.Buffer(state.Input, reference.item).Add(num2, num3);
				reference.stack -= (byte)num2;
				reference.inc -= (byte)num3;
			}
			else
			{
				byte count = default(byte);
				byte inc = default(byte);
				int num4 = cargoPath.TryPickItem(num - 2, 5, (int)reference.item, ref count, ref inc);
				if (num4 > 0)
				{
					FactoryState.Buffer(state.Input, num4).Add(count, inc);
				}
			}
		}
	}

	public static void Send(CargoTraffic traffic, int belt, FactoryState state)
	{
		if (belt <= 0 || belt >= traffic.beltPool.Length || traffic.beltPool[belt].id != belt)
		{
			return;
		}
		int stack = OutputStackLimit();
		KeyValuePair<int, ItemBuffer>[] array = (from x in state.Output
			where x.Value.Count >= stack
			orderby x.Key
			select x).ToArray();
		if (array.Length != 0)
		{
			int num = (state.OutputCursor & 0x7FFFFFFF) % array.Length;
			KeyValuePair<int, ItemBuffer> keyValuePair = array[num];
			int num2 = (int)((keyValuePair.Value.Count != 0) ? ((long)keyValuePair.Value.Inc * (long)stack / keyValuePair.Value.Count) : 0);
			if (num2 <= 255 && traffic.TryInsertItem(belt, 0, keyValuePair.Key, (byte)stack, (byte)Math.Min(255, num2)))
			{
				keyValuePair.Value.Take(stack);
				state.SprayTicks = 45;
				state.SprayItemId = keyValuePair.Key;
				state.OutputCursor = (num + 1) % array.Length;
			}
		}
	}

	public static void ReturnItems(Player player, int entity, FactoryState state)
	{
		lock (state.Sync)
		{
			Dictionary<int, ItemBuffer>[] array = new Dictionary<int, ItemBuffer>[3] { state.Input, state.Output, state.Pending };
			for (int i = 0; i < array.Length; i++)
			{
				foreach (KeyValuePair<int, ItemBuffer> item in array[i])
				{
					player.TryAddItemToPackage(item.Key, item.Value.Count, item.Value.Inc, true, entity, false);
					item.Value.Count = (item.Value.Inc = 0);
				}
			}
			state.Input.Clear();
			state.Output.Clear();
			state.Pending.Clear();
			state.Progress = (state.Duration = 0);
			state.PowerProgress = 0.0;
			state.SprayTicks = (state.SprayItemId = 0);
		}
	}
}
[HarmonyPatch(typeof(SpraycoaterComponent), "InternalUpdate")]
internal static class ProductionPatch
{
	private static bool Prefix(ref SpraycoaterComponent __instance, CargoTraffic _traffic, AnimData[] _animPool, int[] consumeRegister)
	{
		if (!FactoryRuntime.IsFactory(_traffic.factory, __instance.entityId))
		{
			return true;
		}
		FactoryRuntime.Tick(ref __instance, _traffic, _animPool, consumeRegister);
		return false;
	}
}
[HarmonyPatch(typeof(CargoTraffic), "SpraycoaterGameTick")]
internal static class PowerPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		MethodInfo source = AccessTools.Method(typeof(SpraycoaterComponent), "SetPCState", (Type[])null, (Type[])null);
		MethodInfo target = AccessTools.Method(typeof(FactoryRuntime), "SetPower", (Type[])null, (Type[])null);
		int replaced = 0;
		foreach (CodeInstruction instruction in instructions)
		{
			if (CodeInstructionExtensions.Calls(instruction, source))
			{
				instruction.opcode = OpCodes.Call;
				instruction.operand = target;
				replaced++;
			}
			yield return instruction;
		}
		if (replaced != 1)
		{
			throw new InvalidOperationException("Spraycoater power update call was not found exactly once.");
		}
	}
}
[HarmonyPatch(typeof(CargoTraffic), "TakeBackItems_Spraycoater")]
internal static class ReturnPatch
{
	private static bool Prefix(CargoTraffic __instance, Player player, int spraycoaterId)
	{
		int entityId = __instance.spraycoaterPool[spraycoaterId].entityId;
		if (!FactoryRuntime.IsFactory(__instance.factory, entityId))
		{
			return true;
		}
		if (FactoryStore.TryGet(__instance.factory.planetId, entityId, out var state))
		{
			FactoryRuntime.ReturnItems(player, entityId, state);
			lock (state.Sync)
			{
				state.Progress = (state.Duration = 0);
			}
		}
		return false;
	}
}
[HarmonyPatch(typeof(CargoTraffic), "ClearItems_Spraycoater")]
internal static class ClearPatch
{
	private static bool Prefix(CargoTraffic __instance, int spraycoaterId)
	{
		int entityId = __instance.spraycoaterPool[spraycoaterId].entityId;
		if (!FactoryRuntime.IsFactory(__instance.factory, entityId))
		{
			return true;
		}
		if (FactoryStore.TryGet(__instance.factory.planetId, entityId, out var state))
		{
			lock (state.Sync)
			{
				state.Input.Clear();
				state.Output.Clear();
				state.Pending.Clear();
				state.Progress = (state.Duration = 0);
				state.PowerProgress = 0.0;
			}
		}
		return false;
	}
}
[HarmonyPatch(typeof(CargoTraffic), "RemoveSpraycoaterComponent")]
internal static class RemovePatch
{
	private static void Prefix(CargoTraffic __instance, int id)
	{
		int entityId = __instance.spraycoaterPool[id].entityId;
		if (FactoryRuntime.IsFactory(__instance.factory, entityId) && FactoryStore.Remove(__instance.factory.planetId, entityId, out var state) && GameMain.mainPlayer != null)
		{
			FactoryRuntime.ReturnItems(GameMain.mainPlayer, entityId, state);
		}
	}
}
public sealed class ItemBuffer
{
	public int Count;

	public int Inc;

	public void Add(int count, int inc)
	{
		checked
		{
			Count += count;
			Inc += inc;
		}
	}

	public int Take(int count)
	{
		if (count < 0 || count > Count)
		{
			throw new ArgumentOutOfRangeException("count");
		}
		int num = (int)((Count != 0) ? ((long)Inc * (long)count / Count) : 0);
		Count -= count;
		Inc -= num;
		return num;
	}
}
public sealed class FactoryState
{
	public readonly object Sync = new object();

	public readonly Dictionary<int, ItemBuffer> Input = new Dictionary<int, ItemBuffer>();

	public readonly Dictionary<int, ItemBuffer> Output = new Dictionary<int, ItemBuffer>();

	public readonly Dictionary<int, ItemBuffer> Pending = new Dictionary<int, ItemBuffer>();

	public int RecipeId;

	public int Progress;

	public int Duration;

	public double PowerProgress;

	public double ExtraProgress;

	public int OutputCursor;

	public bool ForceAccMode;

	public bool BatchAccMode;

	public int SprayTicks;

	public int SprayItemId;

	public string Status = "未选择配方";

	public double BatchBonus;

	public static ItemBuffer Buffer(Dictionary<int, ItemBuffer> buffers, int item)
	{
		if (!buffers.TryGetValue(item, out var value))
		{
			value = (buffers[item] = new ItemBuffer());
		}
		return value;
	}

	public static int InputLimit(int recipeCount)
	{
		return checked(recipeCount * 2);
	}

	public static int ManualInputRounds(ERecipeType type)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Invalid comparison between Unknown and I4
		if ((int)type != 1)
		{
			return 20;
		}
		return 50;
	}

	public static int ManualInputLimit(int recipeCount, ERecipeType type)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return checked(recipeCount * ManualInputRounds(type));
	}

	public static int OutputLimit(int recipeCount, int batches = 1)
	{
		return Math.Max(200, checked(Math.Max(recipeCount * 20, FactoryRuntime.OutputStackLimit() + recipeCount * batches - 1)));
	}

	public int Acceptable(RecipeProto recipe, int item)
	{
		if (recipe == null)
		{
			return 0;
		}
		int num = Array.IndexOf(recipe.Items, item);
		if (num >= 0)
		{
			return Math.Max(0, InputLimit(recipe.ItemCounts[num]) - Buffer(Input, item).Count);
		}
		return 0;
	}

	public void ChangeRecipe(int recipeId)
	{
		if (recipeId == RecipeId)
		{
			return;
		}
		foreach (KeyValuePair<int, ItemBuffer> item in Pending)
		{
			Buffer(Input, item.Key).Add(item.Value.Count, item.Value.Inc);
		}
		Pending.Clear();
		Progress = (Duration = 0);
		ExtraProgress = 0.0;
		RecipeId = recipeId;
		PowerProgress = 0.0;
		SprayTicks = (SprayItemId = 0);
	}

	public bool CanWork(RecipeProto recipe)
	{
		if (recipe != null)
		{
			int level;
			double bonus;
			if (Pending.Count <= 0 && Duration <= 0)
			{
				return TryPlan(recipe, out level, out bonus);
			}
			return true;
		}
		return false;
	}

	private bool TryPlan(RecipeProto recipe, out int level, out double bonus)
	{
		level = 0;
		bonus = 0.0;
		for (int i = 0; i < recipe.Items.Length; i++)
		{
			if (Buffer(Input, recipe.Items[i]).Count < recipe.ItemCounts[i])
			{
				Status = "缺少原料";
				return false;
			}
		}
		level = ((recipe.Items.Length != 0) ? 10 : 0);
		for (int j = 0; j < recipe.Items.Length; j++)
		{
			ItemBuffer itemBuffer = Buffer(Input, recipe.Items[j]);
			level = Math.Min(level, (itemBuffer.Count != 0) ? (itemBuffer.Inc / itemBuffer.Count) : 0);
		}
		level = Math.Max(0, Math.Min(level, Cargo.accTableMilli.Length - 1));
		bonus = ((recipe.productive && !ForceAccMode) ? Cargo.incTableMilli[Math.Min(level, Cargo.incTableMilli.Length - 1)] : 0.0);
		int num = 1 + (int)(ExtraProgress + bonus);
		for (int k = 0; k < recipe.Results.Length; k++)
		{
			if (Buffer(Output, recipe.Results[k]).Count + (long)recipe.ResultCounts[k] * (long)num > OutputLimit(recipe.ResultCounts[k], num))
			{
				Status = "产物缓存已满";
				return false;
			}
		}
		return true;
	}

	public bool Tick(RecipeProto recipe, Action<int, int> consume, Action<int, int> produce, float power = 1f)
	{
		if (recipe == null)
		{
			Status = "未选择配方";
			return false;
		}
		if (power < 0.1f)
		{
			Status = "未供电";
			return false;
		}
		if (Pending.Count == 0 && Duration == 0)
		{
			if (!TryPlan(recipe, out var level, out var bonus))
			{
				return false;
			}
			bool flag = recipe.productive && !ForceAccMode;
			for (int i = 0; i < recipe.Items.Length; i++)
			{
				ItemBuffer itemBuffer = Buffer(Input, recipe.Items[i]);
				int count = recipe.ItemCounts[i];
				Buffer(Pending, recipe.Items[i]).Add(count, itemBuffer.Take(count));
			}
			Duration = Math.Max(1, recipe.TimeSpend);
			if (!flag)
			{
				Duration = Math.Max(1, (int)Math.Ceiling((double)Duration / (1.0 + Cargo.accTableMilli[level])));
			}
			BatchBonus = bonus;
			BatchAccMode = !flag;
		}
		Status = "生产中";
		PowerProgress += Math.Max(0f, Math.Min(1f, power));
		if (PowerProgress < 1.0)
		{
			return true;
		}
		PowerProgress -= 1.0;
		if (++Progress < Duration)
		{
			return true;
		}
		ExtraProgress += BatchBonus;
		int num = 1 + (int)ExtraProgress;
		ExtraProgress -= (int)ExtraProgress;
		for (int j = 0; j < recipe.Results.Length; j++)
		{
			int num2 = checked(recipe.ResultCounts[j] * num);
			Buffer(Output, recipe.Results[j]).Add(num2, 0);
			produce?.Invoke(recipe.Results[j], num2);
		}
		foreach (KeyValuePair<int, ItemBuffer> item in Pending)
		{
			consume?.Invoke(item.Key, item.Value.Count);
		}
		Pending.Clear();
		Progress = (Duration = 0);
		return true;
	}

	public void Write(BinaryWriter w)
	{
		w.Write(RecipeId);
		w.Write(Progress);
		w.Write(Duration);
		w.Write(ExtraProgress);
		w.Write(BatchBonus);
		w.Write(OutputCursor);
		WriteBuffers(w, Input);
		WriteBuffers(w, Output);
		WriteBuffers(w, Pending);
		w.Write(ForceAccMode);
		w.Write(BatchAccMode);
	}

	public static FactoryState Read(BinaryReader r, int version = 2)
	{
		FactoryState factoryState = new FactoryState
		{
			RecipeId = r.ReadInt32(),
			Progress = r.ReadInt32(),
			Duration = r.ReadInt32(),
			ExtraProgress = r.ReadDouble(),
			BatchBonus = r.ReadDouble(),
			OutputCursor = r.ReadInt32()
		};
		if (factoryState.Progress < 0 || factoryState.Duration < 0 || factoryState.Progress > factoryState.Duration || double.IsNaN(factoryState.ExtraProgress) || double.IsInfinity(factoryState.ExtraProgress) || factoryState.ExtraProgress < 0.0 || factoryState.ExtraProgress >= 1.0 || double.IsNaN(factoryState.BatchBonus) || double.IsInfinity(factoryState.BatchBonus) || factoryState.BatchBonus < 0.0 || factoryState.BatchBonus > 10.0)
		{
			throw new InvalidDataException("Invalid factory progress.");
		}
		ReadBuffers(r, factoryState.Input);
		ReadBuffers(r, factoryState.Output);
		ReadBuffers(r, factoryState.Pending);
		if (version >= 2)
		{
			factoryState.ForceAccMode = r.ReadBoolean();
			factoryState.BatchAccMode = r.ReadBoolean();
		}
		return factoryState;
	}

	private static void WriteBuffers(BinaryWriter w, Dictionary<int, ItemBuffer> buffers)
	{
		KeyValuePair<int, ItemBuffer>[] array = (from x in buffers
			where x.Value.Count > 0
			orderby x.Key
			select x).ToArray();
		w.Write(array.Length);
		KeyValuePair<int, ItemBuffer>[] array2 = array;
		for (int num = 0; num < array2.Length; num++)
		{
			KeyValuePair<int, ItemBuffer> keyValuePair = array2[num];
			w.Write(keyValuePair.Key);
			w.Write(keyValuePair.Value.Count);
			w.Write(keyValuePair.Value.Inc);
		}
	}

	private static void ReadBuffers(BinaryReader r, Dictionary<int, ItemBuffer> buffers)
	{
		int num = r.ReadInt32();
		if (num < 0 || num > 12000)
		{
			throw new InvalidDataException("Invalid factory buffer size.");
		}
		for (int i = 0; i < num; i++)
		{
			int num2 = r.ReadInt32();
			int num3 = r.ReadInt32();
			int num4 = r.ReadInt32();
			if (num2 <= 0 || num3 < 0 || num4 < 0 || buffers.ContainsKey(num2))
			{
				throw new InvalidDataException("Invalid factory buffer entry.");
			}
			buffers.Add(num2, new ItemBuffer
			{
				Count = num3,
				Inc = num4
			});
		}
	}
}
public static class FactoryStore
{
	private static readonly ConcurrentDictionary<long, FactoryState> states = new ConcurrentDictionary<long, FactoryState>();

	public static long Key(int planet, int entity)
	{
		return ((long)planet << 32) | (uint)entity;
	}

	public static FactoryState Get(int planet, int entity)
	{
		return states.GetOrAdd(Key(planet, entity), (long _) => new FactoryState());
	}

	public static bool Remove(int planet, int entity, out FactoryState state)
	{
		return states.TryRemove(Key(planet, entity), out state);
	}

	public static bool TryGet(int planet, int entity, out FactoryState state)
	{
		return states.TryGetValue(Key(planet, entity), out state);
	}

	public static void Clear()
	{
		states.Clear();
	}

	public static void Export(BinaryWriter w)
	{
		w.Write(2);
		KeyValuePair<long, FactoryState>[] array = states.OrderBy((KeyValuePair<long, FactoryState> x) => x.Key).ToArray();
		w.Write(array.Length);
		KeyValuePair<long, FactoryState>[] array2 = array;
		for (int num = 0; num < array2.Length; num++)
		{
			KeyValuePair<long, FactoryState> keyValuePair = array2[num];
			w.Write(keyValuePair.Key);
			lock (keyValuePair.Value.Sync)
			{
				keyValuePair.Value.Write(w);
			}
		}
	}

	public static void Import(BinaryReader r)
	{
		int num = r.ReadInt32();
		if (num != 1 && num != 2)
		{
			throw new InvalidDataException("Unsupported Spray Factory save version.");
		}
		int num2 = r.ReadInt32();
		if (num2 < 0 || num2 > 1000000)
		{
			throw new InvalidDataException("Invalid factory count.");
		}
		Dictionary<long, FactoryState> dictionary = new Dictionary<long, FactoryState>();
		for (int i = 0; i < num2; i++)
		{
			dictionary.Add(r.ReadInt64(), FactoryState.Read(r, num));
		}
		states.Clear();
		foreach (KeyValuePair<long, FactoryState> item in dictionary)
		{
			states[item.Key] = item.Value;
		}
	}
}
internal static class FactoryRates
{
	internal static void Calculate(FactoryState state, RecipeProto recipe, out float cycles, out float multiplier)
	{
		int val = ((recipe.Items.Length != 0) ? (Cargo.accTableMilli.Length - 1) : 0);
		Dictionary<int, ItemBuffer> dictionary = ((state.Pending.Count > 0) ? state.Pending : state.Input);
		int[] items = recipe.Items;
		foreach (int key in items)
		{
			ItemBuffer value;
			int val2 = ((dictionary.TryGetValue(key, out value) && value.Count > 0) ? (value.Inc / value.Count) : 0);
			val = Math.Min(val, val2);
		}
		val = Math.Max(0, Math.Min(val, Cargo.accTableMilli.Length - 1));
		bool flag = recipe.productive && !state.ForceAccMode;
		int num = Math.Max(1, recipe.TimeSpend);
		if (!flag)
		{
			num = Math.Max(1, (int)Math.Ceiling((double)num / (1.0 + Cargo.accTableMilli[val])));
		}
		cycles = 3600f / (float)num;
		multiplier = (flag ? (1f + (float)Cargo.incTableMilli[Math.Min(val, Cargo.incTableMilli.Length - 1)]) : 1f);
	}
}
[HarmonyPatch(typeof(ProductionExtraInfoCalculator), "CalculateFactory")]
internal static class FactoryStatistics
{
	private static void Postfix(ProductionExtraInfoCalculator __instance, GameData gameData, PlanetFactory factory)
	{
		ProductionStatistics productionStatistics = __instance.productionStatistics;
		object obj;
		if (productionStatistics == null)
		{
			obj = null;
		}
		else
		{
			FactoryProductionStat[] factoryStatPool = productionStatistics.factoryStatPool;
			obj = ((factoryStatPool != null) ? factoryStatPool[factory.index] : null);
		}
		FactoryProductionStat val = (FactoryProductionStat)obj;
		if (val != null && factory.cargoTraffic != null)
		{
			Add(factory, gameData.history, val);
		}
	}

	internal static void Add(PlanetFactory factory, GameHistoryData history, FactoryProductionStat stat)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		CargoTraffic cargoTraffic = factory.cargoTraffic;
		for (int i = 1; i < cargoTraffic.spraycoaterCursor; i++)
		{
			SpraycoaterComponent val = cargoTraffic.spraycoaterPool[i];
			if (val.id != i || !FactoryRuntime.IsFactory(factory, val.entityId) || !FactoryStore.TryGet(factory.planetId, val.entityId, out var state))
			{
				continue;
			}
			lock (state.Sync)
			{
				RecipeProto val2 = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(state.RecipeId);
				if (val2 != null && history.RecipeUnlocked(((Proto)val2).ID))
				{
					FactoryRates.Calculate(state, val2, out var cycles, out var multiplier);
					for (int j = 0; j < val2.Items.Length; j++)
					{
						stat.AddRefConsumeSpeed(val2.Items[j], cycles * (float)val2.ItemCounts[j]);
					}
					for (int k = 0; k < val2.Results.Length; k++)
					{
						stat.AddRefProductSpeed(val2.Results[k], cycles * multiplier * (float)val2.ResultCounts[k]);
					}
				}
				AddStorage(stat, state.Input);
				AddStorage(stat, state.Output);
				AddStorage(stat, state.Pending);
			}
		}
	}

	private static void AddStorage(FactoryProductionStat stat, Dictionary<int, ItemBuffer> buffers)
	{
		foreach (KeyValuePair<int, ItemBuffer> buffer in buffers)
		{
			if (buffer.Value.Count > 0)
			{
				stat.AddStorageCount(buffer.Key, buffer.Value.Count);
				stat.AddDetailedStorageCount(buffer.Key, (EDetailedStorageCountType)3, buffer.Value.Count);
			}
		}
	}
}
internal static class FactoryWindow
{
	private sealed class ProductSlot
	{
		internal RectTransform Root;

		internal UIButton Button;

		internal Image Icon;

		internal Image Progress;

		internal Image ExtraProgress;

		internal Text Count;
	}

	private static UISpraycoaterWindow owner;

	private static UIAssemblerWindow view;

	private static readonly Dictionary<GameObject, bool> hidden = new Dictionary<GameObject, bool>();

	private static Vector2 originalSize;

	private static Vector2 originalPosition;

	private static Vector2 screenSize;

	private static Vector2? savedTopLeft;

	private static bool initialLayout;

	private static UIWindowDrag windowDrag;

	private static readonly Vector3[] windowCorners = (Vector3[])(object)new Vector3[4];

	private static StorageComponent serving;

	private static int servingRecipe;

	private static Vector2 originalIncPosition;

	private static Vector2 originalTipPosition;

	private static Vector2 originalSpeedPosition;

	private static Vector2 originalServingPosition;

	private static readonly List<ProductSlot> extraProducts = new List<ProductSlot>();

	private static readonly StringBuilder powerServed = new StringBuilder("         W     %", 20);

	internal static bool Matches(UISpraycoaterWindow window)
	{
		if (window.factory != null && window.traffic != null && window.spraycoaterId > 0)
		{
			return FactoryRuntime.IsFactory(window.factory, window.traffic.spraycoaterPool[window.spraycoaterId].entityId);
		}
		return false;
	}

	internal static void Show(UISpraycoaterWindow window)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Expected O, but got Unknown
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Expected O, but got Unknown
		//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d7: Expected O, but got Unknown
		if ((Object)(object)owner == (Object)(object)window && (Object)(object)view != (Object)null)
		{
			return;
		}
		Hide();
		owner = window;
		originalSize = ((RectTransform)((Component)owner).transform).sizeDelta;
		originalPosition = ((RectTransform)((Component)owner).transform).anchoredPosition;
		initialLayout = true;
		foreach (Transform item in ((Component)owner).transform)
		{
			Transform val = item;
			hidden[((Component)val).gameObject] = ((Component)val).gameObject.activeSelf;
			((Component)val).gameObject.SetActive(false);
		}
		view = Object.Instantiate<UIAssemblerWindow>(UIRoot.instance.uiGame.assemblerWindow, ((Component)owner).transform, false);
		((Object)view).name = "spray-factory-panel";
		((Behaviour)view).enabled = false;
		Transform obj = ((Transform)view.produceGroup).Find("lithography");
		if (obj != null)
		{
			((Component)obj).gameObject.SetActive(false);
		}
		originalIncPosition = view.incInfoGroup.anchoredPosition;
		originalTipPosition = ((Graphic)view.transferTipText).rectTransform.anchoredPosition;
		originalSpeedPosition = view.speedGroup.anchoredPosition;
		originalServingPosition = view.servingGroup.anchoredPosition;
		RectTransform val2 = (RectTransform)((Component)view).transform;
		Vector2 anchorMin = (val2.anchorMax = val2.pivot);
		val2.anchorMin = anchorMin;
		val2.anchoredPosition = Vector2.zero;
		((Transform)val2).localScale = Vector3.one;
		Button[] componentsInChildren = ((Component)view).GetComponentsInChildren<Button>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			componentsInChildren[i].onClick = new ButtonClickedEvent();
		}
		SetText(view.titleText, "喷涂工厂");
		Bind(view.recipeButton.button, SelectRecipe);
		Bind(view.resetButton.button, delegate
		{
			WithState(delegate(FactoryState state)
			{
				state.ChangeRecipe(0);
			});
		});
		Bind(view.productButton0.button, delegate
		{
			TakeOutput(0);
		});
		Bind(view.productButton1.button, delegate
		{
			TakeOutput(1);
		});
		Bind(view.incSwitchButton, delegate
		{
			WithState(delegate(FactoryState state)
			{
				state.ForceAccMode = !state.ForceAccMode;
			});
		});
		((Component)view.copyButton).gameObject.SetActive(false);
		((Component)view.pasteButton).gameObject.SetActive(false);
		Bind(((Component)((Component)view).transform.Find("panel-bg/btn-box/close-wnd-btn")).GetComponent<Button>(), delegate
		{
			UIRoot.instance.uiGame.ShutSpraycoaterWindow();
		});
		((Component)view.menuButton).gameObject.SetActive(false);
		((Component)view.alarmSwitchButton).gameObject.SetActive(false);
		((Component)view.alarmSwitchText).gameObject.SetActive(false);
		InitializeGrid(view.playerInventory);
		InitializeGrid(view.servingBox);
		view.servingBox.beforeManualChange += SyncInputs;
		UIWindowDrag component = ((Component)view).GetComponent<UIWindowDrag>();
		component.dragTrans = (RectTransform)((Component)owner).transform;
		component.refTrans = component.dragTrans;
		windowDrag = component;
		((Component)view).gameObject.SetActive(true);
	}

	private static Vector3 TopLeft(RectTransform rect)
	{
		//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_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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)
		Rect rect2 = rect.rect;
		float xMin = ((Rect)(ref rect2)).xMin;
		rect2 = rect.rect;
		return ((Transform)rect).TransformPoint(new Vector3(xMin, ((Rect)(ref rect2)).yMax, 0f));
	}

	private static void ResizeWindow(Vector2 size)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Expected O, but got Unknown
		//IL_004d: 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_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: 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_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: 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_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: 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_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0244: Unknown result type (might be due to invalid IL or missing references)
		//IL_0253: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = (RectTransform)((Component)owner).transform;
		RectTransform screenRect = windowDrag.screenRect;
		Rect rect;
		if (!initialLayout && val.sizeDelta == size)
		{
			Vector2 val2 = screenSize;
			rect = screenRect.rect;
			if (val2 == ((Rect)(ref rect)).size)
			{
				return;
			}
		}
		Vector3 val3 = TopLeft(val);
		view.windowTrans.sizeDelta = size;
		val.sizeDelta = size;
		if (initialLayout && !savedTopLeft.HasValue)
		{
			Vector3 position = ((Transform)val).position;
			rect = screenRect.rect;
			Vector3 val4 = ((Transform)screenRect).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center));
			rect = val.rect;
			((Transform)val).position = position + (val4 - ((Transform)val).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)));
		}
		else
		{
			((Transform)val).position = ((Transform)val).position + ((initialLayout ? ((Transform)screenRect).TransformPoint(Vector2.op_Implicit(savedTopLeft.Value)) : val3) - TopLeft(val));
		}
		initialLayout = false;
		rect = screenRect.rect;
		screenSize = ((Rect)(ref rect)).size;
		val.GetWorldCorners(windowCorners);
		Vector3 val5 = ((Transform)screenRect).InverseTransformPoint(windowCorners[0]);
		Vector3 val6 = ((Transform)screenRect).InverseTransformPoint(windowCorners[2]);
		rect = screenRect.rect;
		float num = ((Rect)(ref rect)).xMin + 12f;
		rect = screenRect.rect;
		float num2 = ((Rect)(ref rect)).xMax - 12f;
		rect = screenRect.rect;
		float num3 = ((Rect)(ref rect)).yMin + 12f;
		rect = screenRect.rect;
		float num4 = ((Rect)(ref rect)).yMax - 12f;
		float num5 = ((val6.x - val5.x > num2 - num) ? (num - val5.x) : ((val5.x < num) ? (num - val5.x) : Mathf.Min(0f, num2 - val6.x)));
		float num6 = ((val6.y - val5.y > num4 - num3) ? (num4 - val6.y) : ((val6.y > num4) ? (num4 - val6.y) : Mathf.Max(0f, num3 - val5.y)));
		((Transform)val).position = ((Transform)val).position + ((Transform)screenRect).TransformVector(new Vector3(num5, num6, 0f));
	}

	private static void SetText(Text label, string text)
	{
		Localizer component = ((Component)label).GetComponent<Localizer>();
		if ((Object)(object)component != (Object)null)
		{
			((Behaviour)component).enabled = false;
		}
		label.text = text;
	}

	private static void InitializeGrid(UIStorageGrid grid)
	{
		foreach (Component item in from c in ((Component)grid).GetComponentsInChildren<Component>(true)
			where (Object)(object)c != (Object)null && ((object)c).GetType().Name == "UICancelFilterTip"
			select c)
		{
			Object.DestroyImmediate((Object)(object)item.gameObject);
		}
		Text[] componentsInChildren = ((Component)grid).GetComponentsInChildren<Text>(true);
		foreach (Text val in componentsInChildren)
		{
			if ((Object)(object)val != (Object)(object)grid.prefabNumText && (Object)(object)((Component)val).transform.parent == (Object)(object)grid.rectTrans && ((Object)val).name == ((Object)grid.prefabNumText).name + "(Clone)")
			{
				Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
			}
		}
		((ManualBehaviour)grid)._Create();
		foreach (Component item2 in from c in ((Component)grid).GetComponentsInChildren<Component>(true)
			where (Object)(object)c != (Object)null && ((object)c).GetType().Name == "UICancelFilterTip"
			select c)
		{
			item2.gameObject.SetActive(false);
		}
	}

	private static void RefreshPower()
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		SpraycoaterComponent val = owner.traffic.spraycoaterPool[owner.spraycoaterId];
		PowerSystem powerSystem = owner.factory.powerSystem;
		float num = FactoryPower.Ratio(powerSystem, val.pcId);
		((Component)view.powerIcon).gameObject.SetActive(true);
		if (num < 0.1f)
		{
			view.powerText.text = Localization.Translate("未供电");
			((Graphic)view.powerIcon).color = Color.clear;
			((Graphic)view.powerText).color = view.powerOffColor;
			return;
		}
		long num2 = (long)((double)((float)(powerSystem.consumerPool[val.pcId].requiredEnergy * 60) * num) + 0.5);
		StringBuilderUtility.WriteKMG(powerServed, 8, num2, false, '\u2009', ' ');
		StringBuilderUtility.WriteUInt(powerServed, 12, 3, (uint)(num * 100f), 1, ' ');
		view.powerText.text = powerServed.ToString();
		((Graphic)view.powerIcon).color = ((num >= 0.999f) ? view.powerNormalIconColor : view.powerLowIconColor);
		((Graphic)view.powerText).color = ((num >= 0.999f) ? view.powerNormalColor : view.powerLowColor);
	}

	private static void Bind(Button button, Action action)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected O, but got Unknown
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		button.onClick = new ButtonClickedEvent();
		((UnityEvent)button.onClick).AddListener((UnityAction)delegate
		{
			action();
		});
		UIButton component = ((Component)button).GetComponent<UIButton>();
		if ((Object)(object)component != (Object)null)
		{
			component.tips = default(TipSettings);
		}
	}

	private static T CloneProductField<T>(RectTransform root, T original) where T : Component
	{
		List<string> list = new List<string>();
		Transform val = ((Component)original).transform;
		while ((Object)(object)val != (Object)(object)view.productGroup)
		{
			list.Add(((Object)val).name);
			val = val.parent;
		}
		list.Reverse();
		return ((Component)((Transform)root).Find(string.Join("/", list))).GetComponent<T>();
	}

	private static void EnsureProductSlots(int count)
	{
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: 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)
		while (extraProducts.Count < Math.Max(0, count - 2))
		{
			int index = extraProducts.Count + 2;
			RectTransform val = Object.Instantiate<RectTransform>(view.productGroup, ((Transform)view.productGroup).parent, false);
			((Object)val).name = "product-slot-" + index;
			val.sizeDelta = new Vector2(64f, 64f);
			val.anchoredPosition = view.productGroup.anchoredPosition + new Vector2((float)(64 * (index % 3)), (float)(-64 * (index / 3)));
			((Component)CloneProductField<UIButton>(val, view.productButton1)).gameObject.SetActive(false);
			((Component)CloneProductField<Text>(val, view.productCountText1)).gameObject.SetActive(false);
			((Component)CloneProductField<Image>(val, view.productProgress1)).gameObject.SetActive(false);
			((Component)CloneProductField<Image>(val, view.extraProductProgress1)).gameObject.SetActive(false);
			if (((Component)view.resetButton).transform.IsChildOf((Transform)(object)view.productGroup))
			{
				((Component)CloneProductField<UIButton>(val, view.resetButton)).gameObject.SetActive(false);
			}
			ProductSlot productSlot = new ProductSlot
			{
				Root = val,
				Button = CloneProductField<UIButton>(val, view.productButton0),
				Icon = CloneProductField<Image>(val, view.productIcon0),
				Count = CloneProductField<Text>(val, view.productCountText0),
				Progress = CloneProductField<Image>(val, view.productProgress0),
				ExtraProgress = CloneProductField<Image>(val, view.extraProductProgress0)
			};
			Bind(productSlot.Button.button, delegate
			{
				TakeOutput(index);
			});
			extraProducts.Add(productSlot);
		}
		for (int num = 0; num < extraProducts.Count; num++)
		{
			((Component)extraProducts[num].Root).gameObject.SetActive(num + 2 < count);
		}
	}

	private static void WithState(Action<FactoryState> action)
	{
		if ((Object)(object)owner == (Object)null || !Matches(owner))
		{
			return;
		}
		int entityId = owner.traffic.spraycoaterPool[owner.spraycoaterId].entityId;
		FactoryState factoryState = FactoryStore.Get(owner.factory.planetId, entityId);
		lock (factoryState.Sync)
		{
			int recipeId = factoryState.RecipeId;
			action(factoryState);
			if (recipeId != factoryState.RecipeId)
			{
				FactoryRuntime.UpdateSign(owner.factory, entityId, ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(factoryState.RecipeId), working: false);
			}
		}
	}

	private static void SelectRecipe()
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Expected O, but got Unknown
		if ((Object)(object)owner == (Object)null)
		{
			return;
		}
		int planet = owner.factory.planetId;
		int entity = owner.traffic.spraycoaterPool[owner.spraycoaterId].entityId;
		FactoryRecipePicker.Open((RectTransform)((Component)owner).transform, delegate(RecipeProto recipe)
		{
			if (recipe != null && !((Object)(object)owner == (Object)null) && Matches(owner) && owner.factory.planetId == planet && owner.traffic.spraycoaterPool[owner.spraycoaterId].entityId == entity)
			{
				WithState(delegate(FactoryState state)
				{
					state.ChangeRecipe(((Proto)recipe).ID);
				});
			}
		});
	}

	private static void TakeOutput(int index)
	{
		WithState(delegate(FactoryState state)
		{
			RecipeProto val = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(state.RecipeId);
			if (GameMain.mainPlayer != null && val != null && index < val.Results.Length)
			{
				int num = val.Results[index];
				ItemBuffer itemBuffer = FactoryState.Buffer(state.Output, num);
				GameMain.mainPlayer.TryAddItemToPackage(num, itemBuffer.Count, itemBuffer.Inc, true, owner.traffic.spraycoaterPool[owner.spraycoaterId].entityId, false);
				itemBuffer.Count = (itemBuffer.Inc = 0);
			}
		});
	}

	private static void FreeServing()
	{
		if (serving != null)
		{
			serving.onStorageChange -= ApplyInputs;
			((ManualBehaviour)view.servingBox)._Free();
			serving.Free();
			serving = null;
			servingRecipe = 0;
		}
	}

	private static void ApplyInputs()
	{
		WithState(delegate(FactoryState state)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			if (serving != null && state.RecipeId == servingRecipe)
			{
				GRID[] grids = serving.grids;
				foreach (GRID val in grids)
				{
					ItemBuffer itemBuffer = FactoryState.Buffer(state.Input, val.filter);
					itemBuffer.Count = val.count;
					itemBuffer.Inc = val.inc;
				}
			}
		});
	}

	private static void SyncInputs()
	{
		WithState(delegate(FactoryState state)
		{
			RecipeProto val = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(state.RecipeId);
			if (serving != null && val != null && state.RecipeId == servingRecipe)
			{
				for (int i = 0; i < val.Items.Length; i++)
				{
					ItemBuffer itemBuffer = FactoryState.Buffer(state.Input, val.Items[i]);
					serving.grids[i].count = itemBuffer.Count;
					serving.grids[i].inc = itemBuffer.Inc;
				}
				view.servingBox.OnStorageContentChanged();
			}
		});
	}

	internal static void Refresh(UISpraycoaterWindow window)
	{
		Show(window);
		WithState(delegate(FactoryState state)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Expected O, but got Unknown
			//IL_0459: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0915: Unknown result type (might be due to invalid IL or missing references)
			//IL_091a: Unknown result type (might be due to invalid IL or missing references)
			//IL_076a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0797: Unknown result type (might be due to invalid IL or missing references)
			//IL_07bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0974: Unknown result type (might be due to invalid IL or missing references)
			//IL_0814: Unknown result type (might be due to invalid IL or missing references)
			//IL_0820: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fd: Unknown result type (might be due to invalid IL or missing references)
			RecipeProto val = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(state.RecipeId);
			bool flag = val != null;
			bool flag2 = flag && (!val.productive || state.ForceAccMode);
			int num = (flag ? (64 * Math.Max((val.Items.Length - 1) / 3, (val.Results.Length - 1) / 3)) : 0);
			view.incInfoGroup.anchoredPosition = originalIncPosition - Vector2.up * (float)num;
			if (!((Component)view.transferTipText).transform.IsChildOf((Transform)(object)view.incInfoGroup) && !((Component)view.transferTipText).transform.IsChildOf((Transform)(object)view.playerInventoryGroup))
			{
				((Graphic)view.transferTipText).rectTransform.anchoredPosition = originalTipPosition - Vector2.up * (float)num;
			}
			((Component)view.recipeGroup).gameObject.SetActive(!flag);
			((Component)view.produceGroup).gameObject.SetActive(flag);
			((Component)view.incInfoGroup).gameObject.SetActive(flag);
			RefreshPower();
			view.stateText.text = state.Status;
			((Graphic)view.stateText).color = ((state.Status == "生产中") ? view.workNormalColor : view.workStoppedColor);
			((Selectable)view.resetButton.button).interactable = flag;
			((Selectable)view.incSwitchButton).interactable = flag && val.productive;
			((Graphic)view.incSwitchButtonImage).color = (flag2 ? view.incButtonColor2 : view.incButtonColor1);
			((Graphic)view.incSwitchButtonThumb).rectTransform.anchoredPosition = new Vector2((float)(flag2 ? 10 : (-10)), 0f);
			view.incEffectTypeText.text = (flag2 ? "加速生产" : "额外产出");
			((Graphic)view.incEffectTypeText).color = (flag2 ? view.incTextColor2 : view.incTextColor1);
			view.incEffectValueText2.text = "+0.0 %";
			SetText(view.transferTipText, "自动进料:2 轮    满 " + FactoryRuntime.OutputStackLimit() + " 层输出");
			if (servingRecipe != state.RecipeId)
			{
				FreeServing();
				if (flag && val.Items.Length != 0)
				{
					serving = new StorageComponent(val.Items.Length)
					{
						type = (EStorageType)9
					};
					servingRecipe = state.RecipeId;
					for (int i = 0; i < val.Items.Length; i++)
					{
						serving.SetFilterDirect(i, val.Items[i], FactoryState.ManualInputLimit(val.ItemCounts[i], val.Type));
					}
					serving.onStorageChange += ApplyInputs;
					view.servingBox.colCount = Math.Min(3, val.Items.Length);
					view.servingBox.lackParam = FactoryState.ManualInputRounds(val.Type);
					((ManualBehaviour)view.servingBox)._Init((object)serving);
					((ManualBehaviour)view.servingBox)._Open();
				}
			}
			((Component)view.servingGroup).gameObject.SetActive(serving != null);
			SyncInputs();
			if (flag)
			{
				FactoryRates.Calculate(state, val, out var cycles, out var multiplier);
				view.speedText.text = (cycles * (float)val.ResultCounts[0] * multiplier).ToString("0.0") + Localization.Translate("每分钟");
				view.incEffectValueText.text = "+" + ((flag2 ? Math.Max(0f, cycles * (float)val.TimeSpend / 3600f - 1f) : (multiplier - 1f)) * 100f).ToString("0.0") + " %";
				((Graphic)view.incEffectValueText).color = ((Graphic)view.incEffectTypeText).color;
				float num2 = ((state.Duration > 0) ? ((float)state.Progress / (float)state.Duration) : 0f);
				Image productProgress = view.productProgress0;
				float fillAmount = (view.productProgress1.fillAmount = num2);
				productProgress.fillAmount = fillAmount;
				float num4 = Mathf.Clamp01((float)(state.ExtraProgress + (state.BatchAccMode ? 0.0 : (state.BatchBonus * (double)num2))));
				Image extraProductProgress = view.extraProductProgress0;
				fillAmount = (view.extraProductProgress1.fillAmount = num4);
				extraProductProgress.fillAmount = fillAmount;
				EnsureProductSlots(val.Results.Length);
				for (int j = 0; j < Math.Max(2, val.Results.Length); j++)
				{
					bool flag3 = j < val.Results.Length;
					UIButton val2 = (UIButton)(j switch
					{
						1 => view.productButton1, 
						0 => view.productButton0, 
						_ => extraProducts[j - 2].Button, 
					});
					Image val3 = (Image)(j switch
					{
						1 => view.productIcon1, 
						0 => view.productIcon0, 
						_ => extraProducts[j - 2].Icon, 
					});
					Text val4 = (Text)(j switch
					{
						1 => view.productCountText1, 
						0 => view.productCountText0, 
						_ => extraProducts[j - 2].Count, 
					});
					Image val5 = (Image)(j switch
					{
						1 => view.productProgress1, 
						0 => view.productProgress0, 
						_ => extraProducts[j - 2].Progress, 
					});
					object obj = j switch
					{
						1 => view.extraProductProgress1, 
						0 => view.extraProductProgress0, 
						_ => extraProducts[j - 2].ExtraProgress, 
					};
					((Component)val2).gameObject.SetActive(flag3);
					((Component)val3).gameObject.SetActive(flag3);
					((Component)val4).gameObject.SetActive(flag3);
					((Component)val5).gameObject.SetActive(flag3);
					((Component)obj).gameObject.SetActive(flag3);
					val5.fillAmount = num2;
					((Image)obj).fillAmount = num4;
					if (flag3)
					{
						int num6 = val.Results[j];
						ItemBuffer itemBuffer = FactoryState.Buffer(state.Output, num6);
						ItemProto obj2 = ((ProtoSet<ItemProto>)(object)LDB.items).Select(num6);
						val3.sprite = ((obj2 != null) ? obj2.iconSprite : null);
						val4.text = itemBuffer.Count.ToString();
						((Selectable)val2.button).interactable = itemBuffer.Count > 0;
						val2.tips.itemId = num6;
						val2.tips.type = (ItemTipType)0;
						val2.tips.corner = 2;
						val2.tips.delay = 0.2f;
					}
				}
				int num7 = Math.Min(3, val.Results.Length) * 64;
				view.productGroup.sizeDelta = new Vector2((float)Math.Min(num7, 128), 64f);
				view.speedGroup.anchoredPosition = new Vector2((float)(num7 + 16), originalSpeedPosition.y - (float)num * 0.5f);
				view.servingGroup.anchoredPosition = new Vector2((float)(num7 + 96), originalServingPosition.y);
				int num8 = (int)(num2 * (float)view.speedArrows.Length) % view.speedArrows.Length;
				for (int k = 0; k < view.speedArrows.Length; k++)
				{
					((Graphic)view.speedArrows[k]).color = ((state.Status == "生产中" && k == num8) ? view.marqueeOnColor : view.marqueeOffColor);
				}
			}
			Player mainPlayer = GameMain.mainPlayer;
			if (flag && mainPlayer != null && !((ManualBehaviour)view.playerInventory).inited)
			{
				view.playerInventory.colCount = mainPlayer.GetPackageColumnCount();
				((ManualBehaviour)view.playerInventory)._Init((object)mainPlayer.package);
				((ManualBehaviour)view.playerInventory)._Open();
			}
			if (!flag && ((ManualBehaviour)view.playerInventory).inited)
			{
				((ManualBehaviour)view.playerInventory)._Free();
			}
			((Component)view.playerInventoryGroup).gameObject.SetActive(flag && mainPlayer != null);
			view.playerInventoryGroup.anchoredPosition = new Vector2(0f, (float)(-220 - num));
			float num9 = ((mainPlayer != null) ? ((float)(80 + mainPlayer.GetPackageColumnCount() * 50)) : ((RectTransform)((Component)UIRoot.instance.uiGame.assemblerWindow).transform).sizeDelta.x);
			ResizeWindow(new Vector2(num9, (float)((((ManualBehaviour)view.playerInventory).active ? (view.playerInventory.rowCount * 50 + 220) : 270) + (flag ? 40 : 0) + num)));
		});
		if (GameMain.mainPlayer != null)
		{
			if (((ManualBehaviour)view.servingBox).active)
			{
				((ManualBehaviour)view.servingBox)._Update();
			}
			if (((ManualBehaviour)view.playerInventory).active)
			{
				((ManualBehaviour)view.playerInventory)._Update();
			}
		}
	}

	internal static void Hide()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		FactoryRecipePicker.Close();
		if ((Object)(object)view != (Object)null)
		{
			savedTopLeft = Vector2.op_Implicit(((Transform)windowDrag.screenRect).InverseTransformPoint(TopLeft((RectTransform)((Component)owner).transform)));
			FreeServing();
			((ManualBehaviour)view.servingBox)._Destroy();
			((ManualBehaviour)view.playerInventory)._Destroy();
			((Component)view).gameObject.SetActive(false);
			Object.Destroy((Object)(object)((Component)view).gameObject);
			view = null;
			windowDrag = null;
			extraProducts.Clear();
		}
		if ((Object)(object)owner != (Object)null)
		{
			RectTransform val = (RectTransform)((Component)owner).transform;
			val.sizeDelta = originalSize;
			val.anchoredPosition = originalPosition;
		}
		foreach (KeyValuePair<GameObject, bool> item in hidden)
		{
			if ((Object)(object)item.Key != (Object)null)
			{
				item.Key.SetActive(item.Value);
			}
		}
		hidden.Clear();
		owner = null;
	}
}
[HarmonyPatch(typeof(UISpraycoaterWindow), "_OnUpdate")]
internal static class WindowUpdatePatch
{
	private static bool Prefix(UISpraycoaterWindow __instance)
	{
		if (FactoryWindow.Matches(__instance))
		{
			FactoryWindow.Refresh(__instance);
			return false;
		}
		FactoryWindow.Hide();
		return true;
	}
}
[HarmonyPatch(typeof(UISpraycoaterWindow), "_OnClose")]
internal static class WindowClosePatch
{
	private static void Prefix()
	{
		FactoryWindow.Hide();
	}
}
[BepInPlugin("com.komonad.dsp.sprayfactory", "Spray Factory", "0.1.1")]
[BepInDependency("dsp.common-api.CommonAPI", "1.6.7")]
[BepInDependency("me.xiaoye97.plugin.Dyson.LDBTool", "3.0.3")]
[BepInDependency("crecheng.DSPModSave", "1.2.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[CommonAPISubmoduleDependency(new string[] { "ProtoRegistry", "LocalizationModule" })]
public sealed class Plugin : BaseUnityPlugin, IModCanSave
{
	public const string Guid = "com.komonad.dsp.sprayfactory";

	internal static ManualLogSource Log;

	private Harmony harmony;

	private void Awake()
	{
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		LocalizationModule.RegisterTranslation("SprayFactory.Name", "Spray Factory", "喷涂工厂", "");
		LocalizationModule.RegisterTranslation("SprayFactory.Description", "A belt-fed recipe factory. The upper belt supplies materials; products enter the continuous lower belt. Working power: 300 kW.", "传送带配方工厂。上层传送带供料,产物送入下层贯穿传送带。工作功耗:300 kW。", "");
		LDBTool.PreAddDataAction = (Action)Delegate.Combine(LDBTool.PreAddDataAction, new Action(Prototypes.Register));
		LDBTool.PostAddDataAction = (Action)Delegate.Combine(LDBTool.PostAddDataAction, new Action(Prototypes.Finish));
		harmony = new Harmony("com.komonad.dsp.sprayfactory");
		harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Spray Factory loaded.");
	}

	private void OnDestroy()
	{
		FactoryIcon.Clear();
		RecipeColors.Clear();
		FactoryEffects.Clear();
		FactoryWindow.Hide();
		LDBTool.PreAddDataAction = (Action)Delegate.Remove(LDBTool.PreAddDataAction, new Action(Prototypes.Register));
		LDBTool.PostAddDataAction = (Action)Delegate.Remove(LDBTool.PostAddDataAction, new Action(Prototypes.Finish));
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}

	private void LateUpdate()
	{
		if (Prototypes.Ready)
		{
			PlanetFactory factory = GameMain.localPlanet?.factory;
			Camera main = GameCamera.main;
			FactoryEffects.Draw(factory, main);
		}
	}

	public void Export(BinaryWriter writer)
	{
		FactoryStore.Export(writer);
	}

	public void Import(BinaryReader reader)
	{
		FactoryStore.Import(reader);
	}

	public void IntoOthe