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.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Extensions;
using HarmonyLib;
using Mirror;
using MoreMountains.Feedbacks;
using MoreMountains.Tools;
using TryConnect.Utils;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("TryConnect")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TryConnect")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("763c314a-61d3-4716-bc7f-118e5a9364ce")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TryConnect
{
[DisallowMultipleComponent]
public sealed class TryConnectInteractableProxy : MonoBehaviour, IInteractable
{
[SerializeField]
private MonoBehaviour _targetBehaviour;
private IInteractable Target
{
get
{
if ((Object)(object)_targetBehaviour == (Object)null || !(_targetBehaviour is IInteractable))
{
_targetBehaviour = ResolveTargetBehaviour();
}
MonoBehaviour targetBehaviour = _targetBehaviour;
return (IInteractable)(object)((targetBehaviour is IInteractable) ? targetBehaviour : null);
}
}
public float HoldDuration
{
get
{
return (Target != null) ? Target.HoldDuration : 0f;
}
set
{
IInteractable target = Target;
if (target != null)
{
target.HoldDuration = value;
}
}
}
public bool HoldInteract
{
get
{
return Target != null && Target.HoldInteract;
}
set
{
IInteractable target = Target;
if (target != null)
{
target.HoldInteract = value;
}
}
}
public bool IsInteractable
{
get
{
return Target != null && Target.IsInteractable;
}
set
{
IInteractable target = Target;
if (target != null)
{
target.IsInteractable = value;
}
}
}
public bool MeetRequirements
{
get
{
return Target != null && Target.MeetRequirements;
}
set
{
IInteractable target = Target;
if (target != null)
{
target.MeetRequirements = value;
}
}
}
public bool IsBeingHovered
{
get
{
return Target != null && Target.IsBeingHovered;
}
set
{
IInteractable target = Target;
if (target != null)
{
target.IsBeingHovered = value;
}
}
}
public bool IsBeingHold
{
get
{
return Target != null && Target.IsBeingHold;
}
set
{
IInteractable target = Target;
if (target != null)
{
target.IsBeingHold = value;
}
}
}
public float HoldProgress
{
get
{
return (Target != null) ? Target.HoldProgress : 0f;
}
set
{
IInteractable target = Target;
if (target != null)
{
target.HoldProgress = value;
}
}
}
public string TooltipMessage
{
get
{
return (Target != null) ? Target.TooltipMessage : string.Empty;
}
set
{
IInteractable target = Target;
if (target != null)
{
target.TooltipMessage = value;
}
}
}
public string InteractableName
{
get
{
return (Target != null) ? Target.InteractableName : string.Empty;
}
set
{
IInteractable target = Target;
if (target != null)
{
target.InteractableName = value;
}
}
}
public CursorType CursorType
{
get
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
return (CursorType)((Target != null) ? ((int)Target.CursorType) : 0);
}
set
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
IInteractable target = Target;
if (target != null)
{
target.CursorType = value;
}
}
}
public event Action<IInteractable> OnInteractableChanged
{
add
{
IInteractable target = Target;
if (target != null)
{
target.OnInteractableChanged += value;
}
}
remove
{
IInteractable target = Target;
if (target != null)
{
target.OnInteractableChanged -= value;
}
}
}
internal void Bind(MonoBehaviour targetBehaviour)
{
_targetBehaviour = targetBehaviour;
}
public void OnHover(PlayerInteract playerInteract)
{
IInteractable target = Target;
if (target != null)
{
target.OnHover(playerInteract);
}
}
public void ServerOnHover(PlayerInteract playerInteract)
{
IInteractable target = Target;
if (target != null)
{
target.ServerOnHover(playerInteract);
}
}
public void OnHoverExit(PlayerInteract playerInteract)
{
IInteractable target = Target;
if (target != null)
{
target.OnHoverExit(playerInteract);
}
}
public void ServerOnHoverExit(PlayerInteract playerInteract)
{
IInteractable target = Target;
if (target != null)
{
target.ServerOnHoverExit(playerInteract);
}
}
public void OnHold(PlayerInteract playerInteract)
{
IInteractable target = Target;
if (target != null)
{
target.OnHold(playerInteract);
}
}
public void ServerOnHold(PlayerInteract playerInteract)
{
IInteractable target = Target;
if (target != null)
{
target.ServerOnHold(playerInteract);
}
}
public void OnHoldExit(PlayerInteract playerInteract)
{
IInteractable target = Target;
if (target != null)
{
target.OnHoldExit(playerInteract);
}
}
public void ServerOnHoldExit(PlayerInteract playerInteract)
{
IInteractable target = Target;
if (target != null)
{
target.ServerOnHoldExit(playerInteract);
}
}
public void OnInteract(PlayerInteract playerInteract)
{
IInteractable target = Target;
if (target != null)
{
target.OnInteract(playerInteract);
}
}
public void ServerOnInteract(PlayerInteract playerInteract)
{
IInteractable target = Target;
if (target != null)
{
target.ServerOnInteract(playerInteract);
}
}
public void RpcOnInteract(PlayerInteract playerInteract)
{
IInteractable target = Target;
if (target != null)
{
target.RpcOnInteract(playerInteract);
}
}
private MonoBehaviour ResolveTargetBehaviour()
{
Transform parent = ((Component)this).transform.parent;
while ((Object)(object)parent != (Object)null)
{
MonoBehaviour[] components = ((Component)parent).GetComponents<MonoBehaviour>();
foreach (MonoBehaviour val in components)
{
if ((Object)(object)val != (Object)null && val is IInteractable)
{
return val;
}
}
parent = parent.parent;
}
return null;
}
}
internal static class RuntimeItemRegistry
{
private sealed class CustomItemDefinition
{
internal string OwnerGuid;
internal string Key;
internal uint AssetId;
internal GameObject BasePrefab;
internal GameObject SpawnPrefab;
internal int BasePrice;
internal string Description;
internal string DisplayName;
internal GameObject MarkerPrefab;
internal bool ApplyTint;
internal Vector3 ModelScaleMultiplier;
internal int PriceIncreasePerFloor;
internal int ReplacementChancePercent;
internal SpawnableSO Spawnable;
internal Color Tint;
}
private sealed class CustomItemRequest
{
internal string OwnerGuid;
internal string Key;
internal int SpawnableId;
internal uint AssetId;
internal string DisplayName;
internal string Description;
internal SpawnableSO BaseSpawnable;
internal int BaseSpawnableId;
internal Type BaseItemComponentType;
internal GameObject CustomPrefab;
internal GameObject MarkerPrefab;
internal bool ApplyTint;
internal Color Tint;
internal Vector3 ModelScaleMultiplier;
internal int ReplacementChancePercent;
internal int ExtraBasePrice;
internal int ExtraFloorPrice;
internal bool HasLoggedBuildFailure;
}
private const int TicketFizzSpawnableId = 900001;
private const int LoadedChipSpawnableId = 900002;
private static readonly Dictionary<int, CustomItemRequest> RequestsBySpawnableId = new Dictionary<int, CustomItemRequest>();
private static readonly Dictionary<string, CustomItemRequest> RequestsByUniqueKey = new Dictionary<string, CustomItemRequest>(StringComparer.OrdinalIgnoreCase);
private static readonly Dictionary<uint, CustomItemRequest> RequestsByAssetId = new Dictionary<uint, CustomItemRequest>();
private static readonly Dictionary<int, CustomItemDefinition> DefinitionsBySpawnableId = new Dictionary<int, CustomItemDefinition>();
private static readonly Dictionary<uint, CustomItemDefinition> DefinitionsByAssetId = new Dictionary<uint, CustomItemDefinition>();
private static readonly Dictionary<GameObject, CustomItemDefinition> DefinitionsByMarkerPrefab = new Dictionary<GameObject, CustomItemDefinition>();
private static readonly Dictionary<GameObject, List<CustomItemDefinition>> DefinitionsByBasePrefab = new Dictionary<GameObject, List<CustomItemDefinition>>();
private static readonly MethodInfo SetParentHierarchyAfterDelayMethod = AccessTools.Method(typeof(ItemStamp), "SetParentHierarchyAfterDelay", (Type[])null, (Type[])null);
private static readonly FieldInfo AssetIdField = AccessTools.Field(typeof(NetworkIdentity), "_assetId");
private static readonly FieldInfo SpawnHandlersField = AccessTools.Field(typeof(NetworkClient), "spawnHandlers");
private static TryConnectPlugin _plugin;
private static bool _builtInRegistrationsAdded;
internal static void Initialize(TryConnectPlugin plugin)
{
_plugin = plugin;
EnsureBuiltInRegistrations();
}
internal static void Dispose()
{
foreach (CustomItemDefinition value in DefinitionsBySpawnableId.Values)
{
NetworkClient.UnregisterSpawnHandler(value.AssetId);
if ((Object)(object)value.MarkerPrefab != (Object)null)
{
Object.Destroy((Object)(object)value.MarkerPrefab);
}
if ((Object)(object)value.Spawnable != (Object)null)
{
Object.Destroy((Object)(object)value.Spawnable);
}
}
RequestsBySpawnableId.Clear();
RequestsByUniqueKey.Clear();
RequestsByAssetId.Clear();
DefinitionsBySpawnableId.Clear();
DefinitionsByAssetId.Clear();
DefinitionsByMarkerPrefab.Clear();
DefinitionsByBasePrefab.Clear();
_builtInRegistrationsAdded = false;
_plugin = null;
}
internal static TryConnectRegistrationResult RegisterCustomItem(TryConnectItemRegistration registration)
{
EnsureBuiltInRegistrations();
if (!TryNormalizeRegistration(registration))
{
return TryConnectRegistrationResult.InvalidRegistration;
}
string key = BuildUniqueKey(registration.OwnerGuid, registration.Key);
if (RequestsByUniqueKey.ContainsKey(key) || RequestsBySpawnableId.ContainsKey(registration.SpawnableId))
{
return TryConnectRegistrationResult.AlreadyRegistered;
}
AddRequest(CreateRequest(registration));
TryRegisterRuntimeContent();
return TryConnectRegistrationResult.Accepted;
}
internal static void TryRegisterRuntimeContent()
{
EnsureBuiltInRegistrations();
if ((Object)(object)_plugin == (Object)null)
{
return;
}
SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
if ((Object)(object)val == (Object)null || !val.isEnabled)
{
return;
}
ItemPriceSettings priceSettings = Resources.Load<ItemPriceSettings>("ItemPriceSettings");
bool flag = false;
foreach (CustomItemRequest value in RequestsBySpawnableId.Values)
{
flag |= EnsureDefinition(val, priceSettings, value);
}
TryEnsureAllClientRegistrations();
if (flag)
{
val.NotifyChanged();
TryConnectPlugin.Log.LogInfo((object)$"Registered {DefinitionsBySpawnableId.Count} runtime custom item(s).");
}
}
internal static void TryEnsureAllClientRegistrations()
{
foreach (CustomItemDefinition value in DefinitionsBySpawnableId.Values)
{
EnsureClientSpawnHandler(value);
}
}
internal static void TryEnsureClientRegistration(uint assetId)
{
if (!DefinitionsByAssetId.TryGetValue(assetId, out var value))
{
value = TryBuildDefinitionForAssetId(assetId);
}
if (value != null)
{
EnsureClientSpawnHandler(value);
}
}
internal static SpawnableSO GetCustomSpawnable(int id)
{
if (!DefinitionsBySpawnableId.TryGetValue(id, out var value))
{
value = TryBuildDefinitionForSpawnableId(id);
}
return value?.Spawnable;
}
internal static bool TryGetRegisteredItemInfo(int spawnableId, out TryConnectRegisteredItemInfo itemInfo)
{
itemInfo = null;
if (!RequestsBySpawnableId.TryGetValue(spawnableId, out var value))
{
return false;
}
CustomItemDefinition value2;
bool flag = DefinitionsBySpawnableId.TryGetValue(spawnableId, out value2);
itemInfo = new TryConnectRegisteredItemInfo(value.OwnerGuid, value.Key, value.SpawnableId, value.AssetId, value.DisplayName, value.Description, flag ? value2.Spawnable : null, flag);
return true;
}
internal static TryConnectRegisteredItemInfo[] GetRegisteredItemInfos()
{
List<TryConnectRegisteredItemInfo> list = new List<TryConnectRegisteredItemInfo>(RequestsBySpawnableId.Count);
foreach (CustomItemRequest value2 in RequestsBySpawnableId.Values)
{
CustomItemDefinition value;
bool flag = DefinitionsBySpawnableId.TryGetValue(value2.SpawnableId, out value);
list.Add(new TryConnectRegisteredItemInfo(value2.OwnerGuid, value2.Key, value2.SpawnableId, value2.AssetId, value2.DisplayName, value2.Description, flag ? value.Spawnable : null, flag));
}
list.Sort((TryConnectRegisteredItemInfo left, TryConnectRegisteredItemInfo right) => left.SpawnableId.CompareTo(right.SpawnableId));
return list.ToArray();
}
internal static bool TryGetVanillaSpawnable(int spawnableId, out SpawnableSO spawnable)
{
spawnable = null;
SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
if ((Object)(object)val == (Object)null)
{
return false;
}
return TryFindSpawnable(val, (SpawnableSO candidate) => (Object)(object)candidate != (Object)null && candidate.spawnableID == spawnableId, out spawnable);
}
internal static bool TryFindVanillaSpawnable(string searchTerm, out SpawnableSO spawnable)
{
spawnable = null;
if (string.IsNullOrWhiteSpace(searchTerm))
{
return false;
}
SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
if ((Object)(object)val == (Object)null)
{
return false;
}
string trimmed = searchTerm.Trim();
return TryFindSpawnable(val, delegate(SpawnableSO candidate)
{
if ((Object)(object)candidate == (Object)null)
{
return false;
}
if (string.Equals(candidate.spawnableName, trimmed, StringComparison.OrdinalIgnoreCase))
{
return true;
}
return string.Equals(((Object)candidate).name, trimmed, StringComparison.OrdinalIgnoreCase) || ((Object)(object)candidate.prefab != (Object)null && string.Equals(((Object)candidate.prefab).name, trimmed, StringComparison.OrdinalIgnoreCase));
}, out spawnable);
}
internal static bool TryGetCustomBasePrice(SpawnableSO spawnableSO, ref int basePrice)
{
if (!TryGetDefinition(spawnableSO, out var definition))
{
definition = TryBuildDefinitionForSpawnableId(((Object)(object)spawnableSO != (Object)null) ? spawnableSO.spawnableID : 0);
if (definition == null)
{
return false;
}
}
basePrice = definition.BasePrice;
return true;
}
internal static bool TryGetCustomFloorPrice(SpawnableSO spawnableSO, ref int priceIncreasePerFloor)
{
if (!TryGetDefinition(spawnableSO, out var definition))
{
definition = TryBuildDefinitionForSpawnableId(((Object)(object)spawnableSO != (Object)null) ? spawnableSO.spawnableID : 0);
if (definition == null)
{
return false;
}
}
priceIncreasePerFloor = definition.PriceIncreasePerFloor;
return true;
}
internal static bool TryGetCustomDescription(SpawnableSO spawnableSO, ref string description)
{
if (!TryGetDefinition(spawnableSO, out var definition))
{
definition = TryBuildDefinitionForSpawnableId(((Object)(object)spawnableSO != (Object)null) ? spawnableSO.spawnableID : 0);
if (definition == null)
{
return false;
}
}
description = definition.Description;
return true;
}
internal static GameObject GetShopReplacement(MMLootTableGameObjectSO lootTable, Vector3 stampPosition, GameObject fallbackPrefab)
{
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)fallbackPrefab == (Object)null)
{
return null;
}
if (!DefinitionsByBasePrefab.TryGetValue(fallbackPrefab, out var value) || value.Count == 0)
{
return fallbackPrefab;
}
int seed = 0;
if ((Object)(object)NetworkSingleton<SeededRandomManager>.Instance != (Object)null)
{
seed = NetworkSingleton<SeededRandomManager>.Instance.CurrentSeed;
}
string text = (((Object)(object)lootTable != (Object)null) ? ((Object)lootTable).name : "ItemStamp");
int deterministicPercent = ModUtils.GetDeterministicPercent(stampPosition, seed, text + "|" + ((Object)fallbackPrefab).name);
int num = 0;
for (int i = 0; i < value.Count; i++)
{
num += value[i].ReplacementChancePercent;
if (deterministicPercent < num)
{
return value[i].MarkerPrefab;
}
}
return fallbackPrefab;
}
internal static bool TrySpawnCustomItemStampPrefab(ItemStamp stamp, GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale)
{
//IL_0012: 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_0014: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)stamp == (Object)null)
{
return false;
}
return TrySpawnRegisteredPrefab(prefab, position, rotation, scale, stamp);
}
internal static bool TrySpawnConsolePrefab(GameObject prefab, Vector3 position)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
return TrySpawnRegisteredPrefab(prefab, position, Quaternion.identity, Vector3.one, null);
}
private static bool TrySpawnRegisteredPrefab(GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale, ItemStamp stamp)
{
//IL_002c: 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_0036: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)prefab == (Object)null || !DefinitionsByMarkerPrefab.TryGetValue(prefab, out var value))
{
return false;
}
GameObject val = Object.Instantiate<GameObject>(value.SpawnPrefab, position, rotation);
ApplyDefinitionToServerInstance(value, val, scale);
NetworkServer.Spawn(val, value.AssetId, (NetworkConnectionToClient)null);
TryConnectPlugin.Log.LogInfo((object)$"Spawned custom item '{value.DisplayName}'.");
if ((Object)(object)stamp != (Object)null && (Object)(object)NetworkSingleton<ItemStampManager>.Instance != (Object)null)
{
NetworkSingleton<ItemStampManager>.Instance.RegisterSpawnedInstance(val, stamp);
StartParentHierarchyCoroutine(stamp, val);
}
return true;
}
private static void StartParentHierarchyCoroutine(ItemStamp stamp, GameObject spawnedObject)
{
if (!(SetParentHierarchyAfterDelayMethod == null) && SetParentHierarchyAfterDelayMethod.Invoke(stamp, new object[1] { spawnedObject }) is IEnumerator enumerator)
{
((MonoBehaviour)stamp).StartCoroutine(enumerator);
}
}
private static bool EnsureDefinition(SpawnableSettings spawnableSettings, ItemPriceSettings priceSettings, CustomItemRequest request)
{
if (request == null)
{
return false;
}
if (!DefinitionsBySpawnableId.TryGetValue(request.SpawnableId, out var value))
{
value = BuildDefinition(spawnableSettings, priceSettings, request);
if (value == null)
{
return false;
}
CacheDefinition(value);
}
return EnsureDefinition(spawnableSettings, value);
}
private static bool EnsureDefinition(SpawnableSettings spawnableSettings, CustomItemDefinition definition)
{
if (definition == null || (Object)(object)definition.Spawnable == (Object)null)
{
return false;
}
bool flag = false;
for (int i = 0; i < spawnableSettings.spawnables.Count; i++)
{
SpawnableSO val = spawnableSettings.spawnables[i];
if ((Object)(object)val != (Object)null && val.spawnableID == definition.Spawnable.spawnableID)
{
flag = true;
break;
}
}
if (!flag)
{
spawnableSettings.spawnables.Add(definition.Spawnable);
return true;
}
return false;
}
private static void EnsureBuiltInRegistrations()
{
//IL_00b5: 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_00cf: 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_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_019b: Unknown result type (might be due to invalid IL or missing references)
if (!_builtInRegistrationsAdded && !((Object)(object)_plugin == (Object)null) && TryConnectPlugin.EnableCustomItems != null && TryConnectPlugin.EnableCustomItems.Value)
{
_builtInRegistrationsAdded = true;
CustomItemRequest customItemRequest = new CustomItemRequest();
customItemRequest.OwnerGuid = "com.Try-4646.TryConnect";
customItemRequest.Key = "ticket_fizz";
customItemRequest.SpawnableId = 900001;
customItemRequest.AssetId = ModUtils.GetStableAssetId("com.Try-4646.TryConnect", "ticket_fizz");
customItemRequest.DisplayName = "Ticket Fizz";
customItemRequest.Description = "A TryConnect house drink. Behaves like the vanilla Drink, but shows up as injected custom shop loot.";
customItemRequest.BaseItemComponentType = typeof(Drink);
customItemRequest.ApplyTint = true;
customItemRequest.Tint = new Color(0.22f, 0.95f, 0.92f);
customItemRequest.ModelScaleMultiplier = new Vector3(1.08f, 1.08f, 1.08f);
customItemRequest.ReplacementChancePercent = ModUtils.ClampPercent(TryConnectPlugin.TicketFizzReplacementChance.Value);
customItemRequest.ExtraBasePrice = 2;
customItemRequest.ExtraFloorPrice = 1;
AddRequest(customItemRequest);
customItemRequest = new CustomItemRequest();
customItemRequest.OwnerGuid = "com.Try-4646.TryConnect";
customItemRequest.Key = "loaded_chip";
customItemRequest.SpawnableId = 900002;
customItemRequest.AssetId = ModUtils.GetStableAssetId("com.Try-4646.TryConnect", "loaded_chip");
customItemRequest.DisplayName = "Loaded Chip";
customItemRequest.Description = "A counterfeit high-roller token. Behaves like the vanilla Golden Chip when applied to a game.";
customItemRequest.BaseItemComponentType = typeof(GoldenChip);
customItemRequest.ApplyTint = true;
customItemRequest.Tint = new Color(1f, 0.72f, 0.12f);
customItemRequest.ModelScaleMultiplier = new Vector3(1.12f, 1.12f, 1.12f);
customItemRequest.ReplacementChancePercent = ModUtils.ClampPercent(TryConnectPlugin.LoadedChipReplacementChance.Value);
customItemRequest.ExtraBasePrice = 3;
customItemRequest.ExtraFloorPrice = 1;
AddRequest(customItemRequest);
}
}
private static void AddRequest(CustomItemRequest request)
{
RequestsBySpawnableId.Add(request.SpawnableId, request);
RequestsByUniqueKey.Add(BuildUniqueKey(request.OwnerGuid, request.Key), request);
RequestsByAssetId.Add(request.AssetId, request);
}
private static CustomItemRequest CreateRequest(TryConnectItemRegistration registration)
{
//IL_00ac: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
return new CustomItemRequest
{
OwnerGuid = registration.OwnerGuid,
Key = registration.Key,
SpawnableId = registration.SpawnableId,
AssetId = ModUtils.GetStableAssetId(registration.OwnerGuid, registration.Key),
DisplayName = registration.DisplayName,
Description = (registration.Description ?? string.Empty),
BaseSpawnable = registration.BaseSpawnable,
BaseSpawnableId = registration.BaseSpawnableId,
BaseItemComponentType = registration.BaseItemComponentType,
CustomPrefab = registration.CustomPrefab,
MarkerPrefab = registration.MarkerPrefab,
ApplyTint = registration.ApplyTint,
Tint = registration.Tint,
ModelScaleMultiplier = registration.ModelScaleMultiplier,
ReplacementChancePercent = ModUtils.ClampPercent(registration.ReplacementChancePercent),
ExtraBasePrice = registration.ExtraBasePrice,
ExtraFloorPrice = registration.ExtraFloorPrice
};
}
private static bool TryNormalizeRegistration(TryConnectItemRegistration registration)
{
if (registration == null)
{
return false;
}
if (string.IsNullOrWhiteSpace(registration.OwnerGuid) || string.IsNullOrWhiteSpace(registration.Key) || string.IsNullOrWhiteSpace(registration.DisplayName))
{
return false;
}
if ((Object)(object)registration.CustomPrefab == (Object)null && (Object)(object)registration.BaseSpawnable == (Object)null && registration.BaseSpawnableId == 0 && registration.BaseItemComponentType == null)
{
return false;
}
if (registration.BaseItemComponentType != null && !typeof(Component).IsAssignableFrom(registration.BaseItemComponentType))
{
return false;
}
if ((Object)(object)registration.CustomPrefab != (Object)null && (Object)(object)registration.CustomPrefab.GetComponent<Item>() == (Object)null)
{
return false;
}
if ((Object)(object)registration.MarkerPrefab != (Object)null && (Object)(object)registration.MarkerPrefab.GetComponent<Item>() == (Object)null)
{
return false;
}
registration.OwnerGuid = registration.OwnerGuid.Trim();
registration.Key = registration.Key.Trim();
registration.DisplayName = registration.DisplayName.Trim();
registration.Description = registration.Description ?? string.Empty;
if (registration.SpawnableId == 0)
{
registration.SpawnableId = ModUtils.GetStableSpawnableId(registration.OwnerGuid, registration.Key);
}
if ((Object)(object)registration.CustomPrefab != (Object)null)
{
TryConnectApi.RefreshItemPrefab(registration.CustomPrefab);
}
if ((Object)(object)registration.MarkerPrefab != (Object)null)
{
TryConnectApi.RefreshItemPrefab(registration.MarkerPrefab);
}
return true;
}
private static string BuildUniqueKey(string ownerGuid, string key)
{
return ownerGuid + ":" + key;
}
private static void CacheDefinition(CustomItemDefinition definition)
{
DefinitionsBySpawnableId.Add(definition.Spawnable.spawnableID, definition);
DefinitionsByAssetId.Add(definition.AssetId, definition);
DefinitionsByMarkerPrefab.Add(definition.MarkerPrefab, definition);
if ((Object)(object)definition.BasePrefab != (Object)null)
{
if (!DefinitionsByBasePrefab.TryGetValue(definition.BasePrefab, out var value))
{
value = new List<CustomItemDefinition>();
DefinitionsByBasePrefab.Add(definition.BasePrefab, value);
}
value.Add(definition);
value.Sort((CustomItemDefinition left, CustomItemDefinition right) => left.Spawnable.spawnableID.CompareTo(right.Spawnable.spawnableID));
}
}
private static CustomItemDefinition TryBuildDefinitionForAssetId(uint assetId)
{
if (DefinitionsByAssetId.TryGetValue(assetId, out var value))
{
return value;
}
if (!RequestsByAssetId.TryGetValue(assetId, out var value2))
{
return null;
}
return TryBuildDefinition(value2);
}
private static CustomItemDefinition TryBuildDefinitionForSpawnableId(int spawnableId)
{
if (spawnableId == 0)
{
return null;
}
if (DefinitionsBySpawnableId.TryGetValue(spawnableId, out var value))
{
return value;
}
if (!RequestsBySpawnableId.TryGetValue(spawnableId, out var value2))
{
return null;
}
return TryBuildDefinition(value2);
}
private static CustomItemDefinition TryBuildDefinition(CustomItemRequest request)
{
SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
if ((Object)(object)val == (Object)null || !val.isEnabled)
{
return null;
}
ItemPriceSettings priceSettings = Resources.Load<ItemPriceSettings>("ItemPriceSettings");
EnsureDefinition(val, priceSettings, request);
DefinitionsBySpawnableId.TryGetValue(request.SpawnableId, out var value);
return value;
}
private static CustomItemDefinition BuildDefinition(SpawnableSettings spawnableSettings, ItemPriceSettings priceSettings, CustomItemRequest request)
{
//IL_0279: Unknown result type (might be due to invalid IL or missing references)
//IL_027e: Unknown result type (might be due to invalid IL or missing references)
//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
SpawnableSO val = ResolveBaseSpawnable(spawnableSettings, request);
GameObject val2 = (((Object)(object)request.CustomPrefab != (Object)null) ? request.CustomPrefab : (((Object)(object)val != (Object)null) ? val.prefab : null));
if ((Object)(object)val2 == (Object)null)
{
LogBuildFailureOnce(request, "Could not resolve a spawn prefab.");
return null;
}
if ((Object)(object)request.CustomPrefab != (Object)null)
{
TryConnectApi.PrepareRuntimeNetworkTemplate(val2);
TryConnectApi.RefreshItemPrefab(val2);
}
if ((Object)(object)val2.GetComponent<Item>() == (Object)null)
{
LogBuildFailureOnce(request, $"Custom prefab for '{request.DisplayName}' is missing an Item-derived component.");
return null;
}
GameObject val3 = (((Object)(object)request.MarkerPrefab != (Object)null) ? request.MarkerPrefab : val2);
GameObject val4 = Object.Instantiate<GameObject>(val3);
((Object)val4).name = request.Key + "_Marker";
((Object)val4).hideFlags = (HideFlags)61;
val4.SetActive(false);
Object.DontDestroyOnLoad((Object)(object)val4);
TryConnectApi.PrepareRuntimeNetworkTemplate(val4);
TryConnectApi.RefreshItemPrefab(val4);
Item component = val4.GetComponent<Item>();
if ((Object)(object)component == (Object)null)
{
Object.Destroy((Object)(object)val4);
LogBuildFailureOnce(request, $"Marker prefab for '{request.DisplayName}' is missing an Item-derived component.");
return null;
}
SpawnableSO val5 = ScriptableObject.CreateInstance<SpawnableSO>();
((Object)val5).hideFlags = (HideFlags)61;
((Object)val5).name = request.Key + "_SpawnableSO";
val5.spawnableID = request.SpawnableId;
val5.spawnableName = request.DisplayName;
val5.spawnableDescription = request.Description;
val5.prefab = val4;
component.spawnableSo = val5;
int basePrice = 4;
int priceIncreasePerFloor = 1;
if ((Object)(object)priceSettings != (Object)null && (Object)(object)val != (Object)null)
{
basePrice = Math.Max(1, priceSettings.GetBasePrice(val) + request.ExtraBasePrice);
priceIncreasePerFloor = Math.Max(0, priceSettings.GetPriceIncreasePerFloor(val) + request.ExtraFloorPrice);
}
CustomItemDefinition customItemDefinition = new CustomItemDefinition();
customItemDefinition.OwnerGuid = request.OwnerGuid;
customItemDefinition.Key = request.Key;
customItemDefinition.AssetId = request.AssetId;
customItemDefinition.BasePrefab = (((Object)(object)val != (Object)null) ? val.prefab : null);
customItemDefinition.SpawnPrefab = val2;
customItemDefinition.BasePrice = basePrice;
customItemDefinition.Description = request.Description;
customItemDefinition.DisplayName = request.DisplayName;
customItemDefinition.MarkerPrefab = val4;
customItemDefinition.ApplyTint = request.ApplyTint;
customItemDefinition.ModelScaleMultiplier = request.ModelScaleMultiplier;
customItemDefinition.PriceIncreasePerFloor = priceIncreasePerFloor;
customItemDefinition.ReplacementChancePercent = request.ReplacementChancePercent;
customItemDefinition.Spawnable = val5;
customItemDefinition.Tint = request.Tint;
ApplyDefinitionToMarker(customItemDefinition, val4);
EnsureClientSpawnHandler(customItemDefinition);
return customItemDefinition;
}
private static void LogBuildFailureOnce(CustomItemRequest request, string message)
{
if (request != null && !request.HasLoggedBuildFailure)
{
request.HasLoggedBuildFailure = true;
if (TryConnectPlugin.Log != null)
{
TryConnectPlugin.Log.LogWarning((object)$"Custom item '{request.DisplayName}' ({request.OwnerGuid}) could not be registered yet. {message}");
}
}
}
private static SpawnableSO ResolveBaseSpawnable(SpawnableSettings spawnableSettings, CustomItemRequest request)
{
if ((Object)(object)request.BaseSpawnable != (Object)null)
{
return request.BaseSpawnable;
}
if (request.BaseSpawnableId != 0)
{
return FindBaseSpawnableById(spawnableSettings, request.BaseSpawnableId);
}
if (request.BaseItemComponentType != null)
{
return FindBaseSpawnable(spawnableSettings, request.BaseItemComponentType);
}
return null;
}
private static bool TryFindSpawnable(SpawnableSettings spawnableSettings, Predicate<SpawnableSO> predicate, out SpawnableSO spawnable)
{
spawnable = null;
if ((Object)(object)spawnableSettings == (Object)null || predicate == null)
{
return false;
}
for (int i = 0; i < spawnableSettings.spawnables.Count; i++)
{
SpawnableSO val = spawnableSettings.spawnables[i];
if (predicate(val))
{
spawnable = val;
return true;
}
}
return false;
}
private static SpawnableSO FindBaseSpawnableById(SpawnableSettings spawnableSettings, int spawnableId)
{
SpawnableSO spawnable;
return TryFindSpawnable(spawnableSettings, (SpawnableSO candidate) => (Object)(object)candidate != (Object)null && candidate.spawnableID == spawnableId, out spawnable) ? spawnable : null;
}
private static SpawnableSO FindBaseSpawnable(SpawnableSettings spawnableSettings, Type componentType)
{
SpawnableSO spawnable;
return TryFindSpawnable(spawnableSettings, (SpawnableSO candidate) => (Object)(object)candidate != (Object)null && (Object)(object)candidate.prefab != (Object)null && (Object)(object)candidate.prefab.GetComponent(componentType) != (Object)null, out spawnable) ? spawnable : null;
}
private static void ApplyDefinitionToMarker(CustomItemDefinition definition, GameObject markerPrefab)
{
if (!((Object)(object)markerPrefab == (Object)null))
{
((Object)markerPrefab).name = definition.DisplayName;
ApplyDefinitionVisuals(definition, markerPrefab.transform);
Item component = markerPrefab.GetComponent<Item>();
if ((Object)(object)component != (Object)null)
{
component.spawnableSo = definition.Spawnable;
}
}
}
private static void ApplyDefinitionToServerInstance(CustomItemDefinition definition, GameObject spawnedObject, Vector3 scaleMultiplier)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
ApplyDefinitionToInstance(definition, spawnedObject, Vector3.Scale(spawnedObject.transform.localScale, scaleMultiplier));
}
private static void ApplyDefinitionToClientInstance(CustomItemDefinition definition, GameObject spawnedObject, Vector3 scale)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
ApplyDefinitionToInstance(definition, spawnedObject, scale);
}
private static void ApplyDefinitionToInstance(CustomItemDefinition definition, GameObject spawnedObject, Vector3 resolvedScale)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
TryConnectApi.PrepareRuntimeNetworkTemplate(spawnedObject);
TryConnectApi.RefreshItemPrefab(spawnedObject);
((Object)spawnedObject).name = definition.DisplayName;
spawnedObject.transform.localScale = resolvedScale;
spawnedObject.SetActive(true);
TryConnectApi.RefreshItemPrefab(spawnedObject);
NetworkIdentity component = spawnedObject.GetComponent<NetworkIdentity>();
if ((Object)(object)component != (Object)null)
{
SetNetworkAssetId(component, definition.AssetId);
}
Item component2 = spawnedObject.GetComponent<Item>();
if ((Object)(object)component2 != (Object)null)
{
component2.spawnableSo = definition.Spawnable;
}
ApplyDefinitionVisuals(definition, spawnedObject.transform);
}
private static void ApplyDefinitionVisuals(CustomItemDefinition definition, Transform root)
{
//IL_0036: 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_0041: 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)
Item component = ((Component)root).GetComponent<Item>();
Transform val = (((Object)(object)component != (Object)null) ? component.modelTransform : root.Find("Model"));
if ((Object)(object)val == (Object)null)
{
val = root;
}
val.localScale = Vector3.Scale(val.localScale, definition.ModelScaleMultiplier);
if (!definition.ApplyTint)
{
return;
}
Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
foreach (Renderer val2 in componentsInChildren)
{
if ((Object)(object)val2 == (Object)null)
{
continue;
}
Material[] materials = val2.materials;
foreach (Material val3 in materials)
{
if (ModUtils.TrySetMaterialTint(val3, definition.Tint) && val3.HasProperty("_Metallic"))
{
val3.SetFloat("_Metallic", Mathf.Clamp01(val3.GetFloat("_Metallic") + 0.15f));
}
}
val2.materials = materials;
}
}
private static void EnsureClientSpawnHandler(CustomItemDefinition definition)
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Expected O, but got Unknown
//IL_0071: Expected O, but got Unknown
if (definition != null)
{
IDictionary dictionary = ((SpawnHandlersField != null) ? (SpawnHandlersField.GetValue(null) as IDictionary) : null);
if (dictionary == null || !dictionary.Contains(definition.AssetId))
{
NetworkClient.RegisterSpawnHandler(definition.AssetId, new SpawnHandlerDelegate(SpawnCustomPrefab), new UnSpawnDelegate(UnspawnCustomPrefab));
TryConnectPlugin.Log.LogInfo((object)$"Registered custom spawn handler for '{definition.DisplayName}' ({definition.AssetId}).");
}
}
}
private static void SetNetworkAssetId(NetworkIdentity networkIdentity, uint assetId)
{
if (AssetIdField != null)
{
AssetIdField.SetValue(networkIdentity, assetId);
}
}
private static bool TryGetDefinition(SpawnableSO spawnableSO, out CustomItemDefinition definition)
{
definition = null;
if ((Object)(object)spawnableSO == (Object)null)
{
return false;
}
return DefinitionsBySpawnableId.TryGetValue(spawnableSO.spawnableID, out definition);
}
private static GameObject SpawnCustomPrefab(SpawnMessage message)
{
//IL_0006: 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_003d: 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_0043: 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_0051: 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)
if (!DefinitionsByAssetId.TryGetValue(message.assetId, out var value))
{
value = TryBuildDefinitionForAssetId(message.assetId);
if (value == null)
{
return null;
}
}
GameObject val = Object.Instantiate<GameObject>(value.SpawnPrefab, message.position, message.rotation);
ApplyDefinitionToClientInstance(value, val, message.scale);
return val;
}
private static void UnspawnCustomPrefab(GameObject spawnedObject)
{
if ((Object)(object)spawnedObject != (Object)null)
{
Object.Destroy((Object)(object)spawnedObject);
}
}
}
public static class TryConnectApi
{
public const int ApiVersion = 4;
public const string PluginGuid = "com.Try-4646.TryConnect";
private static readonly FieldInfo SceneIdField = typeof(NetworkIdentity).GetField("sceneId", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo HasSpawnedField = typeof(NetworkIdentity).GetField("hasSpawned", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo DestroyCalledField = typeof(NetworkIdentity).GetField("destroyCalled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo NetIdField = typeof(NetworkIdentity).GetField("<netId>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo AssetIdBackingField = typeof(NetworkIdentity).GetField("_assetId", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo IsClientField = typeof(NetworkIdentity).GetField("<isClient>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo IsServerField = typeof(NetworkIdentity).GetField("<isServer>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo IsLocalPlayerField = typeof(NetworkIdentity).GetField("<isLocalPlayer>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo IsOwnedField = typeof(NetworkIdentity).GetField("<isOwned>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo SpawnedFromInstantiateField = typeof(NetworkIdentity).GetField("<SpawnedFromInstantiate>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo ConnectionToServerField = typeof(NetworkIdentity).GetField("<connectionToServer>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo ConnectionToClientField = typeof(NetworkIdentity).GetField("_connectionToClient", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
private static readonly FieldInfo ItemColliderCacheField = typeof(Item).GetField("_allColliders", BindingFlags.Instance | BindingFlags.NonPublic);
public static bool IsInitialized => (Object)(object)TryConnectPlugin.Instance != (Object)null;
public static int GenerateSpawnableId(string ownerGuid, string key)
{
ValidateIdentity(ownerGuid, key);
return ModUtils.GetStableSpawnableId(ownerGuid, key);
}
public static TryConnectRegistrationResult RegisterCustomItem(TryConnectItemRegistration registration)
{
return RuntimeItemRegistry.RegisterCustomItem(registration);
}
public static bool TryGetCustomSpawnable(int spawnableId, out SpawnableSO spawnable)
{
spawnable = RuntimeItemRegistry.GetCustomSpawnable(spawnableId);
return (Object)(object)spawnable != (Object)null;
}
public static bool TryGetRegisteredItem(int spawnableId, out TryConnectRegisteredItemInfo itemInfo)
{
return RuntimeItemRegistry.TryGetRegisteredItemInfo(spawnableId, out itemInfo);
}
public static bool TryGetVanillaSpawnable(int spawnableId, out SpawnableSO spawnable)
{
return RuntimeItemRegistry.TryGetVanillaSpawnable(spawnableId, out spawnable);
}
public static bool TryFindVanillaSpawnable(string searchTerm, out SpawnableSO spawnable)
{
return RuntimeItemRegistry.TryFindVanillaSpawnable(searchTerm, out spawnable);
}
public static bool TryFindVanillaSpawnable(Type componentType, out SpawnableSO spawnable)
{
spawnable = null;
if (componentType == null)
{
throw new ArgumentNullException("componentType");
}
if (!typeof(Component).IsAssignableFrom(componentType))
{
throw new ArgumentException("componentType must derive from UnityEngine.Component.", "componentType");
}
SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
if ((Object)(object)val == (Object)null || val.spawnables == null)
{
return false;
}
for (int i = 0; i < val.spawnables.Count; i++)
{
SpawnableSO val2 = val.spawnables[i];
if ((Object)(object)val2 != (Object)null && (Object)(object)val2.prefab != (Object)null && (Object)(object)val2.prefab.GetComponent(componentType) != (Object)null)
{
spawnable = val2;
return true;
}
}
return false;
}
public static bool TryFindVanillaSpawnable<TComponent>(out SpawnableSO spawnable) where TComponent : Component
{
return TryFindVanillaSpawnable(typeof(TComponent), out spawnable);
}
public static SpawnableSO FindVanillaSpawnable<TComponent>() where TComponent : Component
{
SpawnableSO spawnable;
return TryFindVanillaSpawnable<TComponent>(out spawnable) ? spawnable : null;
}
public static GameObject CreatePrefabTemplate(SpawnableSO baseSpawnable, string templateName = null)
{
if ((Object)(object)baseSpawnable == (Object)null || (Object)(object)baseSpawnable.prefab == (Object)null)
{
throw new ArgumentException("baseSpawnable and its prefab are required.", "baseSpawnable");
}
return CreatePrefabTemplate(baseSpawnable.prefab, templateName);
}
public static GameObject CreatePrefabTemplate(GameObject sourcePrefab, string templateName = null)
{
if ((Object)(object)sourcePrefab == (Object)null)
{
throw new ArgumentNullException("sourcePrefab");
}
GameObject val = Object.Instantiate<GameObject>(sourcePrefab);
((Object)val).name = (string.IsNullOrWhiteSpace(templateName) ? (((Object)sourcePrefab).name + "_TryConnectTemplate") : templateName.Trim());
((Object)val).hideFlags = (HideFlags)61;
val.SetActive(false);
Object.DontDestroyOnLoad((Object)(object)val);
PrepareRuntimeNetworkTemplate(val);
return val;
}
public static TTarget SwapPrefabComponent<TSource, TTarget>(GameObject prefab) where TSource : Component where TTarget : TSource
{
if ((Object)(object)prefab == (Object)null)
{
throw new ArgumentNullException("prefab");
}
TSource component = prefab.GetComponent<TSource>();
if ((Object)(object)component == (Object)null)
{
throw new InvalidOperationException($"Prefab '{((Object)prefab).name}' is missing component '{typeof(TSource).FullName}'.");
}
TTarget val = prefab.AddComponent<TTarget>();
CopyPrefabComponentState((Component)(object)component, (Component)(object)val);
object obj = component;
Behaviour val2 = (Behaviour)((obj is Behaviour) ? obj : null);
object obj2 = val;
Behaviour val3 = (Behaviour)((obj2 is Behaviour) ? obj2 : null);
if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null)
{
val3.enabled = val2.enabled;
}
Object.DestroyImmediate((Object)(object)component);
return val;
}
public static int RemoveNonTriggerColliders(GameObject root)
{
if ((Object)(object)root == (Object)null)
{
throw new ArgumentNullException("root");
}
List<Collider> list = CollectNonTriggerColliders(root);
for (int i = 0; i < list.Count; i++)
{
Object.DestroyImmediate((Object)(object)list[i]);
}
RefreshItemPrefab(root);
return list.Count;
}
public static void RefreshItemPrefab(GameObject prefab)
{
if ((Object)(object)prefab == (Object)null)
{
throw new ArgumentNullException("prefab");
}
Item[] componentsInChildren = prefab.GetComponentsInChildren<Item>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
RefreshItemState(componentsInChildren[i]);
}
}
public static Transform GetPrefabVisualRoot(GameObject prefab)
{
if ((Object)(object)prefab == (Object)null)
{
throw new ArgumentNullException("prefab");
}
return ResolveVisualRoot(prefab);
}
public static GameObject ReplaceVisualsWithPrimitive(GameObject prefab, PrimitiveType primitiveType, Color color, Vector3 localScale, bool replaceColliders = true)
{
//IL_005b: 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_00ad: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)prefab == (Object)null)
{
throw new ArgumentNullException("prefab");
}
Transform val = ResolveVisualRoot(prefab);
int layer = ((((Component)val).gameObject.layer != 0) ? ((Component)val).gameObject.layer : prefab.layer);
SetRenderersEnabled(val, isEnabled: false);
if (replaceColliders)
{
RemoveNonTriggerColliders(prefab);
}
GameObject val2 = GameObject.CreatePrimitive(primitiveType);
((Object)val2).name = ((object)(PrimitiveType)(ref primitiveType)).ToString() + "Visual";
val2.layer = layer;
val2.transform.SetParent(val, false);
val2.transform.localPosition = Vector3.zero;
val2.transform.localRotation = Quaternion.identity;
val2.transform.localScale = localScale;
Renderer component = val2.GetComponent<Renderer>();
if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMaterial != (Object)null)
{
Material val3 = Object.Instantiate<Material>(component.sharedMaterial);
val3.color = color;
component.sharedMaterial = val3;
}
RefreshItemPrefab(prefab);
return val2;
}
public static GameObject ReplaceVisualsWithPrefab(GameObject prefab, GameObject visualPrefab, Vector3 localScale, bool replaceColliders = true)
{
//IL_0003: 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_000a: Unknown result type (might be due to invalid IL or missing references)
return ReplaceVisualsWithPrefab(prefab, visualPrefab, localScale, replaceColliders, Vector3.zero, Vector3.zero);
}
public static GameObject ReplaceVisualsWithPrefab(GameObject prefab, GameObject visualPrefab, Vector3 localScale, bool replaceColliders, Vector3 localPosition, Vector3 localEulerAngles)
{
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)prefab == (Object)null)
{
throw new ArgumentNullException("prefab");
}
if ((Object)(object)visualPrefab == (Object)null)
{
throw new ArgumentNullException("visualPrefab");
}
Transform val = ResolveVisualRoot(prefab);
int layer = ((((Component)val).gameObject.layer != 0) ? ((Component)val).gameObject.layer : prefab.layer);
SetRenderersEnabled(val, isEnabled: false);
if (replaceColliders)
{
RemoveNonTriggerColliders(prefab);
}
GameObject val2 = Object.Instantiate<GameObject>(visualPrefab);
((Object)val2).name = (string.IsNullOrWhiteSpace(((Object)visualPrefab).name) ? "CustomVisual" : ((Object)visualPrefab).name);
RemoveNestedRigidbodies(val2);
val2.transform.SetParent(val, false);
val2.transform.localPosition = localPosition;
val2.transform.localRotation = Quaternion.Euler(localEulerAngles);
val2.transform.localScale = localScale;
SetLayerRecursively(val2, layer);
val2.SetActive(true);
SetRenderersEnabled(val2.transform, isEnabled: true);
RefreshItemPrefab(prefab);
return val2;
}
public static TryConnectRegistrationResult RegisterBundledCustomItem<TBaseItem>(BaseUnityPlugin plugin, TryConnectBundledItemRegistration registration) where TBaseItem : Item
{
return RegisterBundledCustomItem<TBaseItem, TBaseItem>(plugin, registration);
}
public static TryConnectRegistrationResult RegisterBundledCustomItem<TBaseItem, TCustomItem>(BaseUnityPlugin plugin, TryConnectBundledItemRegistration registration) where TBaseItem : Item where TCustomItem : TBaseItem
{
//IL_0101: 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_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_016c: Unknown result type (might be due to invalid IL or missing references)
//IL_0229: Unknown result type (might be due to invalid IL or missing references)
//IL_0237: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)plugin == (Object)null)
{
throw new ArgumentNullException("plugin");
}
if (registration == null)
{
throw new ArgumentNullException("registration");
}
ValidateBundledRegistration(registration);
SpawnableSO val = ResolveBundledBaseSpawnable<TBaseItem>(registration);
if ((Object)(object)val == (Object)null)
{
throw new InvalidOperationException($"Could not resolve a base spawnable for '{typeof(TBaseItem).FullName}'.");
}
GameObject val2 = CreatePrefabTemplate(val, BuildTemplateName(registration.CustomPrefabName, registration.Key, "CustomPrefab"));
GameObject val3 = CreatePrefabTemplate(val, BuildTemplateName(registration.MarkerPrefabName, registration.Key, "MarkerPrefab"));
if (typeof(TBaseItem) != typeof(TCustomItem))
{
TryConnectApi.SwapPrefabComponent<TBaseItem, TCustomItem>(val2);
}
Material fallbackMaterial = (registration.UseBaseMaterialFallback ? CloneFirstMaterial(val2) : null);
AssetBundle val4 = TryConnectAssetBundles.LoadRelativeToPlugin(plugin, registration.BundlePath);
try
{
GameObject visualPrefab = TryConnectAssetBundles.LoadAsset<GameObject>(val4, registration.VisualPrefabName);
GameObject root = ReplaceVisualsWithPrefab(val2, visualPrefab, registration.VisualLocalScale, registration.ReplaceColliders, registration.VisualLocalPosition, registration.VisualLocalEulerAngles);
GameObject root2 = ReplaceVisualsWithPrefab(val3, visualPrefab, registration.VisualLocalScale, registration.ReplaceColliders, registration.VisualLocalPosition, registration.VisualLocalEulerAngles);
EnsureVisibleMaterials(root, fallbackMaterial, registration.ForceVisualMaterial, registration.ApplyVisualColor, registration.VisualColor);
EnsureVisibleMaterials(root2, fallbackMaterial, registration.ForceVisualMaterial, registration.ApplyVisualColor, registration.VisualColor);
}
finally
{
val4.Unload(false);
}
TryConnectItemRegistration tryConnectItemRegistration = new TryConnectItemRegistration();
tryConnectItemRegistration.OwnerGuid = plugin.Info.Metadata.GUID;
tryConnectItemRegistration.Key = registration.Key;
tryConnectItemRegistration.SpawnableId = registration.SpawnableId;
tryConnectItemRegistration.DisplayName = registration.DisplayName;
tryConnectItemRegistration.Description = registration.Description;
tryConnectItemRegistration.BaseSpawnable = val;
tryConnectItemRegistration.BaseSpawnableId = registration.BaseSpawnableId;
tryConnectItemRegistration.BaseItemComponentType = typeof(TBaseItem);
tryConnectItemRegistration.CustomPrefab = val2;
tryConnectItemRegistration.MarkerPrefab = val3;
tryConnectItemRegistration.ApplyTint = registration.ApplyTint;
tryConnectItemRegistration.Tint = registration.Tint;
tryConnectItemRegistration.ModelScaleMultiplier = registration.ModelScaleMultiplier;
tryConnectItemRegistration.ReplacementChancePercent = registration.ReplacementChancePercent;
tryConnectItemRegistration.ExtraBasePrice = registration.ExtraBasePrice;
tryConnectItemRegistration.ExtraFloorPrice = registration.ExtraFloorPrice;
return RegisterCustomItem(tryConnectItemRegistration);
}
public static TryConnectRegisteredItemInfo[] GetRegisteredItems()
{
return RuntimeItemRegistry.GetRegisteredItemInfos();
}
internal static void PrepareRuntimeNetworkTemplate(GameObject prefab)
{
if ((Object)(object)prefab == (Object)null)
{
return;
}
NetworkIdentity[] componentsInChildren = prefab.GetComponentsInChildren<NetworkIdentity>(true);
foreach (NetworkIdentity val in componentsInChildren)
{
if (!((Object)(object)val == (Object)null))
{
if (SceneIdField != null)
{
SceneIdField.SetValue(val, 0uL);
}
if (HasSpawnedField != null)
{
HasSpawnedField.SetValue(val, false);
}
if (DestroyCalledField != null)
{
DestroyCalledField.SetValue(val, false);
}
if (NetIdField != null)
{
NetIdField.SetValue(val, 0u);
}
if (AssetIdBackingField != null)
{
AssetIdBackingField.SetValue(val, 0u);
}
if (IsClientField != null)
{
IsClientField.SetValue(val, false);
}
if (IsServerField != null)
{
IsServerField.SetValue(val, false);
}
if (IsLocalPlayerField != null)
{
IsLocalPlayerField.SetValue(val, false);
}
if (IsOwnedField != null)
{
IsOwnedField.SetValue(val, false);
}
if (SpawnedFromInstantiateField != null)
{
SpawnedFromInstantiateField.SetValue(val, false);
}
if (ConnectionToClientField != null)
{
ConnectionToClientField.SetValue(val, null);
}
if (ConnectionToServerField != null)
{
ConnectionToServerField.SetValue(val, null);
}
}
}
}
private static void ValidateIdentity(string ownerGuid, string key)
{
if (string.IsNullOrWhiteSpace(ownerGuid))
{
throw new ArgumentException("ownerGuid is required.", "ownerGuid");
}
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentException("key is required.", "key");
}
}
private static void ValidateBundledRegistration(TryConnectBundledItemRegistration registration)
{
if (string.IsNullOrWhiteSpace(registration.Key))
{
throw new ArgumentException("registration.Key is required.", "registration");
}
if (string.IsNullOrWhiteSpace(registration.DisplayName))
{
throw new ArgumentException("registration.DisplayName is required.", "registration");
}
if (string.IsNullOrWhiteSpace(registration.BundlePath))
{
throw new ArgumentException("registration.BundlePath is required.", "registration");
}
if (string.IsNullOrWhiteSpace(registration.VisualPrefabName))
{
throw new ArgumentException("registration.VisualPrefabName is required.", "registration");
}
}
private static SpawnableSO ResolveBundledBaseSpawnable<TBaseItem>(TryConnectBundledItemRegistration registration) where TBaseItem : Item
{
if ((Object)(object)registration.BaseSpawnable != (Object)null)
{
return registration.BaseSpawnable;
}
if (registration.BaseSpawnableId != 0 && TryGetVanillaSpawnable(registration.BaseSpawnableId, out var spawnable))
{
return spawnable;
}
return TryConnectApi.FindVanillaSpawnable<TBaseItem>();
}
private static string BuildTemplateName(string explicitName, string key, string suffix)
{
if (!string.IsNullOrWhiteSpace(explicitName))
{
return explicitName.Trim();
}
return key.Trim() + "_" + suffix;
}
private static Material CloneFirstMaterial(GameObject root)
{
if ((Object)(object)root == (Object)null)
{
return null;
}
Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
foreach (Renderer val in componentsInChildren)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
Material[] sharedMaterials = val.sharedMaterials;
for (int j = 0; j < sharedMaterials.Length; j++)
{
if ((Object)(object)sharedMaterials[j] != (Object)null)
{
return Object.Instantiate<Material>(sharedMaterials[j]);
}
}
}
return null;
}
private static void EnsureVisibleMaterials(GameObject root, Material fallbackMaterial, bool forceMaterial, bool applyColor, Color color)
{
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)root == (Object)null)
{
return;
}
Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
foreach (Renderer val in componentsInChildren)
{
if ((Object)(object)val == (Object)null)
{
continue;
}
Material[] sharedMaterials = val.sharedMaterials;
bool flag = sharedMaterials == null || sharedMaterials.Length == 0;
if (!flag)
{
for (int j = 0; j < sharedMaterials.Length; j++)
{
if ((Object)(object)sharedMaterials[j] == (Object)null)
{
flag = true;
break;
}
}
}
if (!forceMaterial && !applyColor && !flag)
{
val.enabled = true;
continue;
}
int num = ((sharedMaterials == null || sharedMaterials.Length == 0) ? 1 : sharedMaterials.Length);
Material[] array = (Material[])(object)new Material[num];
for (int k = 0; k < num; k++)
{
Material sourceMaterial = ((sharedMaterials != null && k < sharedMaterials.Length) ? sharedMaterials[k] : null);
Material val2 = CreateRendererMaterial(sourceMaterial, fallbackMaterial, forceMaterial);
if ((Object)(object)val2 != (Object)null && applyColor)
{
ModUtils.TrySetMaterialTint(val2, color);
}
array[k] = val2;
}
val.sharedMaterials = array;
val.enabled = true;
}
}
private static Material CreateRendererMaterial(Material sourceMaterial, Material fallbackMaterial, bool forceMaterial)
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
Material val = null;
if (!forceMaterial && (Object)(object)sourceMaterial != (Object)null)
{
val = sourceMaterial;
}
else if ((Object)(object)fallbackMaterial != (Object)null)
{
val = fallbackMaterial;
}
else if ((Object)(object)sourceMaterial != (Object)null)
{
val = sourceMaterial;
}
if ((Object)(object)val != (Object)null)
{
return Object.Instantiate<Material>(val);
}
Shader val2 = Shader.Find("Standard") ?? Shader.Find("Universal Render Pipeline/Lit");
return (!((Object)(object)val2 != (Object)null)) ? ((Material)null) : new Material(val2);
}
private static Transform ResolveVisualRoot(GameObject prefab)
{
Item val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Item>() : null);
Transform val2 = (((Object)(object)val != (Object)null) ? val.modelTransform : null);
if ((Object)(object)val2 == (Object)null && (Object)(object)prefab != (Object)null)
{
val2 = prefab.transform.Find("Model");
}
return val2 ?? (((Object)(object)prefab != (Object)null) ? prefab.transform : null);
}
private static void SetRenderersEnabled(Transform root, bool isEnabled)
{
if ((Object)(object)root == (Object)null)
{
return;
}
Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
if ((Object)(object)componentsInChildren[i] != (Object)null)
{
componentsInChildren[i].enabled = isEnabled;
}
}
}
private static void SetLayerRecursively(GameObject root, int layer)
{
if ((Object)(object)root == (Object)null)
{
return;
}
Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
if ((Object)(object)componentsInChildren[i] != (Object)null)
{
((Component)componentsInChildren[i]).gameObject.layer = layer;
}
}
}
private static void RemoveNestedRigidbodies(GameObject root)
{
if ((Object)(object)root == (Object)null)
{
return;
}
Rigidbody[] componentsInChildren = root.GetComponentsInChildren<Rigidbody>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
if ((Object)(object)componentsInChildren[i] != (Object)null)
{
Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
}
}
}
private static void RefreshItemState(Item item)
{
if (!((Object)(object)item == (Object)null))
{
Transform val = item.modelTransform;
if ((Object)(object)val == (Object)null)
{
val = (item.modelTransform = ((Component)item).transform.Find("Model"));
}
item.handRig = ResolveHandRig(val);
item.handMesh = ResolveHandMesh(item.handRig);
item.onHandFb = ResolveFeedbackPlayer(((Component)item).transform, "OnHand");
item.onDropFb = ResolveFeedbackPlayer(((Component)item).transform, "OnDrop");
item.onThrowVfx = ResolveThrowVfx(((Component)item).transform);
if (ItemColliderCacheField != null)
{
ItemColliderCacheField.SetValue(item, CollectNonTriggerColliders(item));
}
EnsureInteractableProxies(item);
}
}
private static GameObject ResolveHandRig(Transform modelTransform)
{
if ((Object)(object)modelTransform == (Object)null)
{
return null;
}
Transform val = modelTransform.Find("HandRig");
return ((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null;
}
private static SkinnedMeshRenderer ResolveHandMesh(GameObject handRig)
{
if ((Object)(object)handRig == (Object)null)
{
return null;
}
SkinnedMeshRenderer[] componentsInChildren = handRig.GetComponentsInChildren<SkinnedMeshRenderer>(true);
return (componentsInChildren.Length != 0) ? componentsInChildren[0] : null;
}
private static MMF_Player ResolveFeedbackPlayer(Transform itemTransform, string feedbackName)
{
Transform val = (((Object)(object)itemTransform != (Object)null) ? itemTransform.Find("Feedbacks") : null);
if ((Object)(object)val == (Object)null)
{
return null;
}
Transform val2 = val.Find(feedbackName);
return ((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<MMF_Player>() : null;
}
private static ParticleSystem ResolveThrowVfx(Transform itemTransform)
{
Transform val = (((Object)(object)itemTransform != (Object)null) ? itemTransform.Find("Feedbacks") : null);
if ((Object)(object)val == (Object)null)
{
return null;
}
Transform val2 = val.Find("OnThrowVFX");
return ((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<ParticleSystem>() : null;
}
private static List<Collider> CollectNonTriggerColliders(Item item)
{
return ((Object)(object)item != (Object)null) ? CollectNonTriggerColliders(((Component)item).gameObject) : new List<Collider>();
}
private static List<Collider> CollectNonTriggerColliders(GameObject root)
{
List<Collider> list = new List<Collider>();
Collider[] array = (Collider[])(((Object)(object)root != (Object)null) ? ((Array)root.GetComponentsInChildren<Collider>(true)) : ((Array)new Collider[0]));
foreach (Collider val in array)
{
if ((Object)(object)val != (Object)null && !val.isTrigger)
{
list.Add(val);
}
}
return list;
}
private static void EnsureInteractableProxies(Item item)
{
if ((Object)(object)item == (Object)null)
{
return;
}
Collider[] componentsInChildren = ((Component)item).GetComponentsInChildren<Collider>(true);
foreach (Collider val in componentsInChildren)
{
if (!((Object)(object)val == (Object)null) && !val.isTrigger && !((Object)(object)((Component)val).transform == (Object)(object)((Component)item).transform) && ((Component)val).GetComponent<IInteractable>() == null)
{
TryConnectInteractableProxy tryConnectInteractableProxy = ((Component)val).GetComponent<TryConnectInteractableProxy>();
if ((Object)(object)tryConnectInteractableProxy == (Object)null)
{
tryConnectInteractableProxy = ((Component)val).gameObject.AddComponent<TryConnectInteractableProxy>();
}
tryConnectInteractableProxy.Bind((MonoBehaviour)(object)item);
}
}
}
private static void CopyPrefabComponentState(Component source, Component target)
{
Type type = ((object)source).GetType();
while (type != null && type != typeof(NetworkBehaviour))
{
FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (!fieldInfo.IsStatic && !fieldInfo.IsInitOnly)
{
fieldInfo.SetValue(target, fieldInfo.GetValue(source));
}
}
type = type.BaseType;
}
}
}
public sealed class TryConnectBundledItemRegistration
{
public string Key { get; set; }
public int SpawnableId { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public SpawnableSO BaseSpawnable { get; set; }
public int BaseSpawnableId { get; set; }
public string BundlePath { get; set; }
public string VisualPrefabName { get; set; }
public string CustomPrefabName { get; set; }
public string MarkerPrefabName { get; set; }
public Vector3 VisualLocalPosition { get; set; } = Vector3.zero;
public Vector3 VisualLocalEulerAngles { get; set; } = Vector3.zero;
public Vector3 VisualLocalScale { get; set; } = Vector3.one;
public bool ReplaceColliders { get; set; }
public bool UseBaseMaterialFallback { get; set; } = true;
public bool ForceVisualMaterial { get; set; }
public bool ApplyVisualColor { get; set; }
public Color VisualColor { get; set; } = Color.white;
public bool ApplyTint { get; set; }
public Color Tint { get; set; } = Color.white;
public Vector3 ModelScaleMultiplier { get; set; } = Vector3.one;
public int ReplacementChancePercent { get; set; }
public int ExtraBasePrice { get; set; }
public int ExtraFloorPrice { get; set; }
}
public static class TryConnectAssetBundles
{
public static AssetBundle Load(string fullPath)
{
if (string.IsNullOrWhiteSpace(fullPath))
{
throw new ArgumentException("fullPath is required.", "fullPath");
}
string fullPath2 = Path.GetFullPath(fullPath.Trim());
if (!File.Exists(fullPath2))
{
throw new FileNotFoundException("Asset bundle file was not found.", fullPath2);
}
AssetBundle val = AssetBundle.LoadFromFile(fullPath2);
if ((Object)(object)val == (Object)null)
{
throw new InvalidOperationException($"Failed to load asset bundle '{fullPath2}'.");
}
return val;
}
public static AssetBundle LoadRelativeToPlugin(BaseUnityPlugin plugin, string relativePath)
{
return Load(ResolvePluginRelativePath(plugin, relativePath));
}
public static T LoadAsset<T>(AssetBundle bundle, string assetName) where T : Object
{
if ((Object)(object)bundle == (Object)null)
{
throw new ArgumentNullException("bundle");
}
if (string.IsNullOrWhiteSpace(assetName))
{
throw new ArgumentException("assetName is required.", "assetName");
}
T val = bundle.LoadAsset<T>(assetName.Trim());
if ((Object)(object)val == (Object)null)
{
throw new InvalidOperationException($"Asset '{assetName}' of type '{typeof(T).FullName}' was not found in bundle '{((Object)bundle).name}'.");
}
return val;
}
public static GameObject CreatePrefabTemplateFromBundle(AssetBundle bundle, string prefabName, string templateName = null)
{
GameObject sourcePrefab = TryConnectAssetBundles.LoadAsset<GameObject>(bundle, prefabName);
return TryConnectApi.CreatePrefabTemplate(sourcePrefab, templateName);
}
public static GameObject CreatePrefabTemplateFromBundle(BaseUnityPlugin plugin, string bundlePath, string prefabName, string templateName = null)
{
AssetBundle val = LoadRelativeToPlugin(plugin, bundlePath);
try
{
return CreatePrefabTemplateFromBundle(val, prefabName, templateName);
}
finally
{
val.Unload(false);
}
}
public static string ResolvePluginRelativePath(BaseUnityPlugin plugin, string relativePath)
{
if ((Object)(object)plugin == (Object)null)
{
throw new ArgumentNullException("plugin");
}
if (string.IsNullOrWhiteSpace(relativePath))
{
throw new ArgumentException("relativePath is required.", "relativePath");
}
string location = ((object)plugin).GetType().Assembly.Location;
if (string.IsNullOrWhiteSpace(location))
{
throw new InvalidOperationException($"Could not resolve assembly location for plugin '{((object)plugin).GetType().FullName}'.");
}
string directoryName = Path.GetDirectoryName(location);
if (string.IsNullOrWhiteSpace(directoryName))
{
throw new InvalidOperationException($"Could not resolve plugin directory for '{location}'.");
}
return Path.GetFullPath(Path.Combine(directoryName, relativePath.Trim()));
}
}
public sealed class TryConnectItemRegistration
{
public string OwnerGuid { get; set; }
public string Key { get; set; }
public int SpawnableId { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public SpawnableSO BaseSpawnable { get; set; }
public int BaseSpawnableId { get; set; }
public Type BaseItemComponentType { get; set; }
public GameObject CustomPrefab { get; set; }
public GameObject MarkerPrefab { get; set; }
public bool ApplyTint { get; set; }
public Color Tint { get; set; } = Color.white;
public Vector3 ModelScaleMultiplier { get; set; } = Vector3.one;
public int ReplacementChancePercent { get; set; }
public int ExtraBasePrice { get; set; }
public int ExtraFloorPrice { get; set; }
}
public sealed class TryConnectRegisteredItemInfo
{
public string OwnerGuid { get; private set; }
public string Key { get; private set; }
public int SpawnableId { get; private set; }
public uint AssetId { get; private set; }
public string DisplayName { get; private set; }
public string Description { get; private set; }
public SpawnableSO Spawnable { get; private set; }
public bool IsRegistered { get; private set; }
internal TryConnectRegisteredItemInfo(string ownerGuid, string key, int spawnableId, uint assetId, string displayName, string description, SpawnableSO spawnable, bool isRegistered)
{
OwnerGuid = ownerGuid;
Key = key;
SpawnableId = spawnableId;
AssetId = assetId;
DisplayName = displayName;
Description = description;
Spawnable = spawnable;
IsRegistered = isRegistered;
}
}
public enum TryConnectRegistrationResult
{
Accepted,
AlreadyRegistered,
InvalidRegistration
}
[BepInPlugin("com.Try-4646.TryConnect", "TryConnect", "1.0.0")]
public sealed class TryConnectPlugin : BaseUnityPlugin
{
public const string PluginGuid = "com.Try-4646.TryConnect";
public const string PluginDisplayName = "TryConnect";
public const string PluginVersion = "1.0.0";
internal const string MyGUID = "com.Try-4646.TryConnect";
internal const string PluginName = "TryConnect";
internal const string VersionString = "1.0.0";
private Harmony _harmony;
public static TryConnectPlugin Instance { get; private set; }
internal static ManualLogSource Log { get; private set; }
internal static ConfigEntry<bool> EnableCustomItems { get; private set; }
internal static ConfigEntry<int> TicketFizzReplacementChance { get; private set; }
internal static ConfigEntry<int> LoadedChipReplacementChance { get; private set; }
private void Awake()
{
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Expected O, but got Unknown
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
EnableCustomItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Custom Items", "Enable", true, "Enable TryConnect runtime shop item registration.");
TicketFizzReplacementChance = ((BaseUnityPlugin)this).Config.Bind<int>("Custom Items", "TicketFizzReplacementChance", 35, "Chance for shop item stamps to replace a vanilla Drink roll with Ticket Fizz.");
LoadedChipReplacementChance = ((BaseUnityPlugin)this).Config.Bind<int>("Custom Items", "LoadedChipReplacementChance", 25, "Chance for shop item stamps to replace a vanilla Golden Chip roll with Loaded Chip.");
RuntimeItemRegistry.Initialize(this);
SceneManager.sceneLoaded += OnSceneLoaded;
((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("PluginName: {0}, VersionString: {1} is loading...", "TryConnect", "1.0.0"));
_harmony = new Harmony("com.Try-4646.TryConnect");
_harmony.PatchAll();
RuntimeItemRegistry.TryRegisterRuntimeContent();
((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("PluginName: {0}, VersionString: {1} is loaded.", "TryConnect", "1.0.0"));
}
private void OnDestroy()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
RuntimeItemRegistry.Dispose();
if (_harmony != null)
{
_harmony.UnpatchSelf();
}
}
private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
RuntimeItemRegistry.TryRegisterRuntimeContent();
}
}
}
namespace TryConnect.Utils
{
internal static class ModUtils
{
internal static uint GetStableAssetId(string key)
{
return GetStableAssetId("com.Try-4646.TryConnect", key);
}
internal static uint GetStableAssetId(string ownerGuid, string key)
{
uint num = GetStableHash(ownerGuid + ":" + key);
if (num == 0)
{
num = 1u;
}
return num;
}
internal static int GetStableSpawnableId(string ownerGuid, string key)
{
uint stableHash = GetStableHash(ownerGuid + ":" + key);
return (int)(0x40000000 | (stableHash & 0x3FFFFFFF));
}
internal static int ClampPercent(int value)
{
return Mathf.Clamp(value, 0, 100);
}
internal static int GetDeterministicPercent(Vector3 position, int seed, string key)
{
//IL_000b: 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_003f: Unknown result type (might be due to invalid IL or missing references)
int num = seed;
num = (num * 397) ^ Mathf.RoundToInt(position.x * 100f);
num = (num * 397) ^ Mathf.RoundToInt(position.y * 100f);
num = (num * 397) ^ Mathf.RoundToInt(position.z * 100f);
for (int i = 0; i < key.Length; i++)
{
num = (num * 397) ^ key[i];
}
if (num == int.MinValue)
{
num = int.MaxValue;
}
return Mathf.Abs(num) % 100;
}
internal static bool TrySetMaterialTint(Material material, Color tint)
{
//IL_0027: 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)
if ((Object)(object)material == (Object)null)
{
return false;
}
if (material.HasProperty("_BaseColor"))
{
material.SetColor("_BaseColor", tint);
return true;
}
if (material.HasProperty("_Color"))
{
material.SetColor("_Color", tint);
return true;
}
return false;
}
private static uint GetStableHash(string text)
{
uint num = 2166136261u;
for (int i = 0; i < text.Length; i++)
{
num ^= text[i];
num *= 16777619;
}
return num;
}
}
}
namespace TryConnect.Patches
{
[HarmonyPatch(typeof(SpawnableSettings), "GetSpawnableSoById")]
internal static class SpawnableSettingsPatches
{
private static void Postfix(int id, ref SpawnableSO __result)
{
if ((Object)(object)__result == (Object)null)
{
__result = RuntimeItemRegistry.GetCustomSpawnable(id);
}
}
}
[HarmonyPatch(typeof(ItemPriceSettings), "GetBasePrice")]
internal static class ItemPriceSettingsBasePricePatches
{
private static bool Prefix(SpawnableSO spawnableSO, ref int __result)
{
return !RuntimeItemRegistry.TryGetCustomBasePrice(spawnableSO, ref __result);
}
}
[HarmonyPatch(typeof(ItemPriceSettings), "GetPriceIncreasePerFloor")]
internal static class ItemPriceSettingsFloorPricePatches
{
private static bool Prefix(SpawnableSO spawnableSO, ref int __result)
{
return !RuntimeItemRegistry.TryGetCustomFloorPrice(spawnableSO, ref __result);
}
}
[HarmonyPatch(typeof(ItemDescriptionSettings), "GetDescription")]
internal static class ItemDescriptionSettingsPatches
{
private static bool Prefix(SpawnableSO spawnableSO, ref string __result)
{
return !RuntimeItemRegistry.TryGetCustomDescription(spawnableSO, ref __result);
}
}
[HarmonyPatch(typeof(ItemStampManager), "GetUniqueLoot", new Type[]
{
typeof(MMLootTableGameObjectSO),
typeof(Vector3)
})]
internal static class ItemStampManagerLootPatches
{
private static void Postfix(MMLootTableGameObjectSO lootTable, Vector3 stampPosition, ref GameObject __result)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
__result = RuntimeItemRegistry.GetShopReplacement(lootTable, stampPosition, __result);
}
}
[HarmonyPatch(typeof(ItemStamp), "SpawnItem")]
internal static class ItemStampSpawnPatches
{
private static bool Prefix(ItemStamp __instance, GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0004: 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)
return !RuntimeItemRegistry.TrySpawnCustomItemStampPrefab(__instance, prefab, position, rotation, scale);
}
}
[HarmonyPatch(typeof(NewConsole), "SpawnPrefabServer")]
internal static class NewConsoleSpawnPatches
{
private static bool Prefix(GameObject prefab, Vector3 position)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
return !RuntimeItemRegistry.TrySpawnConsolePrefab(prefab, position);
}
}
[HarmonyPatch]
internal static class CustomNetworkManagerPatches
{
[CompilerGenerated]
private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator
{
private int <>1__state;
private MethodBase <>2__current;
private int <>l__initialThreadId;
MethodBase IEnumerator<MethodBase>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <TargetMethods>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = AccessTools.Method(typeof(CustomNetworkManager), "OnStartServer", (Type[])null, (Type[])null);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<>2__current = AccessTools.Method(typeof(CustomNetworkManager), "OnClientConnect", (Type[])null, (Type[])null);
<>1__state = 2;
return true;
case 2:
<>1__state = -1;
<>2__current = AccessTools.Method(typeof(CustomNetworkManager), "OnClientSceneChanged", (Type[])null, (Type[])null);
<>1__state = 3;
return true;
case 3:
<>1__state = -1;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
{
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
return this;
}
return new <TargetMethods>d__0(0);
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<MethodBase>)this).GetEnumerator();
}
}
[IteratorStateMachine(typeof(<TargetMethods>d__0))]
private static IEnumerable<MethodBase> TargetMethods()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <TargetMethods>d__0(-2);
}
private static void Postfix()
{
RuntimeItemRegistry.TryRegisterRuntimeContent();
}
}
[HarmonyPatch]
internal static class NetworkClientSpawnLifecyclePatches
{
[CompilerGenerated]
private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator
{
private int <>1__state;
private MethodBase <>2__current;
private int <>l__initialThreadId;
MethodBase IEnumerator<MethodBase>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <TargetMethods>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = AccessTools.Method(typeof(NetworkClient), "ClearSpawners", (Type[])null, (Type[])null);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
{
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
return this;
}
return new <TargetMethods>d__0(0);
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<MethodBase>)this).GetEnumerator();
}
}
[IteratorStateMachine(typeof(<TargetMethods>d__0))]
private static IEnumerable<MethodBase> TargetMethods()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <TargetMethods>d__0(-2);
}
private static void Postfix()
{
RuntimeItemRegistry.TryEnsureAllClientRegistrations();
}
}
[HarmonyPatch(typeof(NetworkClient), "OnSpawn")]
internal static class NetworkClientOnSpawnPatches
{
private static void Prefix(SpawnMessage message)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
RuntimeItemRegistry.TryEnsureClientRegistration(message.assetId);
}
}
}
namespace TryConnect.MonoBehaviours
{
internal class TryConnectComponent : MonoBehaviour
{
public void Awake()
{
}
public void Start()
{
}
public void Update()
{
}
public void LateUpdate()
{
}
}
}