using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("Check")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace BUG_TerraGrid
{
internal sealed class AreaGrid
{
public readonly List<Vector3> Points = new List<Vector3>();
public readonly List<int> Indices = new List<int>();
public readonly List<int> Rows = new List<int>();
public readonly List<int> Columns = new List<int>();
public int RowCount { get; private set; }
public int ColumnCount { get; private set; }
public void Select(PlanetData planet, Vector3 from, Vector3 to, bool shortWay)
{
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
PlatformSystem platform = planet.factory.platformSystem;
platform.EnsureReformData();
Select(planet.aux.mainGrid.segment, platform.latitudeCount, planet.realRadius + 0.2f, from, to, shortWay, (float lat, float lon) => platform.GetReformIndexForSegment(lat, lon), platform.reformData.Length);
}
internal void Select(int segment, int latitudeCount, float radius, Vector3 from, Vector3 to, bool shortWay, Func<float, float, int> index, int indexCount)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
Points.Clear();
Indices.Clear();
Rows.Clear();
Columns.Clear();
RowCount = 0;
ColumnCount = 0;
float num = Turn(from);
float num2 = Turn(to);
float num3 = num;
float num4 = Mathf.Repeat(num2 - num, 1f);
if (num4 > 0.5f == shortWay)
{
num3 = num2;
num4 = 1f - num4;
}
int num5 = latitudeCount / 10 * 10;
int val = OddTenth(Latitude(from, segment));
int val2 = OddTenth(Latitude(to, segment));
for (int i = Math.Min(val, val2); i <= Math.Max(val, val2); i += 2)
{
if (Math.Abs(i) >= num5)
{
continue;
}
int num6 = PlanetGrid.DetermineLongitudeSegmentCount(Math.Abs(i) / 10, segment);
int num7 = num6 * 5;
int num8 = Column(num3, num7);
int num9 = Mod(Column(num3 + num4, num7) - num8, num7) + 1;
if (num4 * (float)num7 >= (float)(num7 - 1))
{
num9 = num7;
}
int num10 = 0;
for (int j = 0; j < num9; j++)
{
int num11 = 2 * Mod(num8 + j, num7) + 1 - num7;
int num12 = index((float)i / 10f, (float)num11 / 10f);
if (num12 >= 0 && num12 < indexCount)
{
Points.Add(Surface((float)i / 10f / (float)segment, (float)num11 / 10f / (float)num6, radius));
Indices.Add(num12);
Rows.Add(RowCount);
Columns.Add(num10++);
}
}
if (num10 != 0)
{
RowCount++;
ColumnCount = Math.Max(ColumnCount, num10);
}
}
}
public long BlockKey(int i, int size)
{
return ((long)(Rows[i] / size) << 32) | (uint)(Columns[i] / size);
}
public static long TileKey(int segment, Vector3 p)
{
//IL_0000: 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)
int num = OddTenth(Latitude(p, segment));
return ((long)num << 32) | (uint)Column(ring: PlanetGrid.DetermineLongitudeSegmentCount(Math.Abs(num) / 10, segment) * 5, turn: Turn(p));
}
private static float Turn(Vector3 p)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
return Mathf.Atan2(p.x, 0f - p.z) / ((float)Math.PI * 2f);
}
private static float Latitude(Vector3 p, int segment)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
return Mathf.Asin(Mathf.Clamp(((Vector3)(ref p)).normalized.y, -1f, 1f)) / ((float)Math.PI * 2f) * (float)segment;
}
private static int OddTenth(float segments)
{
float num = segments * 10f;
float num2 = Mathf.Round(num);
int num3 = (int)Mathf.Abs(num2);
if (num3 % 2 != 1)
{
num3 = Mathf.FloorToInt(Mathf.Abs(num));
if (num3 % 2 != 1)
{
num3++;
}
}
if (!(num2 >= 0f))
{
return -num3;
}
return num3;
}
private static int Column(float turn, int ring)
{
return Mod((OddTenth(Mathf.Repeat(turn + 0.5f, 1f) * (float)ring / 5f - (float)ring / 10f) + ring - 1) / 2, ring);
}
private static int Mod(int x, int m)
{
return (x % m + m) % m;
}
private static Vector3 Surface(float latTurns, float lonTurns, float radius)
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
float num = latTurns * 2f * (float)Math.PI;
float num2 = lonTurns * 2f * (float)Math.PI;
return new Vector3(Mathf.Cos(num) * Mathf.Sin(num2), Mathf.Sin(num), (0f - Mathf.Cos(num)) * Mathf.Cos(num2)) * radius;
}
}
[HarmonyPatch(typeof(BuildTool_Reform))]
internal static class AreaTool
{
private static readonly AreaGrid Area = new AreaGrid();
private static BuildTool_Reform? _tool;
private static Vector3[]? _savedPoints;
private static int[]? _savedIndices;
private static int _savedSize;
private static int _shownSize;
private static Vector3[] _points = (Vector3[])(object)new Vector3[400];
private static int[] _indices = new int[400];
private static Vector3? _corner;
private static bool _on;
private static (PlanetData?, long, long, bool) _lastKey;
public static bool On
{
get
{
return _on;
}
set
{
if (!value)
{
Release();
}
_on = value;
}
}
public static bool ShortWay { get; set; } = true;
[HarmonyPrefix]
[HarmonyPatch("UpdateBrushMode")]
private static bool UpdateBrushMode(BuildTool_Reform __instance, Vector3 currentCastPos)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
if (!_on)
{
return true;
}
Hover(__instance, currentCastPos);
return false;
}
[HarmonyPrefix]
[HarmonyPatch("_OnClose")]
private static void OnClose(BuildTool_Reform __instance)
{
if (__instance == _tool)
{
Release();
}
}
[HarmonyPrefix]
[HarmonyPatch("_OnFree")]
private static void OnFree(BuildTool_Reform __instance)
{
if (__instance == _tool)
{
Release();
}
}
private static void Hover(BuildTool_Reform tool, Vector3 cursor)
{
//IL_0076: 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_0082: 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_00b1: 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_00ed: 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_017e: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
if (_tool != tool)
{
Release();
_tool = tool;
_savedPoints = tool.cursorPoints;
_savedIndices = tool.cursorIndices;
_savedSize = (_shownSize = tool.brushSize);
}
if (tool.brushSize != _shownSize)
{
_savedSize = tool.brushSize;
}
int segment = ((BuildTool)tool).planet.aux.mainGrid.segment;
(PlanetData, long, long, bool) lastKey = (((BuildTool)tool).planet, AreaGrid.TileKey(segment, _corner ?? cursor), AreaGrid.TileKey(segment, cursor), ShortWay);
if (!lastKey.Equals(_lastKey))
{
Area.Select(((BuildTool)tool).planet, _corner ?? cursor, cursor, ShortWay);
_lastKey = lastKey;
}
int count = Area.Points.Count;
Show(tool, count, (count > 0) ? Area.Points[count / 2] : cursor);
string text = (_corner.HasValue ? Text.Selected(Area.ColumnCount, Area.RowCount, count) : "Click the first corner");
if (!ShortWay)
{
text += " — long way around";
}
PaintJob current = PaintJob.Current;
if (current != null)
{
text = Text.Painting(current.Done, current.Total, PaintJob.Paused) + "\n" + text;
}
((BuildTool)tool).actionBuild.model.cursorText = text;
UICursor.SetCursor((ECursor)8);
if (VFInput._buildConfirm.onDown && !VFInput.onGUI)
{
if (!_corner.HasValue)
{
_corner = cursor;
}
else if (PaintJob.Start(tool, Area, Brush.Capture(tool)))
{
_corner = null;
}
}
}
private static void Show(BuildTool_Reform tool, int count, Vector3 center)
{
//IL_009f: 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)
int num = Math.Max(1, (int)Math.Ceiling(Math.Sqrt(count)));
int num2 = num * num;
if (_indices.Length < num2)
{
_indices = new int[num2];
_points = (Vector3[])(object)new Vector3[num2];
}
Area.Points.CopyTo(_points);
Area.Indices.CopyTo(_indices);
for (int i = count; i < num2; i++)
{
_indices[i] = -1;
}
tool.cursorPoints = _points;
tool.cursorIndices = _indices;
tool.cursorPointCount = count;
tool.brushSize = (_shownSize = num);
tool.reformCenterPoint = center;
}
private static void Release()
{
_corner = null;
if (_tool != null)
{
_tool.cursorPoints = _savedPoints;
_tool.cursorIndices = _savedIndices;
_tool.brushSize = _savedSize;
_tool.cursorPointCount = 0;
for (int i = 0; i < _tool.cursorIndices.Length; i++)
{
_tool.cursorIndices[i] = -1;
}
}
_tool = null;
_savedPoints = null;
_savedIndices = null;
ShortWay = true;
_lastKey = default((PlanetData, long, long, bool));
}
}
internal readonly struct Brush
{
public readonly int Mode;
public readonly int Color;
public readonly int Type;
public readonly bool Bury;
public readonly ItemProto? Item;
public Brush(int mode, int color, int type, bool bury, ItemProto? item)
{
Mode = mode;
Color = color;
Type = type;
Bury = bury;
Item = item;
}
public static Brush Capture(BuildTool_Reform tool)
{
return new Brush(tool.reformMode, tool.brushColor, tool.brushType, tool.buryVeins, tool.handItem);
}
}
internal static class GameReform
{
private static readonly MethodInfo Prepare = AccessTools.Method(typeof(BuildTool_Reform), "PrepareBrushPoints", (Type[])null, (Type[])null);
private static readonly MethodInfo Flatten = AccessTools.Method(typeof(BuildTool_Reform), "DoFlattenExecute", (Type[])null, (Type[])null);
private static readonly MethodInfo Restore = AccessTools.Method(typeof(BuildTool_Reform), "DoRestoreExecute", (Type[])null, (Type[])null);
private static readonly FieldInfo Pit = AccessTools.Field(typeof(BuildTool_Reform), "removeBasePitRuinId");
private static readonly FieldInfo Line = AccessTools.Field(typeof(BuildTool_Reform), "lineDrawingMode");
private static readonly FieldInfo Package = AccessTools.Field(typeof(BuildTool), "tmpPackage");
private static readonly MethodInfo HandCount = AccessTools.PropertySetter(typeof(Player), "inhandItemCount");
private static readonly MethodInfo HandInc = AccessTools.PropertySetter(typeof(Player), "inhandItemInc");
private const float Radius = 0.990946f;
internal static string? Measure(BuildTool_Reform tool, Brush brush, List<List<Vector3>> blocks, out int tiles, out long sand)
{
Player player = ((BuildTool)tool).player;
long cost = 0L;
long gain = 0L;
int count = 0;
int items = 0;
List<Vector3> snapped = new List<Vector3>();
string text = WithBrush(tool, brush, delegate
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: 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_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_0157: Unknown result type (might be due to invalid IL or missing references)
//IL_0175: 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)
foreach (List<Vector3> block in blocks)
{
snapped.Clear();
foreach (Vector3 item in block)
{
Snap(tool, item);
if ((int)Pit.GetValue(tool) != 0)
{
return "A Dark Fog base pit is in the selection; remove it with the normal foundation brush first.";
}
if (tool.cursorIndices[0] >= 0)
{
count++;
if (brush.Mode == 1)
{
int cost2 = 0;
int gain2 = 0;
Compute(tool, 0.990946f, ref cost2, ref gain2);
cost += cost2;
gain += gain2;
}
else
{
items += tool.cursorPointCount;
for (int i = 0; i < tool.cursorPointCount; i++)
{
snapped.Add(tool.cursorPoints[i]);
}
}
}
}
if (snapped.Count > 0)
{
float radius;
Vector3 val = Center(block, out radius);
int num2 = 0;
int num3 = 0;
((BuildTool)tool).factory.ComputeFlattenTerrainReform(snapped.ToArray(), val, radius, snapped.Count, ref num2, ref num3, 3f, 1f);
cost += num2;
gain += num3;
}
}
return (string)null;
});
tiles = count;
sand = 0L;
if (text != null || count == 0)
{
return text;
}
if (brush.Mode == 1)
{
sand = cost - gain;
}
else
{
if (brush.Item == null)
{
return "Pick a foundation first.";
}
int id = ((Proto)brush.Item).ID;
int num = ItemCount(player, id) + ((player.inhandItemId == id) ? player.inhandItemCount : 0);
if (num < items)
{
return Text.LackOfItems(items, num);
}
sand = WithHandGuard(player, id, (Func<long>)delegate
{
CopyPackage(tool);
return tool.GetNeedSandCountByInc(id, items, Clamp(cost), Clamp(gain));
});
if (GameMain.data.history.HasFeatureKey(1100001) && GameMain.sandboxToolsEnabled)
{
sand = 0L;
}
}
if (sand > player.sandCount)
{
return Text.NotEnoughSoil(sand, player.sandCount);
}
return null;
}
internal static bool Apply(BuildTool_Reform tool, Brush brush, List<Vector3> block)
{
return WithBrush(tool, brush, delegate
{
//IL_0043: 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_0050: 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_01bf: Unknown result type (might be due to invalid IL or missing references)
//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
List<Vector3> list = new List<Vector3>(block.Count);
List<int> list2 = new List<int>(block.Count);
foreach (Vector3 item in block)
{
Snap(tool, item);
if ((int)Pit.GetValue(tool) != 0)
{
UIRealtimeTip.Popup("A Dark Fog base pit is in the selection; remove it with the normal foundation brush first.", true, 0);
return false;
}
if (tool.cursorIndices[0] >= 0)
{
list2.Add(tool.cursorIndices[0]);
for (int i = 0; i < tool.cursorPointCount; i++)
{
list.Add(tool.cursorPoints[i]);
}
}
}
if (list2.Count == 0)
{
return true;
}
int num = (int)Math.Ceiling(Math.Sqrt(list2.Count));
int num2 = Math.Max(100, Math.Max(num * num, list.Count));
tool.cursorPoints = (Vector3[])(object)new Vector3[num2];
list.CopyTo(tool.cursorPoints);
tool.cursorIndices = new int[num2];
for (int j = 0; j < num2; j++)
{
tool.cursorIndices[j] = ((j < list2.Count) ? list2[j] : (-1));
}
tool.cursorPointCount = list.Count;
tool.brushSize = num;
tool.reformCenterPoint = Center(block, out var radius);
int cost = 0;
int gain = 0;
Compute(tool, radius, ref cost, ref gain);
if (brush.Mode == 1)
{
return Execute(tool, Restore, radius, cost - gain);
}
if (brush.Item == null)
{
return false;
}
Player player = ((BuildTool)tool).player;
return WithHandGuard(player, ((Proto)brush.Item).ID, delegate
{
TopUp(player, ((Proto)brush.Item).ID, tool.cursorPointCount - player.inhandItemCount);
if (NativeCount(player, ((Proto)brush.Item).ID) + player.inhandItemCount < tool.cursorPointCount)
{
UIRealtimeTip.Popup(Text.LackOfItem, true, 1);
return false;
}
CopyPackage(tool);
int need = tool.GetNeedSandCountByInc(((Proto)brush.Item).ID, tool.cursorPointCount, cost, gain);
if (GameMain.data.history.HasFeatureKey(1100001) && GameMain.sandboxToolsEnabled)
{
need = 0;
}
return Execute(tool, Flatten, radius, need);
});
});
}
private static MethodInfo? DeliveryCount()
{
return Harmony.GetPatchInfo((MethodBase)Flatten)?.Transpilers.Select((Patch p) => p.PatchMethod.DeclaringType?.GetMethod("GetItemCount", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
{
typeof(StorageComponent),
typeof(int)
}, null)).FirstOrDefault((MethodInfo m) => m != null && m.ReturnType == typeof(int));
}
private static int NativeCount(Player player, int itemId)
{
MethodInfo methodInfo = DeliveryCount();
if (!(methodInfo == null))
{
return (int)methodInfo.Invoke(null, new object[2] { player.package, itemId });
}
return player.package.GetItemCount(itemId);
}
internal static int ItemCount(Player player, int itemId)
{
int num = NativeCount(player, itemId);
int num2;
if (DeliveryCount() == null)
{
DeliveryPackage deliveryPackage = player.deliveryPackage;
if (deliveryPackage != null && deliveryPackage.unlocked)
{
num2 = deliveryPackage.GetItemCount(itemId);
goto IL_0030;
}
}
num2 = 0;
goto IL_0030;
IL_0030:
return num + num2;
}
private static void TopUp(Player player, int itemId, int need)
{
DeliveryPackage deliveryPackage = player.deliveryPackage;
if (DeliveryCount() != null || deliveryPackage == null || !deliveryPackage.unlocked)
{
return;
}
int num = need - player.package.GetItemCount(itemId);
int num4 = default(int);
int num6 = default(int);
int num7 = default(int);
while (num > 0)
{
int num2 = itemId;
int num3 = num;
deliveryPackage.TakeItems(ref num2, ref num3, ref num4);
if (num2 != itemId || num3 <= 0)
{
break;
}
int num5 = player.package.AddItemStacked(itemId, num3, num4, ref num6);
if (num5 < num3)
{
deliveryPackage.AddItem(itemId, num3 - num5, num6, ref num7);
break;
}
num -= num5;
}
}
private static bool Execute(BuildTool_Reform tool, MethodInfo action, float radius, int need)
{
if (((BuildTool)tool).player.sandCount - need < 0)
{
UIRealtimeTip.Popup(Text.NotEnoughSoilPile, true, 0);
return false;
}
action.Invoke(tool, new object[3] { radius, need, true });
return true;
}
private static void Compute(BuildTool_Reform tool, float radius, ref int cost, ref int gain)
{
//IL_0054: 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)
if (tool.reformMode == 1)
{
((BuildTool)tool).factory.ComputeRestoreTerrainReform(tool.cursorPoints, tool.cursorIndices, tool.brushSize * tool.brushSize, tool.reformCenterPoint, radius, tool.cursorPointCount, ref cost, ref gain, 3f, 1f);
}
else
{
((BuildTool)tool).factory.ComputeFlattenTerrainReform(tool.cursorPoints, tool.reformCenterPoint, radius, tool.cursorPointCount, ref cost, ref gain, 3f, 1f);
}
}
internal static Vector3 Center(List<Vector3> points, out float radius)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: 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_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: 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_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: 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_0051: 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_0068: 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_0070: 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_0073: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = Vector3.zero;
foreach (Vector3 point in points)
{
val += point;
}
Vector3 normalized = ((Vector3)(ref val)).normalized;
Vector3 val2 = points[0];
Vector3 val3 = normalized * ((Vector3)(ref val2)).magnitude;
float num = 0f;
foreach (Vector3 point2 in points)
{
float val4 = num;
val2 = point2 - val3;
num = Math.Max(val4, ((Vector3)(ref val2)).magnitude);
}
radius = num + 0.990946f;
return val3;
}
private static void CopyPackage(BuildTool_Reform tool)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Expected O, but got Unknown
StorageComponent val = (StorageComponent)Package.GetValue(tool);
if (val == null || val.size != ((BuildTool)tool).player.package.size)
{
val = new StorageComponent(((BuildTool)tool).player.package.size);
Package.SetValue(tool, val);
}
Array.Copy(((BuildTool)tool).player.package.grids, val.grids, val.size);
}
private static int Clamp(long value)
{
return (int)Math.Max(-2147483648L, Math.Min(2147483647L, value));
}
private static T WithBrush<T>(BuildTool_Reform tool, Brush brush, Func<T> body)
{
//IL_001d: 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_010e: 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)
Vector3[] cursorPoints = tool.cursorPoints;
int[] cursorIndices = tool.cursorIndices;
int cursorPointCount = tool.cursorPointCount;
int brushSize = tool.brushSize;
Vector3 reformCenterPoint = tool.reformCenterPoint;
int num = (int)Line.GetValue(tool);
int reformMode = tool.reformMode;
int brushColor = tool.brushColor;
int brushType = tool.brushType;
bool buryVeins = tool.buryVeins;
ItemProto handItem = tool.handItem;
try
{
tool.cursorPoints = (Vector3[])(object)new Vector3[100];
tool.cursorIndices = new int[100];
for (int i = 0; i < 100; i++)
{
tool.cursorIndices[i] = -1;
}
tool.brushSize = 1;
Line.SetValue(tool, 0);
tool.reformMode = brush.Mode;
tool.brushColor = brush.Color;
tool.brushType = brush.Type;
tool.buryVeins = brush.Bury;
tool.handItem = brush.Item;
return body();
}
finally
{
tool.cursorPoints = cursorPoints;
tool.cursorIndices = cursorIndices;
tool.cursorPointCount = cursorPointCount;
tool.brushSize = brushSize;
tool.reformCenterPoint = reformCenterPoint;
Line.SetValue(tool, num);
tool.reformMode = reformMode;
tool.brushColor = brushColor;
tool.brushType = brushType;
tool.buryVeins = buryVeins;
tool.handItem = handItem;
}
}
private static void Snap(BuildTool_Reform tool, Vector3 point)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
tool.cursorIndices[0] = -1;
Prepare.Invoke(tool, new object[1] { point });
}
private static T WithHandGuard<T>(Player player, int itemId, Func<T> body)
{
if (player.inhandItemId == itemId || player.inhandItemCount == 0)
{
return body();
}
int inhandItemCount = player.inhandItemCount;
int inhandItemInc = player.inhandItemInc;
HandCount.Invoke(player, new object[1] { 0 });
HandInc.Invoke(player, new object[1] { 0 });
try
{
return body();
}
finally
{
HandCount.Invoke(player, new object[1] { inhandItemCount });
HandInc.Invoke(player, new object[1] { inhandItemInc });
}
}
}
internal sealed class PaintJob
{
public readonly PlanetFactory Factory;
public readonly List<List<Vector3>> Blocks = new List<List<Vector3>>();
public readonly List<Vector3> Centers = new List<Vector3>();
public readonly List<Brush> Brushes = new List<Brush>();
public int Total;
public int Done;
private bool _waiting;
public static PaintJob? Current { get; private set; }
public static bool Paused { get; set; }
public static int BlockSize { get; set; } = 12;
public PaintJob(PlanetFactory factory)
{
Factory = factory;
}
public void Add(Brush brush, List<List<Vector3>> blocks, int count)
{
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
HashSet<Vector3> hashSet = new HashSet<Vector3>();
foreach (List<Vector3> block in blocks)
{
hashSet.UnionWith(block);
}
float radius;
for (int num = Blocks.Count - 1; num >= 0; num--)
{
int num2 = Blocks[num].RemoveAll(hashSet.Contains);
if (num2 != 0)
{
Total -= num2;
if (Blocks[num].Count == 0)
{
Blocks.RemoveAt(num);
Centers.RemoveAt(num);
Brushes.RemoveAt(num);
}
else
{
Centers[num] = GameReform.Center(Blocks[num], out radius);
}
}
}
foreach (List<Vector3> block2 in blocks)
{
Blocks.Add(block2);
Centers.Add(GameReform.Center(block2, out radius));
Brushes.Add(brush);
}
Total += count;
_waiting = false;
}
public static bool Start(BuildTool_Reform tool, AreaGrid area, Brush brush)
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_01de: Unknown result type (might be due to invalid IL or missing references)
int num = ((brush.Mode == 1) ? Math.Min(BlockSize, 10) : BlockSize);
int size = Math.Max(24, num);
List<Vector3> list = new List<Vector3>();
List<long> list2 = new List<long>();
List<long> list3 = new List<long>();
HashSet<int> hashSet = new HashSet<int>();
for (int i = 0; i < area.Points.Count; i++)
{
if (hashSet.Add(area.Indices[i]))
{
list.Add(area.Points[i]);
list2.Add(area.BlockKey(i, num));
list3.Add(area.BlockKey(i, size));
}
}
int tiles;
long sand;
string text = GameReform.Measure(tool, brush, Split(list, list3), out tiles, out sand);
ManualLogSource? log = Plugin.Log;
if (log != null)
{
log.LogInfo((object)($"Area: {list.Count} tiles ({tiles} to paint), mode {brush.Mode}, item {((Proto)(brush.Item?)).ID ?? 0}, soil ~{sand} of {((BuildTool)tool).player.sandCount}" + ((text != null) ? (", refused: " + text) : "")));
}
if (text != null)
{
UIRealtimeTip.Popup(text, true, 0);
return false;
}
if (tiles == 0)
{
return true;
}
List<List<Vector3>> blocks = Split(list, list2);
if (Current != null && Current.Factory == ((BuildTool)tool).factory)
{
Current.Add(brush, blocks, list.Count);
Tick();
return true;
}
Current = new PaintJob(((BuildTool)tool).factory);
Current.Add(brush, blocks, list.Count);
((BuildTool)tool).player.ClearOrders();
((BuildTool)tool).controller.actionMine.miningType = (EObjectType)0;
((BuildTool)tool).controller.actionMine.miningId = 0;
((BuildTool)tool).controller.actionMine.miningTick = 0;
GameScenarioLogic gameScenario = GameMain.gameScenario;
if (gameScenario != null)
{
gameScenario.NotifyOnDoReformOpt(1);
}
Tick();
return true;
}
internal static List<List<Vector3>> Split(IList<Vector3> points, IList<long> keys)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
List<List<Vector3>> list = new List<List<Vector3>>();
Dictionary<long, List<Vector3>> dictionary = new Dictionary<long, List<Vector3>>();
for (int i = 0; i < points.Count; i++)
{
if (!dictionary.TryGetValue(keys[i], out var value))
{
value = new List<Vector3>();
dictionary[keys[i]] = value;
list.Add(value);
}
value.Add(points[i]);
}
return list;
}
public static void Tick()
{
//IL_00ba: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
PaintJob current = Current;
if (current == null)
{
return;
}
Player mainPlayer = GameMain.mainPlayer;
if (GameMain.data == null || mainPlayer == null)
{
Stop(notify: false, null);
return;
}
PendingTiles.Draw(current.Factory.planet, current.Blocks);
if (GameMain.isPaused || Paused)
{
return;
}
BuildTool_Reform val = mainPlayer.controller?.actionBuild?.reformTool;
if (val == null || mainPlayer.factory != current.Factory || ((BuildTool)val).factory != current.Factory)
{
Stop(notify: true, "Area painting stopped: you left the planet.");
return;
}
try
{
int num = -1;
float num2 = mainPlayer.mecha.buildArea * mainPlayer.mecha.buildArea;
for (int i = 0; i < current.Centers.Count; i++)
{
Vector3 val2 = current.Centers[i] - mainPlayer.position;
float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
if (sqrMagnitude <= num2)
{
num2 = sqrMagnitude;
num = i;
}
}
if (num < 0)
{
if (!current._waiting)
{
UIRealtimeTip.Popup(Text.OutOfRange, true, 0);
}
current._waiting = true;
return;
}
current._waiting = false;
List<Vector3> list = current.Blocks[num];
Brush brush = current.Brushes[num];
current.Blocks.RemoveAt(num);
current.Centers.RemoveAt(num);
current.Brushes.RemoveAt(num);
if (!GameReform.Apply(val, brush, list))
{
Stop(notify: true, null);
return;
}
current.Done += list.Count;
if (current.Blocks.Count == 0)
{
Stop(notify: true, (current.Done > list.Count) ? Text.Complete(current.Done) : null);
}
}
catch (Exception ex)
{
Stop(notify: true, "Area painting stopped; see the BepInEx log.");
ManualLogSource? log = Plugin.Log;
if (log != null)
{
log.LogError((object)ex);
}
}
}
public static void Cancel()
{
if (Current != null)
{
Stop(notify: true, "Area painting cancelled.");
}
}
private static void Stop(bool notify, string? message)
{
Current = null;
Paused = false;
PendingTiles.Clear();
if (notify)
{
GameScenarioLogic gameScenario = GameMain.gameScenario;
if (gameScenario != null)
{
gameScenario.NotifyOnDoReformOpt(2);
}
}
if (message != null)
{
UIRealtimeTip.Popup(message, true, 0);
}
}
}
internal static class PendingTiles
{
private static readonly Color Tint = new Color(0.35f, 0.85f, 1f);
private static Mesh? _mesh;
private static Material? _material;
private static bool _noShader;
private static int _shownBlocks = -1;
private static float _builtAt;
internal static bool Enabled { get; set; } = true;
internal static void Draw(PlanetData planet, List<List<Vector3>> blocks)
{
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Expected O, but got Unknown
//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
if (!Enabled || blocks.Count == 0 || planet != GameMain.localPlanet || planet.data == null || !Ready())
{
return;
}
if ((Object)(object)_mesh == (Object)null || (_shownBlocks != blocks.Count && Time.unscaledTime - _builtAt > 0.25f))
{
List<Vector3> list = new List<Vector3>();
List<int> list2 = new List<int>();
float floor = planet.realRadius + 0.2f;
float num = (float)Math.PI * 2f * planet.realRadius / ((float)planet.factory.platformSystem.segment * 5f);
Build(blocks, num * 0.42f, (Vector3 p) => Math.Max(planet.data.QueryModifiedHeight(p), floor) + 0.15f, list, list2);
if (_mesh == null)
{
_mesh = new Mesh
{
indexFormat = (IndexFormat)1
};
}
_mesh.Clear();
_mesh.SetVertices(list);
Color[] array = (Color[])(object)new Color[list.Count];
for (int num2 = 0; num2 < array.Length; num2++)
{
array[num2] = Color.white;
}
_mesh.colors = array;
_mesh.SetTriangles(list2, 0);
_mesh.RecalculateBounds();
_shownBlocks = blocks.Count;
_builtAt = Time.unscaledTime;
}
_material.color = new Color(Tint.r, Tint.g, Tint.b, 0.3f + 0.15f * Mathf.Sin(Time.unscaledTime * 4f));
Graphics.DrawMesh(_mesh, Matrix4x4.identity, _material, 0, (Camera)null, 0, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false);
}
internal static void Clear()
{
if ((Object)(object)_mesh != (Object)null)
{
Object.Destroy((Object)(object)_mesh);
}
_mesh = null;
_shownBlocks = -1;
}
private static bool Ready()
{
//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_006d: Expected O, but got Unknown
if ((Object)(object)_material != (Object)null)
{
return true;
}
if (_noShader)
{
return false;
}
Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("UI/Default");
if ((Object)(object)val == (Object)null)
{
_noShader = true;
ManualLogSource? log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)"No transparent shader found; pending blocks are not highlighted");
}
return false;
}
_material = new Material(val)
{
renderQueue = 3000
};
return true;
}
internal static void Build(List<List<Vector3>> blocks, float half, Func<Vector3, float> height, List<Vector3> vertices, List<int> triangles)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: 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_002d: 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_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: 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_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: 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_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_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: 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_0084: 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_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: 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_00ad: 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_00ba: 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_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: 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_00df: 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)
foreach (List<Vector3> block in blocks)
{
foreach (Vector3 item in block)
{
Vector3 current = item;
Vector3 normalized = ((Vector3)(ref current)).normalized;
Vector3 val = Vector3.Cross(Vector3.up, normalized);
val = ((((Vector3)(ref val)).sqrMagnitude < 1E-06f) ? Vector3.right : ((Vector3)(ref val)).normalized);
Vector3 val2 = Vector3.Cross(normalized, val);
Vector3 val3 = normalized * height(current);
int count = vertices.Count;
vertices.Add(val3 + (-val - val2) * half);
vertices.Add(val3 + (val - val2) * half);
vertices.Add(val3 + (val + val2) * half);
vertices.Add(val3 + (-val + val2) * half);
triangles.Add(count);
triangles.Add(count + 1);
triangles.Add(count + 2);
triangles.Add(count);
triangles.Add(count + 2);
triangles.Add(count + 3);
}
}
}
}
[BepInPlugin("bug.dsp.terragrid", "BUG_TerraGrid", "1.0.0")]
[BepInIncompatibility("ExcelDsp.Painter")]
public class Plugin : BaseUnityPlugin
{
public const string Guid = "bug.dsp.terragrid";
public const string Name = "BUG_TerraGrid";
public const string Version = "1.0.0";
internal static ManualLogSource? Log;
private Harmony? _harmony;
private ConfigEntry<KeyboardShortcut>? _areaKey;
private ConfigEntry<KeyboardShortcut>? _wayKey;
private ConfigEntry<KeyboardShortcut>? _cancelKey;
private ConfigEntry<KeyboardShortcut>? _pauseKey;
public void Awake()
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: 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_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Expected O, but got Unknown
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_016c: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
_areaKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "AreaMode", KeyboardShortcut.Deserialize("D + LeftControl"), "Turn area mode of the foundation tool on or off (off also closes the tool)");
_wayKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "LongWayAround", KeyboardShortcut.Deserialize("P + LeftControl"), "Between the two corners, go the short way or the long way around the planet");
_cancelKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "Cancel", KeyboardShortcut.Deserialize("D + LeftControl + LeftShift"), "Cancel the painting in progress");
_pauseKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "PauseResume", KeyboardShortcut.Deserialize("P + LeftControl + LeftShift"), "Pause or resume the painting in progress");
ConfigEntry<int> blockSize = ((BaseUnityPlugin)this).Config.Bind<int>("Painting", "BlockSize", 12, new ConfigDescription("Areas are painted in BlockSize x BlockSize blocks, one block per frame. Larger is faster but each frame does more work (restore: at most 10)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()));
ConfigEntry<bool> pending = ((BaseUnityPlugin)this).Config.Bind<bool>("Painting", "ShowPendingTiles", true, "Mark tiles still to be painted (for example out of mecha range) with blue squares");
PaintJob.BlockSize = blockSize.Value;
blockSize.SettingChanged += delegate
{
PaintJob.BlockSize = blockSize.Value;
};
PendingTiles.Enabled = pending.Value;
pending.SettingChanged += delegate
{
PendingTiles.Enabled = pending.Value;
};
_harmony = new Harmony("bug.dsp.terragrid");
_harmony.PatchAll(typeof(Plugin).Assembly);
((BaseUnityPlugin)this).Logger.LogInfo((object)"BUG_TerraGrid 1.0.0 loaded");
}
public void OnDestroy()
{
AreaTool.On = false;
Harmony? harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
_harmony = null;
}
public void Update()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: 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)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
KeyboardShortcut value = _cancelKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
PaintJob.Cancel();
}
else
{
value = _areaKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
AreaTool.On = !AreaTool.On;
if (!AreaTool.On)
{
CloseTool();
}
UIRealtimeTip.Popup(Text.Mode(AreaTool.On), false, 0);
}
}
value = _pauseKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
if (PaintJob.Current != null)
{
PaintJob.Paused = !PaintJob.Paused;
UIRealtimeTip.Popup(Text.Paused(PaintJob.Paused), false, 0);
}
}
else
{
value = _wayKey.Value;
if (((KeyboardShortcut)(ref value)).IsDown() && AreaTool.On)
{
AreaTool.ShortWay = !AreaTool.ShortWay;
UIRealtimeTip.Popup(Text.Way(AreaTool.ShortWay), false, 0);
}
}
PaintJob.Tick();
}
private static void CloseTool()
{
Player mainPlayer = GameMain.mainPlayer;
BuildTool_Reform val = ((mainPlayer == null) ? null : mainPlayer.controller?.actionBuild?.reformTool);
if (val != null && ((BuildTool)val).active)
{
mainPlayer.SetHandItems(0, 0, 0);
((BuildTool)val)._Close();
}
}
}
internal static class Text
{
public const string SelectStart = "Click the first corner";
public const string PitInSelection = "A Dark Fog base pit is in the selection; remove it with the normal foundation brush first.";
public const string SelectFoundation = "Pick a foundation first.";
public const string Cancelled = "Area painting cancelled.";
public const string LeftPlanet = "Area painting stopped: you left the planet.";
public const string Failed = "Area painting stopped; see the BepInEx log.";
public const string LongPath = "long way around";
public static string LackOfItem => Localization.Translate("物品不足");
public static string NotEnoughSoilPile => Localization.Translate("沙土不足");
public static string OutOfRange => Localization.Translate("目标超出范围") + " — painting continues when you get close to the blue squares.";
public static string Mode(bool on)
{
if (!on)
{
return "Area painting off";
}
return "Area painting on";
}
public static string Way(bool shortest)
{
if (!shortest)
{
return "Long way around the planet";
}
return "Short way between corners";
}
public static string Paused(bool paused)
{
if (!paused)
{
return "Area painting resumed";
}
return "Area painting paused";
}
public static string Selected(int columns, int rows, int count)
{
return $"Selected: {columns} × {rows} ({count} tiles)";
}
public static string Painting(int done, int total, bool paused)
{
return $"Painting: {done}/{total} ({((total > 0) ? (done * 100 / total) : 0)}%)" + (paused ? " (paused)" : "");
}
public static string Complete(int tiles)
{
return $"Area painting done: {tiles} tiles.";
}
public static string LackOfItems(int need, int have)
{
return $"{LackOfItem} — need {need}, have {have}.";
}
public static string NotEnoughSoil(long need, long have)
{
return $"{NotEnoughSoilPile} — need ≈{need}, have {have}.";
}
}
}