using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using Gunfiguration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ReskinSwitcherMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("N/A")]
[assembly: AssemblyProduct("ReskinSwitcherMod")]
[assembly: AssemblyCopyright("Copyright © N/A 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("78ed1445-9a9d-438b-a7a8-350f9024e295")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 ReskinSwitcherMod
{
[HarmonyPatch]
public static class Patches
{
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPrefix]
public static void ProcessNewCollectionSet(tk2dSpriteCollectionData value)
{
ProcessedCollections.ProcessNewCollection(value);
}
[HarmonyPatch(typeof(tk2dBaseSprite), "Awake")]
[HarmonyPrefix]
public static void ProcessNewCollectionAwake(tk2dBaseSprite __instance)
{
ProcessedCollections.ProcessNewCollection(__instance.Collection);
}
[HarmonyPatch(typeof(tk2dBaseSprite), "SetSprite", new Type[]
{
typeof(tk2dSpriteCollectionData),
typeof(int)
})]
[HarmonyPatch(typeof(tk2dBaseSprite), "SetSprite", new Type[]
{
typeof(tk2dSpriteCollectionData),
typeof(string)
})]
[HarmonyPrefix]
public static void ProcessNewCollectionSS(tk2dSpriteCollectionData newCollection)
{
ProcessedCollections.ProcessNewCollection(newCollection);
}
[HarmonyPatch(typeof(tk2dTileMap), "Awake")]
[HarmonyPrefix]
public static void ProcessNewCollectionTilemap(tk2dTileMap __instance)
{
ProcessedCollections.ProcessNewCollection(__instance.spriteCollection);
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPrefix]
public static void ProcessNewCollectionTilemapCollection(tk2dSpriteCollectionData value)
{
ProcessedCollections.ProcessNewCollection(value);
}
[HarmonyPatch(typeof(GameManager), "ClearActiveGameData")]
[HarmonyPrefix]
public static void StartReskinRun()
{
if (ReskinLoader.groups == null)
{
return;
}
foreach (ReskinGroup value in ReskinLoader.groups.Values)
{
if (value != null && value.TryGetReskin(value.currentResprite, out var reskin))
{
reskin.OnNewRunStarted();
}
}
}
}
[BepInPlugin("spapi.etg.reskinswitcher", "Reskin Switcher", "1.1.0")]
public class Plugin : BaseUnityPlugin
{
public const string GUID = "spapi.etg.reskinswitcher";
public const string NAME = "Reskin Switcher";
public const string VERSION = "1.1.0";
public void Awake()
{
ReskinLoader.LoadReskins();
ReskinConfig.Init();
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "spapi.etg.reskinswitcher");
}
}
public static class ProcessedCollections
{
public static readonly Dictionary<string, tk2dSpriteCollectionData> processed = new Dictionary<string, tk2dSpriteCollectionData>();
public static bool TryGetCollection(string name, out tk2dSpriteCollectionData coll)
{
if (processed.TryGetValue(name, out coll))
{
return (Object)(object)coll != (Object)null;
}
coll = Assets.Collections.Find((tk2dSpriteCollectionData x) => ((Object)x).name == name);
if ((Object)(object)coll == (Object)null)
{
return false;
}
processed[name] = coll;
return true;
}
public static void ProcessNewCollection(tk2dSpriteCollectionData coll)
{
if ((Object)(object)coll == (Object)null || (processed.TryGetValue(((Object)coll).name, out var value) && (Object)(object)value != (Object)null))
{
return;
}
processed[((Object)coll).name] = coll;
foreach (ReskinGroup value2 in ReskinLoader.groups.Values)
{
if (value2.TryGetReskin(value2.currentResprite, out var reskin))
{
reskin.ProcessCollection(coll, alsoApply: true);
}
foreach (ReskinBase reskin2 in value2.ReskinList)
{
reskin2.ProcessCollection(coll, alsoApply: false);
}
}
}
}
public abstract class ReplacementBase
{
public string collName;
public tk2dSpriteCollectionData loadedCollection;
public abstract void ApplyResprites(tk2dSpriteCollectionData coll);
public abstract void UnapplyResprites(tk2dSpriteCollectionData coll);
}
public class SpritesheetReplacement : ReplacementBase
{
public Texture2D spritesheet;
public Dictionary<Material, Texture> previousDefinitions = new Dictionary<Material, Texture>();
public override void ApplyResprites(tk2dSpriteCollectionData coll)
{
if (coll.materials == null || coll.materials.Length == 0)
{
return;
}
Material val = coll.materials[0];
if (!Object.op_Implicit((Object)(object)val))
{
return;
}
Texture mainTexture = val.mainTexture;
if (!Object.op_Implicit((Object)(object)mainTexture))
{
return;
}
string name = ((Object)mainTexture).name;
if (string.IsNullOrEmpty(name) || name[0] == '~')
{
return;
}
((Object)spritesheet).name = "~" + name;
for (int i = 0; i < coll.materials.Length; i++)
{
Material obj = coll.materials[i];
if (!((Object)(object)((obj != null) ? obj.mainTexture : null) == (Object)null))
{
previousDefinitions[coll.materials[i]] = coll.materials[i].mainTexture;
coll.materials[i].mainTexture = (Texture)(object)spritesheet;
}
}
coll.inst.materialInsts = null;
coll.inst.Init();
if (!((Object)(object)coll.inst != (Object)(object)coll) || coll.inst?.materials == null)
{
return;
}
for (int j = 0; j < coll.inst.materials.Length; j++)
{
Material obj2 = coll.inst.materials[j];
if (!((Object)(object)((obj2 != null) ? obj2.mainTexture : null) == (Object)null))
{
previousDefinitions[coll.inst.materials[j]] = coll.inst.materials[j].mainTexture;
coll.inst.materials[j].mainTexture = (Texture)(object)spritesheet;
}
}
}
public override void UnapplyResprites(tk2dSpriteCollectionData coll)
{
foreach (KeyValuePair<Material, Texture> previousDefinition in previousDefinitions)
{
if ((Object)(object)previousDefinition.Key != (Object)null)
{
previousDefinition.Key.mainTexture = previousDefinition.Value;
}
}
previousDefinitions.Clear();
}
}
public class IndividualReplacement : ReplacementBase
{
public class DefinitionInfoCache
{
public FlipMode flipped;
public Material materialInst;
public Vector2 texelSize;
public bool extractRegion;
public Vector2[] uvs;
public Vector3 position0;
public Vector3 position1;
public Vector3 position2;
public Vector3 position3;
public Vector3 boundsCenter;
public Vector3 boundsExtents;
public Vector3 untrimmedBoundsCenter;
public Vector3 untrimmedBoundsExtents;
}
public class DefinitionReplacementInfo
{
public Texture2D texture;
public RuntimeAtlasSegment pack;
public bool hasSavedTrimData;
public int? minX;
public int? maxX;
public int? minY;
public int? maxY;
}
public Dictionary<string, DefinitionReplacementInfo> definitionReplacements;
public Dictionary<tk2dSpriteDefinition, DefinitionInfoCache> previousDefinitions = new Dictionary<tk2dSpriteDefinition, DefinitionInfoCache>();
public bool advanced;
public override void ApplyResprites(tk2dSpriteCollectionData coll)
{
//IL_009c: 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_00b4: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: 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_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_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_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: 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_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)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Expected O, but got Unknown
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
//IL_0150: 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_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_019d: Unknown result type (might be due to invalid IL or missing references)
//IL_01af: 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_01be: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_01c2: 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)
//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0204: Unknown result type (might be due to invalid IL or missing references)
//IL_0206: Unknown result type (might be due to invalid IL or missing references)
//IL_020b: 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_0212: Unknown result type (might be due to invalid IL or missing references)
//IL_0217: Unknown result type (might be due to invalid IL or missing references)
//IL_021e: Unknown result type (might be due to invalid IL or missing references)
//IL_0223: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: 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_022c: 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_0238: Unknown result type (might be due to invalid IL or missing references)
//IL_023d: Unknown result type (might be due to invalid IL or missing references)
//IL_023f: 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_0246: Unknown result type (might be due to invalid IL or missing references)
//IL_024b: Unknown result type (might be due to invalid IL or missing references)
//IL_0250: Unknown result type (might be due to invalid IL or missing references)
//IL_0257: Unknown result type (might be due to invalid IL or missing references)
//IL_025c: Unknown result type (might be due to invalid IL or missing references)
//IL_025e: Unknown result type (might be due to invalid IL or missing references)
//IL_0260: Unknown result type (might be due to invalid IL or missing references)
//IL_0265: Unknown result type (might be due to invalid IL or missing references)
//IL_026a: Unknown result type (might be due to invalid IL or missing references)
//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
//IL_04af: Unknown result type (might be due to invalid IL or missing references)
//IL_04b4: Unknown result type (might be due to invalid IL or missing references)
//IL_0436: Unknown result type (might be due to invalid IL or missing references)
//IL_0440: Unknown result type (might be due to invalid IL or missing references)
//IL_0445: Unknown result type (might be due to invalid IL or missing references)
//IL_0477: Unknown result type (might be due to invalid IL or missing references)
//IL_0481: Unknown result type (might be due to invalid IL or missing references)
//IL_0486: Unknown result type (might be due to invalid IL or missing references)
//IL_048a: Unknown result type (might be due to invalid IL or missing references)
//IL_048f: Unknown result type (might be due to invalid IL or missing references)
//IL_0491: Unknown result type (might be due to invalid IL or missing references)
//IL_0496: Unknown result type (might be due to invalid IL or missing references)
//IL_049c: Unknown result type (might be due to invalid IL or missing references)
//IL_049e: Unknown result type (might be due to invalid IL or missing references)
//IL_04bb: Unknown result type (might be due to invalid IL or missing references)
//IL_04c0: Unknown result type (might be due to invalid IL or missing references)
//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
Vector3 val5 = default(Vector3);
Vector3 val6 = default(Vector3);
foreach (KeyValuePair<string, DefinitionReplacementInfo> definitionReplacement in definitionReplacements)
{
tk2dSpriteDefinition spriteDefinition = coll.GetSpriteDefinition(definitionReplacement.Key);
if (spriteDefinition == null)
{
continue;
}
DefinitionReplacementInfo value = definitionReplacement.Value;
Texture2D texture = value.texture;
DefinitionReplacementInfo definitionReplacementInfo = value;
RuntimeAtlasSegment val = definitionReplacementInfo.pack ?? (definitionReplacementInfo.pack = Assets.Packer.Pack(texture, false));
if (val == null)
{
continue;
}
previousDefinitions[spriteDefinition] = new DefinitionInfoCache
{
extractRegion = spriteDefinition.extractRegion,
flipped = spriteDefinition.flipped,
materialInst = spriteDefinition.materialInst,
texelSize = spriteDefinition.texelSize,
uvs = spriteDefinition.uvs,
position0 = spriteDefinition.position0,
position1 = spriteDefinition.position1,
position2 = spriteDefinition.position2,
position3 = spriteDefinition.position3,
boundsCenter = spriteDefinition.boundsDataCenter,
boundsExtents = spriteDefinition.boundsDataExtents,
untrimmedBoundsCenter = spriteDefinition.untrimmedBoundsDataCenter,
untrimmedBoundsExtents = spriteDefinition.untrimmedBoundsDataExtents
};
spriteDefinition.flipped = (FlipMode)0;
spriteDefinition.materialInst = new Material(spriteDefinition.material);
spriteDefinition.texelSize = ((Texture)texture).texelSize;
spriteDefinition.extractRegion = true;
spriteDefinition.materialInst.mainTexture = (Texture)(object)val.texture;
spriteDefinition.uvs = val.uvs;
if (!advanced)
{
continue;
}
Vector3 val2 = spriteDefinition.position3 - spriteDefinition.position0;
Vector3 val3 = new Vector3((float)((Texture)texture).width, (float)((Texture)texture).height) / 16f;
Vector3 val4 = val3 - val2;
((Vector3)(ref val5))..ctor(val4.x / 2f, 0f);
((Vector3)(ref val6))..ctor(0f, val4.y / 2f);
spriteDefinition.position0 += -val5 - val6;
spriteDefinition.position1 += val5 - val6;
spriteDefinition.position2 += -val5 + val6;
spriteDefinition.position3 += val5 + val6;
Color[] pixels = texture.GetPixels();
int? minX = null;
int? maxX = null;
int? minY = null;
int? maxY = null;
if (value.hasSavedTrimData)
{
minX = value.minX;
maxX = value.maxX;
minY = value.minY;
maxY = value.maxY;
}
else if (ETGMod.IsReadable(texture))
{
for (int i = 0; i < pixels.Length; i++)
{
Color val7 = pixels[i];
if (!(val7.a <= 0f))
{
int num = i % ((Texture)texture).width;
int num2 = i / ((Texture)texture).width;
int valueOrDefault = minY.GetValueOrDefault();
if (!minY.HasValue)
{
valueOrDefault = num2;
minY = valueOrDefault;
}
maxY = num2;
minX = Mathf.Min(minX.GetValueOrDefault(int.MaxValue), num);
maxX = Mathf.Max(maxX.GetValueOrDefault(int.MinValue), num);
}
}
}
if (!value.hasSavedTrimData)
{
value.minX = minX;
value.maxX = maxX;
value.minY = minY;
value.maxY = maxY;
value.hasSavedTrimData = true;
}
if (minX.HasValue && maxX.HasValue && minY.HasValue && maxY.HasValue)
{
int num3 = maxX.GetValueOrDefault() - minX.GetValueOrDefault() + 1;
int num4 = maxY.GetValueOrDefault() - minY.GetValueOrDefault() + 1;
Vector3 boundsDataExtents = new Vector3((float)num3, (float)num4) / 16f;
Vector3 val8 = new Vector3((float)(maxX.GetValueOrDefault() + minX.GetValueOrDefault() + 1) / 2f, (float)(maxY.GetValueOrDefault() + minY.GetValueOrDefault() + 1) / 2f) / 16f;
spriteDefinition.boundsDataCenter = spriteDefinition.position0 + val8;
spriteDefinition.boundsDataExtents = boundsDataExtents;
}
else
{
spriteDefinition.boundsDataExtents += val4;
}
spriteDefinition.untrimmedBoundsDataExtents += val4;
}
}
public override void UnapplyResprites(tk2dSpriteCollectionData coll)
{
//IL_0042: 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)
//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_0083: 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_0090: 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_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)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: 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_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_00d1: 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_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
foreach (KeyValuePair<tk2dSpriteDefinition, DefinitionInfoCache> previousDefinition in previousDefinitions)
{
if (previousDefinition.Key != null)
{
tk2dSpriteDefinition key = previousDefinition.Key;
DefinitionInfoCache value = previousDefinition.Value;
key.flipped = value.flipped;
key.materialInst = value.materialInst;
key.texelSize = value.texelSize;
key.extractRegion = value.extractRegion;
key.uvs = value.uvs;
key.position0 = value.position0;
key.position1 = value.position1;
key.position2 = value.position2;
key.position3 = value.position3;
key.boundsDataCenter = value.boundsCenter;
key.boundsDataExtents = value.boundsExtents;
key.untrimmedBoundsDataCenter = value.untrimmedBoundsCenter;
key.untrimmedBoundsDataExtents = value.untrimmedBoundsExtents;
}
}
previousDefinitions.Clear();
}
}
public class ReskinGroup
{
public string name;
public string currentResprite;
public RandomReskin randomReskin;
public EmptyReskin emptyReskin;
public Dictionary<string, NamedReskin> reskins;
public List<ReskinBase> ReskinList
{
get
{
ReskinBase item = emptyReskin;
Dictionary<string, NamedReskin>.ValueCollection values = reskins.Values;
List<ReskinBase> list = new List<ReskinBase>(2 + values.Count);
list.Add(item);
foreach (NamedReskin item2 in values)
{
list.Add(item2);
}
list.Add(randomReskin);
return list;
}
}
public List<ReskinBase> ReskinListNoRandom
{
get
{
ReskinBase item = emptyReskin;
Dictionary<string, NamedReskin>.ValueCollection values = reskins.Values;
List<ReskinBase> list = new List<ReskinBase>(1 + values.Count);
list.Add(item);
foreach (NamedReskin item2 in values)
{
list.Add(item2);
}
return list;
}
}
public ReskinGroup()
{
randomReskin = new RandomReskin
{
group = this
};
emptyReskin = new EmptyReskin
{
group = this
};
}
public bool TryGetReskin(string name, out ReskinBase reskin)
{
if (name == ReskinConfig.NoResprite)
{
reskin = null;
return false;
}
if (name == ReskinConfig.RandomResprite)
{
reskin = randomReskin;
return true;
}
if (reskins.TryGetValue(name, out var value))
{
reskin = value;
return true;
}
reskin = null;
return false;
}
}
public abstract class ReskinBase
{
public List<ReplacementBase> replacements = new List<ReplacementBase>();
public ReskinGroup group;
public abstract string Name { get; }
public virtual void ApplyReplacements()
{
foreach (ReplacementBase replacement in replacements)
{
if (!((Object)(object)replacement.loadedCollection == (Object)null))
{
replacement.ApplyResprites(replacement.loadedCollection);
}
}
}
public virtual void UnapplyReplacements()
{
foreach (ReplacementBase replacement in replacements)
{
if (!((Object)(object)replacement.loadedCollection == (Object)null))
{
replacement.UnapplyResprites(replacement.loadedCollection);
}
}
}
public virtual void LoadCollections(bool alsoApply)
{
foreach (ReplacementBase replacement in replacements)
{
if (ProcessedCollections.TryGetCollection(replacement.collName, out replacement.loadedCollection) && alsoApply)
{
replacement.ApplyResprites(replacement.loadedCollection);
}
}
}
public virtual void ProcessCollection(tk2dSpriteCollectionData coll, bool alsoApply)
{
if ((Object)(object)coll == (Object)null)
{
return;
}
foreach (ReplacementBase replacement in replacements)
{
if (!((Object)(object)replacement.loadedCollection != (Object)null) && !(replacement.collName != ((Object)coll).name))
{
replacement.loadedCollection = coll;
if (alsoApply)
{
replacement.ApplyResprites(coll);
}
}
}
}
public virtual void OnNewRunStarted()
{
}
}
public class NamedReskin : ReskinBase
{
public string _name;
public override string Name => _name;
}
public class EmptyReskin : ReskinBase
{
public override string Name => ReskinConfig.NoResprite;
public override void ApplyReplacements()
{
}
public override void UnapplyReplacements()
{
}
public override void LoadCollections(bool alsoApply)
{
}
public override void ProcessCollection(tk2dSpriteCollectionData coll, bool alsoApply)
{
}
}
public class RandomReskin : ReskinBase
{
public override string Name => ReskinConfig.RandomResprite;
public override void ApplyReplacements()
{
RandomizeReplacements();
base.ApplyReplacements();
}
public override void LoadCollections(bool alsoApply)
{
RandomizeReplacements();
base.LoadCollections(alsoApply);
}
public override void OnNewRunStarted()
{
UnapplyReplacements();
ApplyReplacements();
}
public void RandomizeReplacements()
{
replacements.Clear();
if (group != null)
{
List<ReskinBase> reskinListNoRandom = group.ReskinListNoRandom;
if (reskinListNoRandom != null && reskinListNoRandom.Count > 0)
{
replacements.AddRange(BraveUtility.RandomElement<ReskinBase>(group.ReskinListNoRandom).replacements);
}
}
}
}
public static class ReskinConfig
{
public static Gunfig gunfig;
public static string NoResprite = "None";
public static string RandomResprite = "Random";
public static void Init()
{
if (ReskinLoader.groups.Count <= 0)
{
return;
}
gunfig = Gunfig.Get("Reskin Switcher");
foreach (ReskinGroup value in ReskinLoader.groups.Values)
{
Gunfig obj = gunfig;
string name = value.name;
List<string> list = value.ReskinList.ConvertAll((ReskinBase x) => x.Name);
Action<string, string> action = MaybeUpdateSprites;
obj.AddScrollBox(name, list, "Current resprite for group \"" + value.name + "\"", action, (List<string>)null, (Update)1);
value.currentResprite = gunfig.Value(value.name);
foreach (ReskinBase reskin in value.ReskinList)
{
reskin.LoadCollections(reskin.Name == value.currentResprite);
}
}
}
public static void MaybeUpdateSprites(string key, string value)
{
if (ReskinLoader.groups.TryGetValue(key, out var value2))
{
if (value2.currentResprite != null && value2.TryGetReskin(value2.currentResprite, out var reskin))
{
reskin.UnapplyReplacements();
}
if (value2.TryGetReskin(value, out var reskin2))
{
reskin2.ApplyReplacements();
}
value2.currentResprite = value;
}
}
}
public static class ReskinLoader
{
public const string RESKIN_FILTER = "*-resprite.spapi";
public const string READMODE_GROUPNAME = "GroupName";
public const string READMODE_RESPRITENAME = "RespriteName";
public const string READMODE_RESPRITEFILES = "RespriteFiles";
public const string READMODE_ADVANCEDMODE = "AdvancedMode";
public static Dictionary<string, ReskinGroup> groups = new Dictionary<string, ReskinGroup>();
public static void LoadReskins()
{
string[] files = Directory.GetFiles(Paths.PluginPath, "*-resprite.spapi", SearchOption.AllDirectories);
if (files == null)
{
return;
}
string[] array = files;
foreach (string text in array)
{
string fileName = Path.GetFileName(text);
Debug.Log((object)("[Reskin Switcher] Reading resprite file: " + fileName));
if (!TryReadReskinData(text, out var groupName, out var replacementName, out var replacements, out var advancedMode))
{
continue;
}
if (Utility.IsNullOrWhiteSpace(groupName) || Utility.IsNullOrWhiteSpace(replacementName) || replacements.Count <= 0)
{
Debug.LogError((object)("Error reading resprite data file \"" + fileName + "\": GroupName, RespriteName and/or RespriteFiles are empty."));
continue;
}
if (replacementName == ReskinConfig.NoResprite || replacementName == ReskinConfig.RandomResprite)
{
Debug.LogError((object)("Error reading resprite data file \"" + fileName + "\": RespriteName cannot be a special name (" + replacementName + ")."));
continue;
}
List<ReplacementBase> list = ReadReplacementsForReskin(text, replacements, advancedMode);
if (list.Count > 0)
{
NamedReskin namedReskin = new NamedReskin
{
_name = replacementName,
replacements = list
};
if (!groups.TryGetValue(groupName, out var value))
{
Dictionary<string, ReskinGroup> dictionary = groups;
string key = groupName;
ReskinGroup obj = new ReskinGroup
{
name = groupName,
reskins = new Dictionary<string, NamedReskin>()
};
value = obj;
dictionary[key] = obj;
}
try
{
value.reskins.Add(replacementName, namedReskin);
namedReskin.group = value;
Debug.Log((object)("Successfully added resprite \"" + replacementName + "\" to group \"" + groupName + "\""));
}
catch
{
Debug.LogError((object)("Error loading resprite data file \"" + fileName + "\": resprite \"" + replacementName + "\" already exists."));
}
}
}
}
public static List<ReplacementBase> ReadReplacementsForReskin(string f, List<string> replacements, bool advanced)
{
string fileName = Path.GetFileName(f);
string directoryName = Path.GetDirectoryName(f);
List<ReplacementBase> list = new List<ReplacementBase>();
foreach (string replacement in replacements)
{
string text = Path.Combine(directoryName, replacement);
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(replacement);
if (replacement.EndsWith(".png"))
{
Texture2D tex;
if (!File.Exists(text))
{
Debug.LogError((object)("Error reading resprites for resprite data file \"" + fileName + "\": no file \"" + replacement + "\" exists in folder \"" + Path.GetFileName(directoryName) + "\"."));
}
else if (!TryReadImage(text, out tex))
{
Debug.LogError((object)("Error reading spritesheet resprite \"" + replacement + "\" for resprite data file \"" + fileName + "\": invalid image."));
}
else
{
list.Add(new SpritesheetReplacement
{
spritesheet = tex,
collName = fileNameWithoutExtension
});
}
continue;
}
if (!Directory.Exists(text))
{
Debug.LogError((object)("Error reading resprites for resprite data file \"" + fileName + "\": no folder \"" + replacement + "\" exists in folder \"" + Path.GetFileName(directoryName) + "\"."));
continue;
}
IndividualReplacement individualReplacement = new IndividualReplacement
{
collName = fileNameWithoutExtension,
definitionReplacements = new Dictionary<string, IndividualReplacement.DefinitionReplacementInfo>(),
advanced = advanced
};
string[] files = Directory.GetFiles(text, "*.png");
foreach (string text2 in files)
{
if (!TryReadImage(text2, out var tex2))
{
Debug.LogError((object)("Error reading individual resprite frame \"" + replacement + "/" + Path.GetFileName(text2) + "\" for resprite data file \"" + fileName + "\": invalid image."));
}
else if (!individualReplacement.definitionReplacements.ContainsKey(((Object)tex2).name))
{
individualReplacement.definitionReplacements[((Object)tex2).name] = new IndividualReplacement.DefinitionReplacementInfo
{
texture = tex2
};
}
else
{
Debug.LogError((object)("Error reading individual resprite frame \"" + replacement + "/" + Path.GetFileName(text2) + "\" for resprite data file \"" + fileName + "\": frame named \"" + ((Object)tex2).name + "\" already exists."));
}
}
if (individualReplacement.definitionReplacements.Count > 0)
{
list.Add(individualReplacement);
}
}
return list;
}
public static bool TryReadImage(string f, out Texture2D tex)
{
//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_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
tex = new Texture2D(1, 1, (TextureFormat)4, false)
{
filterMode = (FilterMode)0,
name = Path.GetFileNameWithoutExtension(f)
};
try
{
if (ImageConversion.LoadImage(tex, File.ReadAllBytes(f)))
{
return true;
}
}
catch
{
}
return false;
}
public static bool TryReadReskinData(string f, out string groupName, out string replacementName, out List<string> replacements, out bool advancedMode)
{
string fileName = Path.GetFileName(f);
groupName = "";
replacementName = "";
replacements = new List<string>();
advancedMode = false;
string[] array = File.ReadAllLines(f);
for (int i = 0; i < array.Length; i++)
{
string text = array[i];
if (Utility.IsNullOrWhiteSpace(text))
{
continue;
}
string text2 = text.Trim();
if (text2.StartsWith("#") && text2.Length > 1)
{
string text3 = text2.Substring(1).Trim().ToLowerInvariant();
if (Utility.IsNullOrWhiteSpace(text3))
{
continue;
}
List<string> property;
bool flag = TryReadDataProperty(array, ref i, out property);
if (text3 == "GroupName".ToLowerInvariant())
{
if (flag)
{
groupName = property.LastOrDefault();
}
continue;
}
if (text3 == "RespriteName".ToLowerInvariant())
{
if (flag)
{
replacementName = property.LastOrDefault();
}
continue;
}
if (text3 == "RespriteFiles".ToLowerInvariant())
{
if (flag)
{
replacements.AddRange(property);
}
continue;
}
if (text3 == "AdvancedMode".ToLowerInvariant())
{
if (flag)
{
if (bool.TryParse(property.Last().ToLowerInvariant(), out var result))
{
advancedMode = result;
}
else
{
Debug.LogError((object)("Error reading resprite data file \"" + fileName + "\": unexpected value for AdvancedMode. Value can only be \"true\" or \"false\""));
}
}
continue;
}
Debug.LogError((object)("Error reading resprite data file \"" + fileName + "\": read mode \"" + text3 + "\" doesn't exist."));
return false;
}
Debug.LogError((object)("Error reading resprite data file \"" + fileName + "\": unexpected line \"" + text + "\"."));
return false;
}
return true;
}
public static bool TryReadDataProperty(string[] lines, ref int index, out List<string> property)
{
property = new List<string>();
index++;
while (index < lines.Length)
{
string text = lines[index];
if (!Utility.IsNullOrWhiteSpace(text))
{
string text2 = text.Trim();
if (text2.StartsWith("#") && text2.Length > 1)
{
index--;
break;
}
property.Add(text2);
}
index++;
}
return property.Count > 0;
}
}
}