using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using Microsoft.CodeAnalysis;
using Shooterlatro.Core;
using Shooterlatro.Game;
using Shooterlatro.Shaders.DynamicWorldChange;
using Shooterlatro.Worlds;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("LuckyShotCustomWorldAPI")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+4135dd1490a61fe647f2a0e54287f36471f5cf7f")]
[assembly: AssemblyProduct("LuckyShotCustomWorldAPI")]
[assembly: AssemblyTitle("LuckyShotCustomWorldAPI")]
[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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace LuckyShot.CustomWorldAPI
{
public sealed class RunWorldRef
{
public WorldType? BuiltIn { get; set; }
public string CustomId { get; set; }
public static RunWorldRef BuiltIn_(WorldType t)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
return new RunWorldRef
{
BuiltIn = t
};
}
public static RunWorldRef Custom(string id)
{
return new RunWorldRef
{
CustomId = id
};
}
public override string ToString()
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
object obj = CustomId;
if (obj == null)
{
WorldType? builtIn = BuiltIn;
obj = (builtIn.HasValue ? ((object)builtIn.GetValueOrDefault()/*cast due to .constrained prefix*/).ToString() : null) ?? "?";
}
return (string)obj;
}
}
public sealed class CustomRun
{
public string Id { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public string OwnerModId { get; set; }
public int SequencePolicy { get; set; } = 1;
public List<RunWorldRef> Worlds { get; } = new List<RunWorldRef>();
public bool IsRegistered { get; internal set; }
public static CustomRun Create(string id, string displayName = null)
{
return new CustomRun
{
Id = id,
DisplayName = (displayName ?? id)
};
}
public CustomRun Described(string text)
{
Description = text;
return this;
}
public CustomRun WithOwner(string owner)
{
OwnerModId = owner;
return this;
}
public CustomRun Stable()
{
SequencePolicy = 1;
return this;
}
public CustomRun Shuffled()
{
SequencePolicy = 0;
return this;
}
public CustomRun AddBuiltIn(WorldType t)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
Worlds.Add(RunWorldRef.BuiltIn_(t));
return this;
}
public CustomRun AddCustom(string id)
{
Worlds.Add(RunWorldRef.Custom(id));
return this;
}
public CustomRun Register(string ownerModId = null)
{
return CustomRuns.Register(this, ownerModId);
}
public override string ToString()
{
return Id + " (" + Worlds.Count + " worlds)";
}
}
public static class CustomRuns
{
private static readonly object Sync = new object();
private static readonly Dictionary<string, CustomRun> Runs = new Dictionary<string, CustomRun>(StringComparer.OrdinalIgnoreCase);
public static IReadOnlyCollection<CustomRun> All
{
get
{
lock (Sync)
{
return new List<CustomRun>(Runs.Values).AsReadOnly();
}
}
}
public static event Action<CustomRun> Registered;
public static event Action<CustomRun> Started;
public static event Action<CustomRun> Aborted;
public static CustomRun Get(string id)
{
if (string.IsNullOrWhiteSpace(id))
{
return null;
}
lock (Sync)
{
CustomRun value;
return Runs.TryGetValue(id, out value) ? value : null;
}
}
public static bool IsActive(string id)
{
lock (Sync)
{
if (!Runs.TryGetValue(id, out var value))
{
return false;
}
return value.Worlds.Count > 0 && value.IsRegistered && value.Worlds.Exists((RunWorldRef w) => string.IsNullOrEmpty(w.CustomId) || CustomWorlds.IsRegistered(w.CustomId));
}
}
public static bool Abort(string id)
{
CustomRun value;
lock (Sync)
{
if (!Runs.TryGetValue(id, out value))
{
return false;
}
value.IsRegistered = false;
Runs.Remove(id);
}
try
{
CustomRuns.Aborted?.Invoke(value);
}
catch
{
}
return true;
}
public static CustomRun Register(CustomRun run, string ownerModId = null)
{
if (run == null)
{
throw new ArgumentNullException("run");
}
if (string.IsNullOrWhiteSpace(run.Id))
{
throw new ArgumentException("CustomRun.Id must be set.", "run");
}
if (string.IsNullOrWhiteSpace(run.DisplayName))
{
run.DisplayName = run.Id;
}
lock (Sync)
{
if (Runs.ContainsKey(run.Id))
{
return null;
}
run.OwnerModId = ownerModId ?? InferOwner();
Runs[run.Id] = run;
run.IsRegistered = true;
}
try
{
CustomRuns.Registered?.Invoke(run);
}
catch
{
}
return run;
}
public static bool Unregister(string id)
{
lock (Sync)
{
if (!Runs.TryGetValue(id, out var value))
{
return false;
}
Runs.Remove(id);
value.IsRegistered = false;
}
return true;
}
public static void Cleanup()
{
lock (Sync)
{
List<string> list = new List<string>();
foreach (KeyValuePair<string, CustomRun> run in Runs)
{
CustomRun value = run.Value;
value.IsRegistered = false;
list.Add(run.Key);
try
{
CustomRuns.Aborted?.Invoke(value);
}
catch
{
}
}
foreach (string item in list)
{
Runs.Remove(item);
}
}
}
public static bool Start(string id)
{
if (IsActive(id))
{
return false;
}
CustomRun customRun = Get(id);
if (customRun == null)
{
return false;
}
ScenarioManager val = ScenarioInjector.ManagerPublic();
if ((Object)(object)val == (Object)null)
{
return false;
}
foreach (RunWorldRef world in customRun.Worlds)
{
if (!string.IsNullOrEmpty(world.CustomId))
{
CustomWorlds.Get(world.CustomId);
}
}
List<ScenarioInstance> list = new List<ScenarioInstance>();
List<ScenarioInstance> list2 = new List<ScenarioInstance>(val.scenarios);
foreach (RunWorldRef w in customRun.Worlds)
{
ScenarioInstance val2 = null;
if (!string.IsNullOrEmpty(w.CustomId))
{
val2 = CustomWorlds.Get(w.CustomId)?.Instance;
}
else if (w.BuiltIn.HasValue)
{
val2 = list2.Find((ScenarioInstance s) => (Object)(object)s != (Object)null && (Object)(object)s.asset != (Object)null && s.asset.worldType == w.BuiltIn.Value);
}
if ((Object)(object)val2 != (Object)null)
{
list.Add(val2);
}
}
foreach (ScenarioInstance item in list2)
{
if ((Object)(object)item != (Object)null && !list.Contains(item))
{
list.Add(item);
}
}
val.scenarios.Clear();
val.scenarios.AddRange(list);
val.SequencePolicy = customRun.SequencePolicy;
val.ResetSequence();
try
{
CustomRuns.Started?.Invoke(customRun);
}
catch
{
}
return true;
}
public static string[] Names()
{
List<string> list = new List<string>();
foreach (CustomRun item in All)
{
list.Add(item.Id + " - " + item.DisplayName + " [" + item.Worlds.Count + "]");
}
return list.ToArray();
}
private static string InferOwner()
{
try
{
string text = Assembly.GetCallingAssembly()?.GetName()?.Name;
return string.IsNullOrEmpty(text) ? "unknown" : text;
}
catch
{
return "unknown";
}
}
}
public sealed class CustomWorld
{
public string Id { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public WorldType Category { get; set; }
public string OwnerModId { get; set; }
public Texture SkyboxTexture { get; set; }
public Color SkyboxTint { get; set; } = Color.white;
public float SkyboxExposure { get; set; } = 1f;
public float SkyboxRotation { get; set; }
public bool OverrideLight { get; set; }
public Color LightColor { get; set; } = Color.white;
public float LightIntensity { get; set; } = 1f;
public Vector3 LightRotation { get; set; } = new Vector3(50f, -30f, 0f);
public float Radius { get; set; } = 100f;
internal ScenarioInstance Instance { get; set; }
public bool IsRegistered { get; internal set; }
public static CustomWorld Create(string id, string displayName = null)
{
return new CustomWorld
{
Id = id,
DisplayName = (displayName ?? id)
};
}
public CustomWorld Described(string text)
{
Description = text;
return this;
}
public CustomWorld WithCategory(WorldType c)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
Category = c;
return this;
}
public CustomWorld WithOwner(string owner)
{
OwnerModId = owner;
return this;
}
public CustomWorld WithSkybox(Texture tex)
{
SkyboxTexture = tex;
return this;
}
public CustomWorld WithSkyboxTint(Color c)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
SkyboxTint = c;
return this;
}
public CustomWorld WithSkyboxExposure(float e)
{
SkyboxExposure = e;
return this;
}
public CustomWorld WithSkyboxRotation(float deg)
{
SkyboxRotation = deg;
return this;
}
public CustomWorld WithLight(Color color, float intensity)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
OverrideLight = true;
LightColor = color;
LightIntensity = intensity;
return this;
}
public CustomWorld WithLightRotation(Vector3 euler)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
LightRotation = euler;
return this;
}
public CustomWorld WithRadius(float r)
{
Radius = r;
return this;
}
public CustomWorld Register(string ownerModId = null)
{
return CustomWorlds.Register(this, ownerModId);
}
public override string ToString()
{
return Id + " (" + DisplayName + ")";
}
}
public static class CustomWorlds
{
private static readonly object Sync = new object();
private static readonly Dictionary<string, CustomWorld> Worlds = new Dictionary<string, CustomWorld>(StringComparer.OrdinalIgnoreCase);
private static readonly List<CustomWorld> Pending = new List<CustomWorld>();
private static bool _hooked;
public static IReadOnlyCollection<CustomWorld> All
{
get
{
lock (Sync)
{
return new List<CustomWorld>(Worlds.Values).AsReadOnly();
}
}
}
public static event Action<CustomWorld> Registered;
public static event Action<CustomWorld> Unregistered;
public static event Action<CustomWorld> Activating;
public static CustomWorld Get(string id)
{
if (string.IsNullOrWhiteSpace(id))
{
return null;
}
lock (Sync)
{
CustomWorld value;
return Worlds.TryGetValue(id, out value) ? value : null;
}
}
public static CustomWorld Register(CustomWorld world, string ownerModId = null)
{
if (world == null)
{
throw new ArgumentNullException("world");
}
if (string.IsNullOrWhiteSpace(world.Id))
{
throw new ArgumentException("CustomWorld.Id must be set.", "world");
}
if (string.IsNullOrWhiteSpace(world.DisplayName))
{
world.DisplayName = world.Id;
}
lock (Sync)
{
if (Worlds.ContainsKey(world.Id) || Pending.Exists((CustomWorld p) => string.Equals(p.Id, world.Id, StringComparison.OrdinalIgnoreCase)))
{
return null;
}
world.OwnerModId = ownerModId ?? InferOwner();
EnsureHook();
if (ScenarioInjector.ManagerAvailable())
{
InjectNow(world);
}
else
{
Pending.Add(world);
}
}
return world;
}
public static bool Unregister(string id)
{
CustomWorld value;
lock (Sync)
{
if (!Worlds.TryGetValue(id, out value))
{
CustomWorld customWorld = Pending.Find((CustomWorld x) => string.Equals(x.Id, id, StringComparison.OrdinalIgnoreCase));
if (customWorld != null)
{
Pending.Remove(customWorld);
customWorld.IsRegistered = false;
return true;
}
return false;
}
ScenarioInjector.Remove(value.Instance);
value.IsRegistered = false;
Worlds.Remove(id);
}
try
{
CustomWorlds.Unregistered?.Invoke(value);
}
catch
{
}
return true;
}
public static bool Activate(string id)
{
CustomWorld customWorld;
lock (Sync)
{
customWorld = Get(id);
if (customWorld == null || (Object)(object)customWorld.Instance == (Object)null)
{
return false;
}
}
try
{
CustomWorlds.Activating?.Invoke(customWorld);
}
catch
{
}
return ScenarioInjector.Activate(customWorld.Instance);
}
public static void ClearPending()
{
lock (Sync)
{
Pending.Clear();
}
}
public static void Cleanup()
{
lock (Sync)
{
CustomWorld[] array = Worlds.Values.ToArray();
foreach (CustomWorld customWorld in array)
{
ScenarioInjector.Remove(customWorld.Instance);
customWorld.IsRegistered = false;
Worlds.Remove(customWorld.Id);
try
{
CustomWorlds.Unregistered?.Invoke(customWorld);
}
catch
{
}
}
Pending.Clear();
}
}
public static string[] Names()
{
List<string> list = new List<string>();
foreach (CustomWorld item in All)
{
list.Add(item.Id + " - " + item.DisplayName);
}
return list.ToArray();
}
public static bool IsRegistered(string id)
{
lock (Sync)
{
return Worlds.ContainsKey(id) || Pending.Exists((CustomWorld p) => string.Equals(p.Id, id, StringComparison.OrdinalIgnoreCase));
}
}
private static void EnsureHook()
{
if (!_hooked)
{
_hooked = true;
GameEvents.OnGameStarted += HandleGameStarted;
}
}
private static void HandleGameStarted(OnGameStartedContext ctx)
{
List<CustomWorld> list;
lock (Sync)
{
if (Pending.Count == 0)
{
return;
}
list = new List<CustomWorld>(Pending);
Pending.Clear();
}
foreach (CustomWorld item in list)
{
lock (Sync)
{
InjectNow(item);
}
try
{
CustomWorlds.Registered?.Invoke(item);
}
catch
{
}
}
}
private static void InjectNow(CustomWorld world)
{
world.Instance = ScenarioFactory.CreateInstance(world);
world.IsRegistered = ScenarioInjector.Inject(world.Instance);
if (world.IsRegistered)
{
Worlds[world.Id] = world;
}
try
{
CustomWorlds.Registered?.Invoke(world);
}
catch
{
}
}
private static string InferOwner()
{
try
{
string text = Assembly.GetCallingAssembly()?.GetName()?.Name;
return string.IsNullOrEmpty(text) ? "unknown" : text;
}
catch
{
return "unknown";
}
}
}
[BepInPlugin("com.luckyshot.wiki.customworldapi", "LuckyShot Custom World API", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
private void Awake()
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"LuckyShot Custom World API loaded (library only, no demos, no in-game keys).");
((BaseUnityPlugin)this).Logger.LogInfo((object)"Mods: use CustomWorld.Create(...).Register() and CustomRun.Create(...).Register(); then CustomRuns.Start(id).");
}
}
internal static class PluginInfo
{
public const string GUID = "com.luckyshot.wiki.customworldapi";
public const string NAME = "LuckyShot Custom World API";
public const string VERSION = "1.0.0";
}
internal static class ScenarioFactory
{
public static ScenarioInstance CreateInstance(CustomWorld w)
{
//IL_0014: 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_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0074: 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_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
ScenarioAsset val = ScriptableObject.CreateInstance<ScenarioAsset>();
val.displayName = w.DisplayName;
val.worldType = w.Category;
val.skyboxTexture = w.SkyboxTexture;
val.skyboxTint = w.SkyboxTint;
val.skyboxExposure = w.SkyboxExposure;
val.skyboxRotation = w.SkyboxRotation;
val.overrideDirectionalLight = w.OverrideLight;
val.directionalLightColor = w.LightColor;
val.directionalLightIntensity = w.LightIntensity;
val.directionalLightRotation = w.LightRotation;
val.radiusTarget = w.Radius;
ScenarioInstance obj = new GameObject("CustomWorld_" + w.Id)
{
hideFlags = (HideFlags)61
}.AddComponent<ScenarioInstance>();
obj.asset = val;
return obj;
}
}
internal static class ScenarioInjector
{
private static ScenarioManager Manager()
{
GameManager instance = GameManager.Instance;
if (!((Object)(object)instance != (Object)null))
{
return null;
}
return instance.scenarioManager;
}
public static ScenarioManager ManagerPublic()
{
return Manager();
}
public static bool ManagerAvailable()
{
return (Object)(object)Manager() != (Object)null;
}
public static bool Inject(ScenarioInstance inst)
{
ScenarioManager val = Manager();
if ((Object)(object)val == (Object)null || (Object)(object)inst == (Object)null)
{
return false;
}
if (!val.scenarios.Contains(inst))
{
val.scenarios.Add(inst);
}
return true;
}
public static void Remove(ScenarioInstance inst)
{
ScenarioManager val = Manager();
if ((Object)(object)val != (Object)null && (Object)(object)inst != (Object)null)
{
val.scenarios.Remove(inst);
}
}
public static bool Activate(ScenarioInstance inst)
{
ScenarioManager val = Manager();
if ((Object)(object)val == (Object)null || (Object)(object)inst == (Object)null)
{
return false;
}
val.PreviewActivateScenario(inst);
return true;
}
}
}