using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.NET.Common;
using HarmonyLib;
using ModSettingsMenu.Api;
using RomesteadLocalizationAPI.Api;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]
[assembly: AssemblyCompany("BossMapMarkers")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BossMapMarkers")]
[assembly: AssemblyTitle("BossMapMarkers")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace BossMapMarkers;
internal static class I18n
{
public static readonly RomesteadLocalizer L = RomesteadLocalization.For("local.romestead.boss-map-markers");
}
public static class WorldMapPatches
{
private static int _cachedCount = -1;
private static string? _cachedWorldId = null;
private static object[]? _cachedMarkers = null;
private static readonly BindingFlags IF = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
private static readonly BindingFlags SF = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
private static readonly Dictionary<string, string> BossIcons = new Dictionary<string, string>
{
{ "boss:satyrboss", "map_marker:gravestone" },
{ "boss:phoenix", "map_marker:gravestone" },
{ "boss:talos", "map_marker:gravestone" },
{ "boss:minervas_owl", "map_marker:gravestone" },
{ "boss:cyclops_eye", "map_marker:cyclop" }
};
public static void DrawMapMarkers_Prefix(object __instance)
{
//IL_0336: Unknown result type (might be due to invalid IL or missing references)
//IL_033d: Expected O, but got Unknown
//IL_029d: Unknown result type (might be due to invalid IL or missing references)
//IL_02a4: Expected O, but got Unknown
bool flag = default(bool);
try
{
object obj = __instance.GetType().GetField("_reuseMarkersList", IF)?.GetValue(__instance);
if (Plugin.ImmediateMapMarkerType == null && obj != null && obj.GetType().IsGenericType)
{
Plugin.CacheMarkerType(obj.GetType().GetGenericArguments()[0]);
}
ConfigEntry<bool>? enabledEntry = Plugin.EnabledEntry;
if (enabledEntry != null && !enabledEntry.Value)
{
return;
}
Type gameStateType = Plugin.GameStateType;
if (gameStateType == null || obj == null || Plugin.ImmediateMapMarkerType == null)
{
return;
}
float tileW = 16f;
float tileH = 16f;
object obj2 = gameStateType.GetField("Config", SF)?.GetValue(null);
if (obj2 != null)
{
object obj3 = obj2.GetType().GetField("TileSize", IF)?.GetValue(obj2);
if (obj3 != null)
{
tileW = Convert.ToSingle(obj3.GetType().GetField("X", IF)?.GetValue(obj3) ?? ((object)16f));
tileH = Convert.ToSingle(obj3.GetType().GetField("Y", IF)?.GetValue(obj3) ?? ((object)16f));
}
}
object obj4 = gameStateType.GetField("BossLocations", SF)?.GetValue(null);
if (!(obj4 is IEnumerable enumerable))
{
return;
}
int num = (obj4 as ICollection)?.Count ?? 0;
if (num == 0)
{
return;
}
string currentWorldId = GetCurrentWorldId(__instance, gameStateType);
if (_cachedMarkers == null || _cachedCount != num || _cachedWorldId != currentWorldId)
{
_cachedCount = num;
_cachedWorldId = currentWorldId;
List<object> list = new List<object>();
foreach (object item in enumerable)
{
object fieldVal = GetFieldVal(item, "value");
if (fieldVal == null || !Plugin.IsBossEnabled(GetStr(fieldVal, "BossId") ?? ""))
{
continue;
}
string str = GetStr(fieldVal, "WorldId");
if (currentWorldId == null || string.IsNullOrEmpty(str) || !(str != currentWorldId))
{
object obj5 = CreateMarker(fieldVal, tileW, tileH);
if (obj5 != null)
{
list.Add(obj5);
}
}
}
_cachedMarkers = list.ToArray();
ManualLogSource logger = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(39, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[BossMapMarkers] ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(_cachedMarkers.Length);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" boss marker(s) ready.");
}
logger.LogInfo(val);
}
MethodInfo method = obj.GetType().GetMethod("Add");
if (!(method == null))
{
object[] cachedMarkers = _cachedMarkers;
foreach (object obj6 in cachedMarkers)
{
method.Invoke(obj, new object[1] { obj6 });
}
}
}
catch (Exception ex)
{
ManualLogSource logger2 = Plugin.Logger;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(17, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[BossMapMarkers] ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
}
logger2.LogError(val2);
}
}
private static object? CreateMarker(object bossLoc, float tileW, float tileH)
{
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01a5: Expected O, but got Unknown
try
{
object obj = Activator.CreateInstance(Plugin.ImmediateMapMarkerType);
string text = GetStr(bossLoc, "BossId") ?? "";
object obj2 = GetFieldVal(bossLoc, "IconLocation") ?? GetFieldVal(bossLoc, "Location");
if (obj2 != null && Plugin.TilePositionField != null)
{
float num = Convert.ToSingle(obj2.GetType().GetField("X", IF)?.GetValue(obj2) ?? ((object)0f));
float num2 = Convert.ToSingle(obj2.GetType().GetField("Y", IF)?.GetValue(obj2) ?? ((object)0f));
object obj3 = MakeVec2(Plugin.TilePositionField.FieldType, num / tileW, num2 / tileH);
if (obj3 != null)
{
Plugin.TilePositionField.SetValue(obj, obj3);
}
}
Plugin.IconIdField?.SetValue(obj, BossIcons.TryGetValue(text, out string value) ? value : "map_marker:gravestone");
Plugin.HoverTextField?.SetValue(obj, Plugin.GetLocalizedName(text));
Plugin.IsDecorativeField?.SetValue(obj, false);
Plugin.StickyField?.SetValue(obj, true);
if (Plugin.ScaleField?.FieldType == typeof(float))
{
Plugin.ScaleField.SetValue(obj, 1.2f);
}
return obj;
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(31, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[BossMapMarkers] CreateMarker: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
return null;
}
}
private static object? MakeVec2(Type vec2Type, float x, float y)
{
try
{
object obj = Activator.CreateInstance(vec2Type);
vec2Type.GetField("X", IF)?.SetValue(obj, x);
vec2Type.GetField("Y", IF)?.SetValue(obj, y);
return obj;
}
catch
{
return null;
}
}
private static string? GetCurrentWorldId(object worldMap, Type gs)
{
object fieldVal = GetFieldVal(worldMap, "World");
if (fieldVal != null)
{
object obj = GetFieldVal(fieldVal, "Id") ?? GetFieldVal(fieldVal, "WorldId");
if (obj != null)
{
return obj.ToString();
}
}
object obj2 = gs.GetField("CurrentWorld", SF)?.GetValue(null);
if (obj2 != null)
{
return (GetFieldVal(obj2, "Id") ?? GetFieldVal(obj2, "WorldId"))?.ToString();
}
return null;
}
public static void ClearCache()
{
_cachedMarkers = null;
_cachedCount = -1;
_cachedWorldId = null;
}
private static object? GetFieldVal(object? obj, string name)
{
return obj?.GetType().GetField(name, IF)?.GetValue(obj);
}
private static string? GetStr(object? obj, string name)
{
return GetFieldVal(obj, name)?.ToString();
}
}
[BepInPlugin("local.romestead.boss-map-markers", "Boss Map Markers", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BasePlugin
{
public const string PluginGuid = "local.romestead.boss-map-markers";
public const string PluginName = "Boss Map Markers";
public const string PluginVersion = "1.0.0";
public static ManualLogSource Logger = null;
public static Type? GameStateType;
public static ConfigEntry<bool>? EnabledEntry;
public static readonly Dictionary<string, ConfigEntry<bool>> BossEnabledEntries = new Dictionary<string, ConfigEntry<bool>>();
private static readonly (string BossId, string ConfigKey, int Order)[] BossSettings = new(string, string, int)[5]
{
("boss:satyrboss", "ShowSatyrBoss", 2),
("boss:phoenix", "ShowPhoenix", 3),
("boss:talos", "ShowTalos", 4),
("boss:minervas_owl", "ShowMinervasOwl", 5),
("boss:cyclops_eye", "ShowCyclops", 6)
};
public static Type? ImmediateMapMarkerType;
public static FieldInfo? TilePositionField;
public static FieldInfo? IconIdField;
public static FieldInfo? HoverTextField;
public static FieldInfo? ScaleField;
public static FieldInfo? IsDecorativeField;
public static FieldInfo? StickyField;
private bool _settingsRegistered;
public override void Load()
{
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Expected O, but got Unknown
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Expected O, but got Unknown
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Expected O, but got Unknown
Logger = ((BasePlugin)this).Log;
I18n.L.RegisterJson(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "localization.json"));
RomesteadLocalization.LocalizationApplied += OnLocalizationApplied;
Harmony val = new Harmony("local.romestead.boss-map-markers");
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
Type[] types;
try
{
types = assembly.GetTypes();
}
catch
{
continue;
}
Type[] array = types;
foreach (Type type in array)
{
if (type.FullName == "Candide.GameModels.GameState")
{
GameStateType = type;
}
else if (type.FullName == "Candide.World.WorldMap")
{
MethodInfo method = type.GetMethod("DrawMapMarkers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
val.Patch((MethodBase)method, new HarmonyMethod(typeof(WorldMapPatches).GetMethod("DrawMapMarkers_Prefix", BindingFlags.Static | BindingFlags.Public)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
}
}
ManualLogSource logger = Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(9, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("Boss Map Markers");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.0.0");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded.");
}
logger.LogInfo(val2);
}
private ConfigDescription BuildEnabledDescription()
{
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Expected O, but got Unknown
return new ConfigDescription(I18n.L.Text("entry.enabled.desc", Array.Empty<object>()), (AcceptableValueBase)null, new object[2]
{
ModSettingsTags.Section("General", I18n.L.Text("section.general", Array.Empty<object>()), (int?)10, (bool?)null),
ModSettingsTags.Entry(I18n.L.Text("entry.enabled", Array.Empty<object>()), I18n.L.Text("entry.enabled.desc", Array.Empty<object>()), (int?)1, (double?)null, (bool?)null)
});
}
private static ConfigDescription BuildBossDescription(string bossId, int order)
{
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Expected O, but got Unknown
string text = I18n.L.Text("entry.boss.enabled.desc", Array.Empty<object>());
return new ConfigDescription(text, (AcceptableValueBase)null, new object[2]
{
ModSettingsTags.Section("General", I18n.L.Text("section.general", Array.Empty<object>()), (int?)10, (bool?)null),
ModSettingsTags.Entry(I18n.L.Text("entry.boss.enabled", Array.Empty<object>()).Replace("{boss}", I18n.L.Text(bossId, Array.Empty<object>())), text.Replace("{boss}", I18n.L.Text(bossId, Array.Empty<object>())), (int?)order, (double?)null, (bool?)null)
});
}
private void OnLocalizationApplied(string locale)
{
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: 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_01ab: Expected O, but got Unknown
WorldMapPatches.ClearCache();
if (!_settingsRegistered)
{
_settingsRegistered = true;
EnabledEntry = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, BuildEnabledDescription());
EnabledEntry.SettingChanged += delegate
{
WorldMapPatches.ClearCache();
};
(string, string, int)[] bossSettings = BossSettings;
for (int num = 0; num < bossSettings.Length; num++)
{
(string, string, int) tuple = bossSettings[num];
ConfigEntry<bool> val = ((BasePlugin)this).Config.Bind<bool>("Bosses", tuple.Item2, true, BuildBossDescription(tuple.Item1, tuple.Item3));
val.SettingChanged += delegate
{
WorldMapPatches.ClearCache();
};
BossEnabledEntries[tuple.Item1] = val;
}
}
else
{
SetDescription((ConfigEntryBase?)(object)EnabledEntry, BuildEnabledDescription());
(string, string, int)[] bossSettings = BossSettings;
for (int num = 0; num < bossSettings.Length; num++)
{
(string, string, int) tuple2 = bossSettings[num];
if (BossEnabledEntries.TryGetValue(tuple2.Item1, out ConfigEntry<bool> value))
{
SetDescription((ConfigEntryBase?)(object)value, BuildBossDescription(tuple2.Item1, tuple2.Item3));
}
}
}
ModSettingsRegistry.Register("local.romestead.boss-map-markers", I18n.L.Text("mod.name", Array.Empty<object>()), ((BasePlugin)this).Config, new ModSettingsModOptions
{
Icon = "map",
Version = "1.0.0",
Author = "wwwshe",
Description = I18n.L.Text("mod.description", Array.Empty<object>()),
Order = 60
});
}
public override bool Unload()
{
RomesteadLocalization.LocalizationApplied -= OnLocalizationApplied;
return true;
}
public static string GetLocalizedName(string bossId)
{
return I18n.L.Text(bossId, Array.Empty<object>());
}
public static bool IsBossEnabled(string bossId)
{
if (BossEnabledEntries.TryGetValue(bossId, out ConfigEntry<bool> value))
{
return value.Value;
}
return true;
}
private static void SetDescription(ConfigEntryBase? entry, ConfigDescription description)
{
if (entry != null)
{
typeof(ConfigEntryBase).GetField("<Description>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(entry, description);
}
}
public static void CacheMarkerType(Type type)
{
if (!(ImmediateMapMarkerType == type))
{
ImmediateMapMarkerType = type;
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
TilePositionField = type.GetField("TilePosition", bindingAttr);
IconIdField = type.GetField("IconId", bindingAttr);
HoverTextField = type.GetField("HoverText", bindingAttr);
ScaleField = type.GetField("Scale", bindingAttr);
IsDecorativeField = type.GetField("IsDecorative", bindingAttr);
StickyField = type.GetField("Sticky", bindingAttr);
Logger.LogInfo((object)"[BossMapMarkers] ImmediateMapMarker cached.");
}
}
}