using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[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 VeinsUtilizationBoosterMod
{
[BepInPlugin("godvector.dysonsphereprogram.veinsutilizationbooster", "VeinsUtilizationBooster", "1.4.0")]
[BepInProcess("DSPGAME.exe")]
public sealed class VeinsUtilizationBoosterPlugin : BaseUnityPlugin
{
public const string PluginGuid = "godvector.dysonsphereprogram.veinsutilizationbooster";
public const string PluginName = "VeinsUtilizationBooster";
public const string PluginVersion = "1.4.0";
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<int> TargetLevel;
internal static ConfigEntry<int> TechIdOverride;
private GameHistoryData _lastHistory;
private bool _applied;
private float _nextCheck;
private void Awake()
{
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the Veins Utilization booster.");
TargetLevel = ((BaseUnityPlugin)this).Config.Bind<int>("General", "TargetLevel", 10000, new ConfigDescription("Target Veins Utilization level. Default is 10000. Values are clamped to the repeatable technology's current MaxLevel, including limits raised by other mods.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(6, 1000000000), Array.Empty<object>()));
TechIdOverride = ((BaseUnityPlugin)this).Config.Bind<int>("Advanced", "TechIdOverride", 0, "0 = automatic detection. Only change this for troubleshooting.");
((BaseUnityPlugin)this).Logger.LogInfo((object)"VeinsUtilizationBooster 1.4.0 loaded.");
}
private void Update()
{
if (!Enabled.Value || Time.realtimeSinceStartup < _nextCheck)
{
return;
}
_nextCheck = Time.realtimeSinceStartup + 1f;
GameHistoryData history = GameMain.history;
if (history == null)
{
_lastHistory = null;
_applied = false;
return;
}
if (history != _lastHistory)
{
_lastHistory = history;
_applied = false;
}
if (_applied || (Object)(object)LDB.techs == (Object)null || ((ProtoSet<TechProto>)(object)LDB.techs).dataArray == null || history.techStates == null)
{
return;
}
try
{
Apply(history);
_applied = true;
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)"Veins Utilization synchronization failed.");
((BaseUnityPlugin)this).Logger.LogError((object)ex);
_nextCheck = Time.realtimeSinceStartup + 3f;
}
}
private void Apply(GameHistoryData history)
{
//IL_0212: Unknown result type (might be due to invalid IL or missing references)
//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0304: Unknown result type (might be due to invalid IL or missing references)
//IL_0231: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0418: Unknown result type (might be due to invalid IL or missing references)
//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
//IL_0521: Unknown result type (might be due to invalid IL or missing references)
//IL_052e: Unknown result type (might be due to invalid IL or missing references)
List<TechProto> list = FindCandidates();
if (list.Count == 0)
{
throw new Exception("Veins Utilization technology could not be detected.");
}
TechProto val = SelectRepeatable(list);
if (val == null)
{
throw new Exception("Repeatable Veins Utilization technology could not be selected.");
}
int iD = ((Proto)val).ID;
int maxLevel = val.MaxLevel;
if (maxLevel < 6)
{
throw new Exception("Detected repeatable Veins Utilization MaxLevel is invalid: " + maxLevel);
}
int num = Math.Max(6, Math.Min(TargetLevel.Value, maxLevel));
if (num != TargetLevel.Value)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Configured TargetLevel " + TargetLevel.Value + " was clamped to the game's repeatable-tech maximum " + maxLevel + "."));
}
int num2 = EstimateAppliedLevelFromMiningSpeed(history.miningSpeedScale);
((BaseUnityPlugin)this).Logger.LogInfo((object)("VU state before repair: tech target=" + num + ", miningSpeedScale=" + history.miningSpeedScale + ", estimated actually-applied level=" + num2));
List<TechProto> list2 = new List<TechProto>();
foreach (TechProto item in list)
{
if (((Proto)item).ID != iD)
{
list2.Add(item);
}
}
list2.Sort(delegate(TechProto a, TechProto b)
{
int num12 = a.Level.CompareTo(b.Level);
return (num12 != 0) ? num12 : ((Proto)a).ID.CompareTo(((Proto)b).ID);
});
int num3 = Math.Min(5, list2.Count);
if (num3 < 5)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Only " + num3 + " finite Veins Utilization stages were found; expected I-V."));
}
for (int num4 = 0; num4 < num3; num4++)
{
TechProto val2 = list2[num4];
int iD2 = ((Proto)val2).ID;
int num5 = num4 + 1;
if (history.techStates.TryGetValue(iD2, out var value))
{
int num6 = Math.Max(val2.Level, val2.MaxLevel);
if (value.curLevel < num6 || !value.unlocked)
{
value.curLevel = num6;
value.maxLevel = Math.Max(value.maxLevel, num6);
value.unlocked = true;
history.techStates[iD2] = value;
}
}
if (num2 < num5)
{
ApplyFunctions(history, val2, num5);
num2 = EstimateAppliedLevelFromMiningSpeed(history.miningSpeedScale);
((BaseUnityPlugin)this).Logger.LogInfo((object)("Applied Veins Utilization finite stage " + num5 + "; miningSpeedScale=" + history.miningSpeedScale + "; estimated level=" + num2));
}
}
if (!history.techStates.TryGetValue(iD, out var value2))
{
throw new Exception("Repeatable Veins Utilization TechState not found.");
}
int curLevel = value2.curLevel;
int maxLevel2 = value2.maxLevel;
bool unlocked = value2.unlocked;
((BaseUnityPlugin)this).Logger.LogInfo((object)("Repeatable VU state before synchronization: curLevel=" + curLevel + ", maxLevel=" + maxLevel2 + ", unlocked=" + unlocked));
int num7 = num;
if (num2 < 5)
{
num2 = EstimateAppliedLevelFromMiningSpeed(history.miningSpeedScale);
}
int num8 = Math.Max(6, num2 + 1);
if (num8 <= num7)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("Replaying Veins Utilization effects from level " + num8 + " through target level " + num7 + "."));
for (int num9 = num8; num9 <= num7; num9++)
{
ApplyFunctions(history, val, num9);
}
}
int num10 = Math.Max(curLevel, num);
if (num10 > maxLevel)
{
num10 = maxLevel;
}
value2.curLevel = num10;
value2.maxLevel = maxLevel;
value2.unlocked = num10 >= maxLevel;
history.techStates[iD] = value2;
int num11 = EstimateAppliedLevelFromMiningSpeed(history.miningSpeedScale);
((BaseUnityPlugin)this).Logger.LogInfo((object)("Repeatable VU state after synchronization: curLevel=" + value2.curLevel + ", maxLevel=" + value2.maxLevel + ", unlocked=" + value2.unlocked));
((BaseUnityPlugin)this).Logger.LogInfo((object)("VU synchronization complete. Target=" + num + ", EffectLevel≈" + num11 + ", miningSpeedScale=" + history.miningSpeedScale + ", miningCostRate=" + history.miningCostRate));
if (value2.curLevel < value2.maxLevel)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Repeatable VU remains below the real maximum. The next level should remain researchable.");
}
else
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Repeatable VU is at the real maximum and is marked unlocked/completed.");
}
if (num11 < value2.curLevel - 1 || num11 > value2.curLevel + 1)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"The resulting mining-speed effect does not closely match curLevel. Another mod or a game update may be changing miningSpeedScale.");
}
}
private static int EstimateAppliedLevelFromMiningSpeed(float miningSpeedScale)
{
if (miningSpeedScale <= 1.0001f)
{
return 0;
}
double num = ((double)miningSpeedScale - 1.0) / 0.1;
if (num < 0.0)
{
return 0;
}
if (num > 1000000.0)
{
return 1000000;
}
return (int)Math.Round(num, MidpointRounding.AwayFromZero);
}
private static void ApplyFunctions(GameHistoryData history, TechProto tech, int level)
{
int[] unlockFunctions = tech.UnlockFunctions;
double[] unlockValues = tech.UnlockValues;
if (unlockFunctions == null || unlockValues == null || unlockFunctions.Length == 0 || unlockFunctions.Length != unlockValues.Length)
{
throw new Exception("Invalid UnlockFunctions/UnlockValues for Tech ID " + ((Proto)tech).ID);
}
for (int i = 0; i < unlockFunctions.Length; i++)
{
history.UnlockTechFunction(unlockFunctions[i], unlockValues[i], level);
}
}
private List<TechProto> FindCandidates()
{
List<TechProto> list = new List<TechProto>();
if (TechIdOverride.Value > 0)
{
TechProto val = ((ProtoSet<TechProto>)(object)LDB.techs).Select(TechIdOverride.Value);
if (val != null)
{
list.Add(val);
}
return list;
}
TechProto[] dataArray = ((ProtoSet<TechProto>)(object)LDB.techs).dataArray;
foreach (TechProto val2 in dataArray)
{
if (val2 == null)
{
continue;
}
string text = ((Proto)val2).Name ?? "";
string s = text;
try
{
if (Localization.CanTranslate(text))
{
s = Localization.Translate(text);
}
}
catch
{
}
if (LooksLikeVU(text) || LooksLikeVU(s))
{
list.Add(val2);
}
}
return list;
}
private static bool LooksLikeVU(string s)
{
if (string.IsNullOrEmpty(s))
{
return false;
}
string text = s.ToLowerInvariant();
if (!text.Contains("veins utilization") && !text.Contains("vein utilization") && !s.Contains("광맥 활용") && !s.Contains("矿物利用"))
{
return s.Contains("礦物利用");
}
return true;
}
private static TechProto SelectRepeatable(List<TechProto> all)
{
TechProto val = null;
foreach (TechProto item in all)
{
if (val == null || item.MaxLevel > val.MaxLevel || (item.MaxLevel == val.MaxLevel && item.Level > val.Level))
{
val = item;
}
}
return val;
}
}
}