Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PUP FPS v1.0.30
PUP_FPS.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [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: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.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; } } } public sealed class ServerZoneStreamBlock : MonoBehaviour { private const string Id = "com.pup.instancecombiner.serverstream"; private const int Vanilla = 10240; private static ConfigEntry<bool> enabledSetting; private static bool active; private static int limit = 10240; private static int extraObjects; private static long started; private static long extraStarted; private static double cooldown; private Harmony harmony; private bool initialized; private ManualLogSource Logger; private static double Seconds => (double)Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; public void Setup(ConfigFile config, ManualLogSource logger) { Logger = logger; enabledSetting = config.Bind<bool>("ServerStreaming", "Enabled", true, "Enable bounded dedicated-server ZDO packet growth. False restores vanilla packet size."); } private void Initialize() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00a1: Expected O, but got Unknown //IL_00a1: Expected O, but got Unknown //IL_00a1: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_0104: Expected O, but got Unknown //IL_0104: Expected O, but got Unknown initialized = true; if (!ZNet.instance.IsDedicated()) { ((Behaviour)this).enabled = false; return; } harmony = new Harmony("com.pup.instancecombiner.serverstream"); try { harmony.Patch((MethodBase)AccessTools.Method(typeof(ZDOMan), "SendZDOs", (Type[])null, (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "Before", (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "After", (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "Rewrite", (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "Finish", (Type[])null), (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(ZDOMan), "AddForceSendZdos", (Type[])null, (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "BeforeForcedBatch", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(ServerZoneStreamBlock), "RewriteForcedBatch", (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "FinishForcedBatch", (Type[])null), (HarmonyMethod)null); } catch (Exception) { harmony.UnpatchSelf(); ((Behaviour)this).enabled = false; } } private static void Before(bool __1) { started = Stopwatch.GetTimestamp(); extraStarted = 0L; extraObjects = 0; active = enabledSetting.Value && !__1 && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer(); if (!active || Seconds < cooldown || Time.unscaledDeltaTime > 0.04f) { limit = 10240; } } private static int PayloadLimit() { if (!active) { return 10240; } return limit; } private static int CheckedSize(ZPackage package) { int num = package.Size(); if (!active || limit <= 10240 || num <= 10240) { return num; } long timestamp = Stopwatch.GetTimestamp(); if (extraStarted == 0L) { extraStarted = timestamp; } double num2 = (double)(timestamp - extraStarted) * 1000.0 / (double)Stopwatch.Frequency; double num3 = (double)(timestamp - started) * 1000.0 / (double)Stopwatch.Frequency; if (extraObjects >= 32 || num2 >= 1.0 || num3 >= 25.0) { return limit + 1; } extraObjects++; return num; } private static void After() { if (active) { double num = (double)(Stopwatch.GetTimestamp() - started) * 1000.0 / (double)Stopwatch.Frequency; if (num >= 25.0 || Time.unscaledDeltaTime > 0.04f) { limit = 10240; cooldown = Seconds + 2.0; } else if (Seconds >= cooldown && num < 15.0) { limit = Math.Min(20480, limit + 1024); } } } private static Exception Finish(Exception __exception) { active = false; return __exception; } private static void BeforeForcedBatch(List<ZDO> __1, out int __state) { __state = __1?.Count ?? (-1); } private static void AppendForcedZdo(List<ZDO> list, int index, ZDO zdo) { list.Add(zdo); } private static void RestoreForcedOrder(List<ZDO> list, int originalCount) { if (list != null && originalCount >= 0 && list.Count > originalCount) { list.Reverse(0, originalCount); list.Reverse(); } } private static Exception FinishForcedBatch(List<ZDO> __1, int __state, Exception __exception) { RestoreForcedOrder(__1, __state); return __exception; } private static IEnumerable<CodeInstruction> RewriteForcedBatch(IEnumerable<CodeInstruction> source) { List<CodeInstruction> list = source.ToList(); MethodInfo insert = AccessTools.Method(typeof(List<ZDO>), "Insert", (Type[])null, (Type[])null); var array = (from x in list.Select((CodeInstruction c, int i) => new { c, i }) where CodeInstructionExtensions.Calls(x.c, insert) select x).ToArray(); if (array.Length != 1 || array[0].i < 2 || list[array[0].i - 2].opcode != OpCodes.Ldc_I4_0) { throw new InvalidOperationException("Unexpected AddForceSendZdos IL; original behavior retained"); } array[0].c.opcode = OpCodes.Call; array[0].c.operand = AccessTools.Method(typeof(ServerZoneStreamBlock), "AppendForcedZdo", (Type[])null, (Type[])null); return list; } private static IEnumerable<CodeInstruction> Rewrite(IEnumerable<CodeInstruction> source) { List<CodeInstruction> list = source.ToList(); var array = (from x in list.Select((CodeInstruction c, int i) => new { c, i }) where x.c.opcode == OpCodes.Ldc_I4 && object.Equals(x.c.operand, 10240) select x).ToArray(); var array2 = (from x in list.Select((CodeInstruction c, int i) => new { c, i }) where CodeInstructionExtensions.Calls(x.c, AccessTools.Method(typeof(ZPackage), "Size", (Type[])null, (Type[])null)) select x).ToArray(); if (array.Length != 2 || array2.Length != 1 || list[array[1].i + 1].opcode != OpCodes.Ldloc_0 || list[array[1].i + 2].opcode != OpCodes.Sub || list[array2[0].i + 1].opcode != OpCodes.Ldloc_1 || (list[array2[0].i + 2].opcode != OpCodes.Ble_S && list[array2[0].i + 2].opcode != OpCodes.Ble)) { throw new InvalidOperationException("Unexpected SendZDOs IL; original behavior retained"); } array[1].c.opcode = OpCodes.Call; array[1].c.operand = AccessTools.Method(typeof(ServerZoneStreamBlock), "PayloadLimit", (Type[])null, (Type[])null); array2[0].c.opcode = OpCodes.Call; array2[0].c.operand = AccessTools.Method(typeof(ServerZoneStreamBlock), "CheckedSize", (Type[])null, (Type[])null); return list; } private void Update() { if (!initialized && (Object)(object)ZNet.instance != (Object)null) { Initialize(); } } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } namespace ValheimInstanceCombiner { [BepInPlugin("com.pup.instancecombiner.safe", "PUP Safe Building Combiner", "1.0.30")] public class InstanceCombinerMod : BaseUnityPlugin { private sealed class GpuDrawGroup { public Mesh mesh; public int subMesh; public Material material; public readonly HashSet<string> stableIds = new HashSet<string>(StringComparer.Ordinal); public bool usesTessellation; public bool tessellationEnabled = true; public Bounds worldBounds; public bool hasWorldBounds; public bool cameraVisible = true; public readonly List<Matrix4x4[]> chunks = new List<Matrix4x4[]>(); } private sealed class RawGpuGroup { public string meshName; public int vertexCount; public int subMeshCount; public Vector3 boundsSize; public int subMesh; public string materialName; public readonly List<Matrix4x4[]> chunks = new List<Matrix4x4[]>(); } private sealed class RawGpuCache { public bool fullVisual; public readonly List<RawGpuGroup> groups = new List<RawGpuGroup>(); } private sealed class RawMeshData { public Vector3[] vertices; public Vector3[] normals; public Vector4[] tangents; public Vector2[] uv; public int[][] triangles; } private sealed class RawSubCluster { public RawMeshData mesh; public string[] materialNames; public readonly List<CachedColliderData> colliders = new List<CachedColliderData>(); } private sealed class PreparedSubCluster { public SubClusterCacheEntry entry; public RawSubCluster raw; public long sourceBytes; } private sealed class BakedRecord { public string customId; public long userId; public uint id; public int prefabHash; public Vector3 position; public Quaternion rotation; public Vector3 scale; } private sealed class CachedColliderData { public int subX = -1; public int subZ = -1; public int colliderIndex = -1; public byte type; public int layer; public Vector3 position; public Quaternion rotation; public Vector3 scale; public bool trigger; public Vector3 center; public Vector3 size; public float radius; public float height; public int direction; public bool convex; public string meshName; public Mesh mesh; public RawMeshData rawMesh; } private sealed class PendingCollider { public Vector2Int cell; public GameObject root; public CachedColliderData data; } private sealed class SubClusterCacheEntry { public int x; public int z; public string name; public string fileName; } private sealed class MaterialCombineGroup { public Material source; public readonly List<CombineInstance> parts = new List<CombineInstance>(); } [HarmonyPatch(typeof(Player), "OnSpawned")] private static class PlayerSpawnPatch { private static void Postfix() { InstanceCombinerMod instanceCombinerMod = Object.FindFirstObjectByType<InstanceCombinerMod>(); if ((Object)(object)instanceCombinerMod != (Object)null) { instanceCombinerMod.LoadState(); instanceCombinerMod.BeginSinglePlayerFastInitialLoad(); } } } [HarmonyPatch(typeof(ZNet), "LoadWorld")] private static class SinglePlayerWorldLoadIndexPatch { private static void Postfix() { if ((Object)(object)Instance != (Object)null && (Object)(object)ZNet.instance != (Object)null && ZNet.IsSinglePlayer) { Instance.PrepareSinglePlayerStableIndexDuringWorldLoad(); Instance.LoadState(); Instance.BeginSinglePlayerFastWorldLoadPrewarm(); } } } [HarmonyPatch(typeof(Player), "TeleportTo")] private static class PortalDestinationPrewarmPatch { private static void Postfix(Vector3 pos, bool distantTeleport, bool __result) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (__result && distantTeleport && (Object)(object)Instance != (Object)null) { Instance.BeginSinglePlayerFastPortal(pos); Instance.PrewarmRemotePortalDestination(pos); } } } [HarmonyPatch(typeof(Player), "UpdateTeleport")] private static class SinglePlayerPortalArrivalPatch { private static void Prefix(Player __instance, out bool __state) { __state = (Object)(object)__instance != (Object)null && ((Character)__instance).IsTeleporting(); } private static void Postfix(Player __instance, bool __state) { if (__state && (Object)(object)__instance != (Object)null && !((Character)__instance).IsTeleporting() && (Object)(object)Instance != (Object)null) { Instance.FinishSinglePlayerPortalCurtain(); } } } [HarmonyPatch(typeof(Hud), "UpdateBlackScreen")] private static class SinglePlayerPortalCurtainPatch { private static void Postfix(Hud __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)Instance == (Object)null) && (Instance.ShouldHoldSinglePlayerPortalCurtain() | Instance.ShouldHoldRemotePortalCurtain())) { object? obj = AccessTools.Field(typeof(Hud), "m_loadingScreen")?.GetValue(__instance); Component val = (Component)((obj is Component) ? obj : null); if (!((Object)(object)val == (Object)null)) { val.gameObject.SetActive(true); AccessTools.Property(((object)val).GetType(), "alpha")?.SetValue(val, 1f, null); } } } } [HarmonyPatch(typeof(ZNet), "Shutdown")] private static class MultiplayerClientShutdownPatch { private static void Prefix() { if ((Object)(object)Instance != (Object)null) { Instance.BeginMultiplayerClientShutdown(); } } } [HarmonyPatch(typeof(ZNetScene), "CreateObject")] private static class HideBakedObjectAtCreationPatch { private static bool Prefix(ZDO zdo, ref GameObject __result) { if ((Object)(object)Instance == (Object)null || !Instance.TrySuppressRemoteOriginalCreation(zdo)) { return true; } __result = null; return false; } private static void Postfix(ZDO zdo, GameObject __result) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (((Object)(object)Instance != (Object)null && Instance.TryUnloadRemoteOriginalAtCreation(zdo, __result)) || (Object)(object)Instance == (Object)null || zdo == null || (Object)(object)__result == (Object)null || !zdo.GetBool(BakedKey, false)) { return; } Vector2Int item = default(Vector2Int); ((Vector2Int)(ref item))..ctor(zdo.GetInt(CellXKey, int.MinValue), zdo.GetInt(CellZKey, int.MinValue)); if (Instance.gpuCacheReadyCells.Contains(item) && !Instance.suppressedVisualCells.Contains(item)) { ZNetView component = __result.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null) { Instance.HideOriginalRenderers(component); } } } } [HarmonyPatch(typeof(ZNetScene), "IsAreaReady")] private static class RemoteAreaReadyPatch { private static void Postfix(Vector3 point, ref bool __result) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!__result && (Object)(object)Instance != (Object)null && Instance.IsRemoteAreaReadyIgnoringSuppressed(point)) { __result = true; } } } [HarmonyPatch(typeof(ZNetScene), "AddInstance")] private static class HideBakedObjectAtAddInstancePatch { private static void Postfix(ZDO zdo, ZNetView nview) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Instance?.ObserveRestoreSupportView(zdo, nview); if (!((Object)(object)Instance == (Object)null) && zdo != null && !((Object)(object)nview == (Object)null) && zdo.GetBool(BakedKey, false)) { Vector2Int item = default(Vector2Int); ((Vector2Int)(ref item))..ctor(zdo.GetInt(CellXKey, int.MinValue), zdo.GetInt(CellZKey, int.MinValue)); if (Instance.gpuCacheReadyCells.Contains(item) && !Instance.suppressedVisualCells.Contains(item)) { Instance.HideOriginalRenderers(nview); } } } } [HarmonyPatch(typeof(WearNTear), "UpdateSupport")] private static class WearNTearSupportPatch { private static bool Prefix(WearNTear __instance, out float __state) { __state = (((Object)(object)Instance != (Object)null && WearSupportField != null) ? ((float)WearSupportField.GetValue(__instance)) : (-1f)); if (!((Object)(object)Instance == (Object)null)) { if (!Instance.ShouldBlockSupportUpdate()) { return !Instance.IsRestoreSupportBlocked(__instance); } return false; } return true; } private static void Postfix(WearNTear __instance, float __state) { if ((Object)(object)Instance != (Object)null) { Instance.PreserveDependentSupport(__instance, __state); } } } [HarmonyPatch(typeof(WearNTear), "UpdateWear")] private static class WearNTearWearPatch { private static bool Prefix(WearNTear __instance) { if (!((Object)(object)Instance == (Object)null)) { if (!Instance.ShouldBlockSupportUpdate()) { return !Instance.IsRestoreSupportBlocked(__instance); } return false; } return true; } } [HarmonyPatch(typeof(ZNet), "SaveWorld")] private static class ZNetSaveWorldPatch { private static void Prefix() { if ((Object)(object)Instance != (Object)null) { Instance.BeforeVanillaWorldSave(); } } } private sealed class DedicatedBakeTarget { public long userId; public uint id; public int prefabHash; public Vector3 position; } private sealed class RemoteVisualHandoff { public ZDOID id; public MeshRenderer[] allRenderers; public List<MeshRenderer> enabledRenderers; public LODGroup[] allLodGroups; public List<LODGroup> enabledLodGroups; } private sealed class RemoteProvisionalVisualPublication { public GameObject root; public List<GpuDrawGroup> groups; public List<RemoteVisualHandoff> originals; public int queuedFrame; } private sealed class IncomingRecordTransfer { public Vector2Int cell; public string cacheId; public int total; public readonly List<BakedRecord> records = new List<BakedRecord>(); } private sealed class RemoteCellManifest { public Vector2Int cell; public string cacheId; public int recordCount; public ulong fingerprint; } private sealed class IncomingFile { public string name; public long length; public string sha256; public long received; } private sealed class IncomingCellTransfer { public Vector2Int cell; public string cacheId; public float lastActivity; public readonly Dictionary<string, IncomingFile> files = new Dictionary<string, IncomingFile>(StringComparer.OrdinalIgnoreCase); } private sealed class RemoteFinalVisualHandoff { public GameObject root; public List<GpuDrawGroup> groups; public GameObject previousRoot; public List<GpuDrawGroup> previousGroups; public int queuedFrame; public float queuedTime; } private sealed class RestoreLookup { internal readonly Dictionary<string, List<ZDO>> stable = new Dictionary<string, List<ZDO>>(StringComparer.Ordinal); internal readonly Dictionary<string, List<ZDO>> positions = new Dictionary<string, List<ZDO>>(StringComparer.Ordinal); internal readonly Dictionary<Vector2Int, Dictionary<ZDOID, ZDO>> parked = new Dictionary<Vector2Int, Dictionary<ZDOID, ZDO>>(); } [HarmonyPatch(typeof(ZDO), "InternalSetPosition")] private static class RestoreSectorAfterPositionPatch { private static void Postfix(ZDO __instance) { if ((Object)(object)Instance != (Object)null && Instance.IsMultiplayerGuest()) { Instance.RepairRestoredZdoSector(__instance); } } } [HarmonyPatch(typeof(ZDOMan), "RPC_ZDOData")] private static class RestoreSectorAfterPacketPatch { private static void Prefix(ZPackage pkg, out List<KeyValuePair<ZDOID, string>> __state) { __state = (((Object)(object)Instance != (Object)null && Instance.IsMultiplayerGuest() && ZDOMan.instance != null) ? Instance.CaptureRestoreSectorCandidates(pkg) : null); } private static void Postfix(List<KeyValuePair<ZDOID, string>> __state) { if ((Object)(object)Instance != (Object)null && Instance.IsMultiplayerGuest()) { Instance.RepairReceivedRestoreSectors(__state); } } } private sealed class RestoreSupportCell { internal List<BakedRecord> pending; internal List<BakedRecord> materialized = new List<BakedRecord>(); internal float readyAfter; internal bool visualCover; internal HashSet<string> identities; } private sealed class FastColliderCellState { public string directory; public string cacheId; public GameObject root; public List<Mesh> owned; public readonly List<SubClusterCacheEntry> pending = new List<SubClusterCacheEntry>(); } private sealed class PreparedGpuRead { public string cacheId; public ulong fingerprint; public Task<RawGpuCache> task; } internal static InstanceCombinerMod Instance; private const float CellSize = 64f; private const float ParkingCoordinate = 1900000f; private const string CacheSchema = "c14"; private const string StateHeader = "PUP_SAFE|11|64|STABLE_OBJECT_ID|CACHE_ID|TRANSACTIONAL|MODE_ISOLATED"; private const string LegacyStateHeader = "PUP_SAFE|8|64|GRAUSTEN|SUBCLUSTER16|CUSTOM_ID"; private readonly Harmony harmony = new Harmony("com.pup.instancecombiner.safe"); private static readonly FieldInfo WearSupportField = AccessTools.Field(typeof(WearNTear), "m_support"); private readonly Dictionary<Vector2Int, GameObject> clusters = new Dictionary<Vector2Int, GameObject>(); private readonly Dictionary<Vector2Int, List<Mesh>> generatedMeshes = new Dictionary<Vector2Int, List<Mesh>>(); private readonly Dictionary<Vector2Int, List<BakedRecord>> records = new Dictionary<Vector2Int, List<BakedRecord>>(); private readonly Dictionary<Vector2Int, string> cacheIds = new Dictionary<Vector2Int, string>(); private readonly Dictionary<string, Material> materialCopies = new Dictionary<string, Material>(StringComparer.Ordinal); private readonly HashSet<Vector2Int> failedCacheCells = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> staleCleanupPending = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> pendingWorldSaveRestores = new HashSet<Vector2Int>(); private const string RestorePendingCacheId = "RESTORE_PENDING"; private readonly Dictionary<Vector2Int, HashSet<ZDOID>> pendingRestoredInstances = new Dictionary<Vector2Int, HashSet<ZDOID>>(); private readonly Dictionary<ZDOID, List<MeshRenderer>> hiddenRenderers = new Dictionary<ZDOID, List<MeshRenderer>>(); private readonly Dictionary<ZDOID, List<LODGroup>> hiddenLodGroups = new Dictionary<ZDOID, List<LODGroup>>(); private static Dictionary<string, Mesh> meshAssetCache; private static Dictionary<string, Material> materialAssetCache; private static Dictionary<string, (Mesh mesh, Material material)> gpuSourceCache; private static bool gpuSourceCacheBuilding; private readonly HashSet<Vector2Int> gpuCacheReadyCells = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> suppressedVisualCells = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> startupVisualBatchCells = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> warmingStartupCells = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> revealedStartupCells = new HashSet<Vector2Int>(); private bool startupVisualBatchRevealed; private bool visualWarmupRunning; private readonly HashSet<Vector2Int> loadingCells = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> singlePlayerFullGpuCells = new HashSet<Vector2Int>(); private readonly Dictionary<Vector2Int, bool> colliderCellActive = new Dictionary<Vector2Int, bool>(); private readonly Dictionary<Vector2Int, HashSet<string>> protectedSupportColliders = new Dictionary<Vector2Int, HashSet<string>>(); private Vector3 previousPlayerPosition; private Vector3 smoothedTravelDirection; private float nextColliderActivationCheck; private const float ColliderEnableRadius = 80f; private const float ColliderDisableRadius = 96f; private const float ColliderPreloadSeconds = 2f; private const double MainThreadLoadBudgetMs = 2.0; private const double ColliderLoadBudgetMs = 1.0; private const float SupportGuardGraceSeconds = 10f; private bool processing; private bool highlightEnabled; private readonly HashSet<Vector2Int> highlightSuppressedCells = new HashSet<Vector2Int>(); private bool cacheLoadingProgressActive; private bool cacheLoadingProgressVisible; private float cacheLoadingProgressStarted; private int cacheLoadingProgressCompleted; private int cacheLoadingProgressTotal; private readonly HashSet<Vector2Int> multiplayerStartupProgressCells = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> multiplayerStartupReadyCells = new HashSet<Vector2Int>(); private bool multiplayerStartupProgressCaptured; private bool multiplayerStartupProgressCompleted; private GUIStyle cacheLoadingProgressStyle; private GUIStyle cacheLoadingProgressShadowStyle; private string worldName = ""; private long worldUid; private readonly Dictionary<int, Material> highlightMaterials = new Dictionary<int, Material>(); private readonly Dictionary<MeshRenderer, Material[]> highlightedClusterMaterials = new Dictionary<MeshRenderer, Material[]>(); private float nextCellCheck; private int activeColliderLoads; private int pendingSubClusterLoads; private readonly SortedDictionary<int, Queue<PendingCollider>> pendingColliders = new SortedDictionary<int, Queue<PendingCollider>>(); private int queuedColliderCount; private int loadedQueuedColliders; private float supportGuardUntil; private ZNet loadedZNet; private ZDOMan stableZdoIndexOwner; private long stableZdoIndexWorldUid; private Dictionary<string, List<ZDO>> stableZdoIndexCache; private bool safeSaveRestoreInProgress; private bool applicationQuitting; private readonly Dictionary<Vector2Int, List<GpuDrawGroup>> gpuBakedGroups = new Dictionary<Vector2Int, List<GpuDrawGroup>>(); private readonly HashSet<Material> retiredGpuMaterials = new HashSet<Material>(); private readonly Dictionary<Vector2Int, List<MeshRenderer>> gpuClusterHidden = new Dictionary<Vector2Int, List<MeshRenderer>>(); private readonly Dictionary<Vector2Int, List<MeshRenderer>> precipitationRenderers = new Dictionary<Vector2Int, List<MeshRenderer>>(); private readonly Dictionary<MeshRenderer, bool> skyAlphaPreviousEnabled = new Dictionary<MeshRenderer, bool>(); private readonly Dictionary<MeshRenderer, int> skyAlphaPreviousLayer = new Dictionary<MeshRenderer, int>(); private readonly Dictionary<MeshRenderer, ShadowCastingMode> skyAlphaPreviousShadowMode = new Dictionary<MeshRenderer, ShadowCastingMode>(); private Mesh singlePlayerPrecipitationCubeMesh; private readonly Plane[] gpuFrustumPlanes = (Plane[])(object)new Plane[6]; private readonly Dictionary<Vector2Int, Bounds> gpuCellWorldBounds = new Dictionary<Vector2Int, Bounds>(); private readonly Dictionary<Vector2Int, bool> gpuCellCameraVisible = new Dictionary<Vector2Int, bool>(); private Camera gpuCullCamera; private Vector3 gpuCullCameraPosition; private Quaternion gpuCullCameraRotation; private float gpuCullCameraFieldOfView; private float gpuCullCameraAspect; private bool gpuCullVisibilityDirty = true; private static readonly FieldInfo ZNetSceneInstancesField = typeof(ZNetScene).GetField("m_instances", BindingFlags.Instance | BindingFlags.NonPublic); private const string MultiplayerProtocol = "PUP_MP_7"; private const string MultiplayerVersion = "1.0.29"; private const string MultiplayerClientCacheHeader = "PUP_MP_CLIENT_RECORDS_3"; private const int MultiplayerRecordBatchSize = 512; private const string MetadataAckName = "__PUP_METADATA_READY__"; private const int MultiplayerChunkSize = 8192; private const float MultiplayerRequestRadius = 192f; private const float MultiplayerChunkAckTimeout = 15f; private const float MultiplayerReceiveTimeout = 60f; private const float MultiplayerHandshakeTimeout = 30f; private const string RpcHello = "PUP_FPS_MP_HELLO"; private const string RpcReject = "PUP_FPS_MP_REJECT"; private const string RpcManifest = "PUP_FPS_MP_MANIFEST"; private const string RpcRequestCell = "PUP_FPS_MP_REQUEST_CELL"; private const string RpcCellFiles = "PUP_FPS_MP_CELL_FILES"; private const string RpcCellChunk = "PUP_FPS_MP_CELL_CHUNK"; private const string RpcCellAck = "PUP_FPS_MP_CELL_ACK"; private const string RpcCellRemoved = "PUP_FPS_MP_CELL_REMOVED"; private const string RpcCellRecords = "PUP_FPS_MP_CELL_RECORDS"; private const string RpcRecordAck = "PUP_FPS_MP_RECORD_ACK"; private const string RpcAdminCommand = "PUP_FPS_ADMIN_COMMAND"; private const string RpcAdminResult = "PUP_FPS_ADMIN_RESULT"; private const string RpcAdminHighlight = "PUP_FPS_ADMIN_HIGHLIGHT"; private const string RpcRestoreAck = "PUP_FPS_MP_RESTORE_ACK"; private const string RpcRestoreProgress = "PUP_FPS_MP_RESTORE_PROGRESS"; private const string RpcBakeReady = "PUP_FPS_MP_BAKE_READY"; private ZRoutedRpc multiplayerRpc; private float nextMultiplayerHello; private float nextMultiplayerPeerCheck; private bool multiplayerManifestReceived; private bool multiplayerRejected; private readonly HashSet<long> multiplayerVerifiedPeers = new HashSet<long>(); private readonly Dictionary<long, float> multiplayerPeerFirstSeen = new Dictionary<long, float>(); private readonly Dictionary<Vector2Int, RemoteCellManifest> multiplayerRemoteCells = new Dictionary<Vector2Int, RemoteCellManifest>(); private readonly HashSet<Vector2Int> multiplayerRequestedCells = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> multiplayerPendingLoadCells = new HashSet<Vector2Int>(); private readonly Dictionary<Vector2Int, int> multiplayerBuildGenerations = new Dictionary<Vector2Int, int>(); private readonly HashSet<Vector2Int> multiplayerPendingVanillaRestore = new HashSet<Vector2Int>(); private readonly Dictionary<ZDOID, Vector2Int> multiplayerRestoreTrackedZdos = new Dictionary<ZDOID, Vector2Int>(); private readonly Dictionary<Vector2Int, List<ZNetView>> multiplayerRestoredViews = new Dictionary<Vector2Int, List<ZNetView>>(); private IncomingCellTransfer multiplayerIncomingTransfer; private long multiplayerServerPeerUid; private ConnectionStatus multiplayerLastConnectionStatus; private readonly HashSet<long> multiplayerSendingPeers = new HashSet<long>(); private readonly HashSet<string> multiplayerPendingChunkAcks = new HashSet<string>(); private Vector2Int? multiplayerOutstandingRequest; private float multiplayerOutstandingRequestStarted; private float nextMultiplayerCellRequestAllowed; private IncomingRecordTransfer multiplayerIncomingRecords; private readonly Dictionary<Vector2Int, List<BakedRecord>> multiplayerDiskCachedRecords = new Dictionary<Vector2Int, List<BakedRecord>>(); private readonly Dictionary<Vector2Int, Dictionary<string, Queue<BakedRecord>>> multiplayerRemoteCreationIndex = new Dictionary<Vector2Int, Dictionary<string, Queue<BakedRecord>>>(); private readonly Dictionary<ZDOID, ZDO> multiplayerSuppressedRemoteZdos = new Dictionary<ZDOID, ZDO>(); private readonly Dictionary<string, Vector2Int> multiplayerSuppressedStableCells = new Dictionary<string, Vector2Int>(StringComparer.Ordinal); private readonly Dictionary<Vector2Int, HashSet<long>> multiplayerPendingRestoreAcks = new Dictionary<Vector2Int, HashSet<long>>(); private readonly Dictionary<Vector2Int, Dictionary<long, float>> multiplayerRestoreProgress = new Dictionary<Vector2Int, Dictionary<long, float>>(); private readonly HashSet<Vector2Int> multiplayerRemotePhysicsReady = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> multiplayerProvisionalVisualCells = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> multiplayerProvisionalBuildsInProgress = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> multiplayerRemoteBuildsInProgress = new HashSet<Vector2Int>(); private readonly Dictionary<Vector2Int, List<RemoteVisualHandoff>> multiplayerPendingVisualHandoffs = new Dictionary<Vector2Int, List<RemoteVisualHandoff>>(); private readonly Dictionary<Vector2Int, int> multiplayerGpuSubmittedFrames = new Dictionary<Vector2Int, int>(); private readonly Dictionary<Vector2Int, int> multiplayerHandoffPublishedFrames = new Dictionary<Vector2Int, int>(); private readonly Dictionary<Vector2Int, float> multiplayerHandoffPublishedTimes = new Dictionary<Vector2Int, float>(); private readonly Dictionary<Vector2Int, RemoteFinalVisualHandoff> multiplayerPendingFinalVisualHandoffs = new Dictionary<Vector2Int, RemoteFinalVisualHandoff>(); private readonly Dictionary<Vector2Int, RemoteProvisionalVisualPublication> multiplayerPendingProvisionalVisualPublications = new Dictionary<Vector2Int, RemoteProvisionalVisualPublication>(); private readonly Dictionary<Vector2Int, float> multiplayerPortalPrewarmUntil = new Dictionary<Vector2Int, float>(); private bool multiplayerClientShutdownInProgress; private bool multiplayerServerAdminAllowed; private bool multiplayerRemoteServerDedicated; private int multiplayerDedicatedBudgetFrame = -1; private long multiplayerDedicatedBudgetStarted; private int multiplayerDedicatedLastProvisionalStartFrame = -1; private bool multiplayerDedicatedPortalPending; private Vector3 multiplayerDedicatedPortalTarget; private float multiplayerDedicatedPortalDeadline; private bool multiplayerProvisionalCacheScanned; private long multiplayerManifestRevision; private long multiplayerLastReceivedManifestRevision = -1L; private GameObject multiplayerSpawnSafety; private Vector2Int multiplayerSpawnSafetyCell; private float multiplayerSpawnSafetyY; private float multiplayerSpawnSafetyReadySince = -1f; private readonly Dictionary<Vector2Int, HashSet<long>> multiplayerPendingBakeReady = new Dictionary<Vector2Int, HashSet<long>>(); private readonly Dictionary<GameObject, HashSet<Mesh>> remoteOwnedColliderMeshes = new Dictionary<GameObject, HashSet<Mesh>>(); private static readonly Func<ZDO, bool> IsOutsideRestoreSector = AccessTools.MethodDelegate<Func<ZDO, bool>>(AccessTools.PropertyGetter(typeof(ZDO), "OutsideZones"), (object)null, true); private static readonly Action<ZDO, SectorIndex> SetRestoreSector = AccessTools.MethodDelegate<Action<ZDO, SectorIndex>>(AccessTools.Method(typeof(ZDO), "SetSector", (Type[])null, (Type[])null), (object)null, true); private int remoteRestoreWorkFrame = -1; private int remoteRestoreWorkCount; private long remoteRestoreWorkStarted; private Dictionary<string, List<ZDO>> remoteRestoreFallback; private ZDOMan remoteRestoreFallbackOwner; private bool remoteRestoreFallbackBuilding; private readonly Dictionary<Vector2Int, RestoreSupportCell> restoreSupportCells = new Dictionary<Vector2Int, RestoreSupportCell>(); private readonly Dictionary<string, ZNetView> restoreSupportViews = new Dictionary<string, ZNetView>(StringComparer.Ordinal); private ZDOMan restoreSupportOwner; private bool restoreSupportChecking; private float restoreSupportNextCheck; private readonly Dictionary<Vector2Int, FastColliderCellState> fastColliderCells = new Dictionary<Vector2Int, FastColliderCellState>(); private readonly Dictionary<Vector2Int, HashSet<string>> fastLoadedSubclusters = new Dictionary<Vector2Int, HashSet<string>>(); private readonly Dictionary<Vector2Int, Vector3> singlePlayerFastFocus = new Dictionary<Vector2Int, Vector3>(); private readonly Dictionary<Vector2Int, float> singlePlayerFastRetainUntil = new Dictionary<Vector2Int, float>(); private readonly HashSet<Vector2Int> singlePlayerDormantCells = new HashSet<Vector2Int>(); private readonly Dictionary<Vector2Int, float> singlePlayerFastLastUsed = new Dictionary<Vector2Int, float>(); private const int SinglePlayerDormantCellLimit = 20; private readonly Dictionary<Vector2Int, PreparedGpuRead> singlePlayerPreparedGpuReads = new Dictionary<Vector2Int, PreparedGpuRead>(); private bool singlePlayerInitialVisualPipelineRunning; private readonly Dictionary<Vector2Int, float> singlePlayerVisualHandoffStarted = new Dictionary<Vector2Int, float>(); private bool fastColliderPumpRunning; private bool singlePlayerPortalCurtainActive; private float singlePlayerPortalCurtainReleaseAt; private bool singlePlayerStartupCurtainActive; private float singlePlayerStartupCurtainStarted; private readonly HashSet<Vector2Int> singlePlayerStartupCurtainCells = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> singlePlayerVisualHandoffNeedsParking = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> singlePlayerReparkRunning = new HashSet<Vector2Int>(); private readonly HashSet<Vector2Int> invalidCacheRecoveryCells = new HashSet<Vector2Int>(); private readonly Dictionary<Vector2Int, List<ZNetView>> pendingSoloBakePublications = new Dictionary<Vector2Int, List<ZNetView>>(); private static string MetadataScope => GetWorldMetadataScope(); private static string BakedKey => "PUP_SAFE_Baked_" + MetadataScope; private static string PositionKey => "PUP_SAFE_Position_" + MetadataScope; private static string RotationKey => "PUP_SAFE_Rotation_" + MetadataScope; private static string ScaleKey => "PUP_SAFE_Scale_" + MetadataScope; private static string CellXKey => "PUP_SAFE_CellX_" + MetadataScope; private static string CellZKey => "PUP_SAFE_CellZ_" + MetadataScope; private static string CustomIdKey => "PUP_GRAUSTEN_ID_" + MetadataScope; private static string GetWorldMetadataScope() { if (IsDedicatedServerRuntime()) { return "multiplayer"; } if (ZNet.IsSinglePlayer || ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())) { return "solo"; } if (!((Object)(object)Instance != (Object)null) || !Instance.multiplayerRemoteServerDedicated) { return "solo"; } return "multiplayer"; } private void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown Instance = this; Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnCameraPreCull)); Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnCameraPostRender)); harmony.PatchAll(); InitializeMultiplayerSync(); ((Component)this).gameObject.AddComponent<ServerZoneStreamBlock>().Setup(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); } private void OnDestroy() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnCameraPreCull)); Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnCameraPostRender)); if ((Object)(object)singlePlayerPrecipitationCubeMesh != (Object)null) { Object.Destroy((Object)(object)singlePlayerPrecipitationCubeMesh); } singlePlayerPrecipitationCubeMesh = null; RestoreCoordinatesForVanillaSave("plugin unload"); pendingColliders.Clear(); queuedColliderCount = 0; loadedQueuedColliders = 0; activeColliderLoads = 0; Instance = null; harmony.UnpatchSelf(); foreach (Vector2Int item in clusters.Keys.ToList()) { DestroyCluster(item); } foreach (Material retiredGpuMaterial in retiredGpuMaterials) { if ((Object)(object)retiredGpuMaterial != (Object)null) { Object.Destroy((Object)(object)retiredGpuMaterial); } } retiredGpuMaterials.Clear(); foreach (Material value in materialCopies.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } foreach (Material value2 in highlightMaterials.Values) { if ((Object)(object)value2 != (Object)null) { Object.Destroy((Object)(object)value2); } } foreach (List<MeshRenderer> value3 in hiddenRenderers.Values) { foreach (MeshRenderer item2 in value3) { if ((Object)(object)item2 != (Object)null) { ((Renderer)item2).enabled = true; } } } hiddenRenderers.Clear(); foreach (List<LODGroup> value4 in hiddenLodGroups.Values) { foreach (LODGroup item3 in value4) { if ((Object)(object)item3 != (Object)null) { item3.enabled = true; } } } hiddenLodGroups.Clear(); DisableGpuRenderTest(); } private void OnApplicationQuit() { applicationQuitting = true; RestoreCoordinatesForVanillaSave("application quit"); } private void OnCameraPreCull(Camera camera) { if ((Object)(object)camera != (Object)null && (Object)(object)camera == (Object)(object)Camera.main) { CommitRemoteVisualHandoffsBeforeMainCameraCull(); } if (!((Object)(object)camera == (Object)null) && !(((Object)camera).name != "SkyAlphaCamera")) { RestoreSkyAlphaRendererState(); DrawSinglePlayerPrecipitationMasks(camera); } } private void OnCameraPostRender(Camera camera) { if (!((Object)(object)camera == (Object)null) && !(((Object)camera).name != "SkyAlphaCamera")) { RestoreSkyAlphaRendererState(); } } private void RestoreSkyAlphaRendererState() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<MeshRenderer, bool> item in skyAlphaPreviousEnabled) { if ((Object)(object)item.Key != (Object)null) { ((Renderer)item.Key).enabled = item.Value; if (skyAlphaPreviousLayer.TryGetValue(item.Key, out var value)) { ((Component)item.Key).gameObject.layer = value; } if (skyAlphaPreviousShadowMode.TryGetValue(item.Key, out var value2)) { ((Renderer)item.Key).shadowCastingMode = value2; } } } skyAlphaPreviousEnabled.Clear(); skyAlphaPreviousLayer.Clear(); skyAlphaPreviousShadowMode.Clear(); } private void DrawSinglePlayerPrecipitationMasks(Camera camera) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) foreach (List<MeshRenderer> value in precipitationRenderers.Values) { foreach (MeshRenderer item in value) { if ((Object)(object)item == (Object)null) { continue; } MeshFilter component = ((Component)item).GetComponent<MeshFilter>(); Mesh val = (((Object)(object)component != (Object)null) ? component.sharedMesh : null); Material[] sharedMaterials = ((Renderer)item).sharedMaterials; if ((Object)(object)val == (Object)null || sharedMaterials == null || sharedMaterials.Length == 0) { continue; } Matrix4x4 localToWorldMatrix = ((Component)item).transform.localToWorldMatrix; for (int i = 0; i < val.subMeshCount; i++) { Material val2 = sharedMaterials[Mathf.Min(i, sharedMaterials.Length - 1)]; if (!((Object)(object)val2 == (Object)null)) { Graphics.DrawMesh(val, localToWorldMatrix, val2, 10, camera, i, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false, (Transform)null, (LightProbeUsage)0, (LightProbeProxyVolume)null); } } } } } private void Update() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) MultiplayerUpdate(); UpdateRestoreSupportGuard(); if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return; } if (UnityInput.Current.GetKeyDown((KeyCode)91) && !processing) { if (IsMultiplayerGuest()) { SendServerAdminCommand(1); } else if (loadingCells.Count == 0) { ((MonoBehaviour)this).StartCoroutine(BakeCell(GetCell(((Component)Player.m_localPlayer).transform.position))); } else { ShowMessage("Please wait for streamed zone loading"); } } if (UnityInput.Current.GetKeyDown((KeyCode)93) && !processing) { if (IsMultiplayerGuest()) { SendServerAdminCommand(2); } else if (loadingCells.Count != 0) { ShowMessage("Please wait for streamed zone loading"); } else { Vector2Int? val = FindNearestBakedCell(((Component)Player.m_localPlayer).transform.position, 96f); if (val.HasValue) { ((MonoBehaviour)this).StartCoroutine(UnbakeCell(val.Value)); } else { ShowMessage("No baked cluster nearby"); } } } if (UnityInput.Current.GetKeyDown((KeyCode)92)) { if (IsMultiplayerGuest()) { SendServerAdminCommand(4); } else { highlightEnabled = !highlightEnabled; RefreshHighlights(); ShowMessage(highlightEnabled ? "Cluster highlighting enabled" : "Cluster highlighting disabled"); } } if (UnityInput.Current.GetKeyDown((KeyCode)289) && !processing) { if (IsMultiplayerGuest()) { SendServerAdminCommand(3); } else if (loadingCells.Count == 0) { ((MonoBehaviour)this).StartCoroutine(RestoreAllParked()); } else { ShowMessage("Please wait for streamed zone loading"); } } DrawGpuRenderTest(); ProcessPendingColliders(); UpdateTravelPrediction(); UpdateCacheLoadingProgress(); if (Time.time >= nextColliderActivationCheck) { nextColliderActivationCheck = Time.time + 0.2f; UpdateColliderActivation(); } if (!processing && Time.time >= nextCellCheck) { nextCellCheck = Time.time + 0.5f; UpdateVisibleClusters(); } } private void UpdateCacheLoadingProgress() { //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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null) { ResetCacheLoadingProgress(); return; } if (IsMultiplayerGuest()) { UpdateMultiplayerCacheLoadingProgress(); return; } if (records.Count == 0) { ResetCacheLoadingProgress(); return; } Vector2s valheimZone = ZoneSystem.GetZone(((Component)Player.m_localPlayer).transform.position); SimulationDistance syncedSimulationDistance = ZNet.instance.GetSyncedSimulationDistance(); int activeArea = Mathf.Max(1, ((SimulationDistance)(ref syncedSimulationDistance)).NearSimulationDistance); List<Vector2Int> list = records.Keys.Where((Vector2Int cell) => !pendingWorldSaveRestores.Contains(cell) && CellOverlapsValheimArea(cell, valheimZone, activeArea)).ToList(); int count = list.Count; int num = list.Count((Vector2Int cell) => clusters.ContainsKey(cell) && gpuCacheReadyCells.Contains(cell) && !loadingCells.Contains(cell) && !suppressedVisualCells.Contains(cell)); if (count <= 0 || (num >= count && loadingCells.Count == 0 && pendingSubClusterLoads == 0 && queuedColliderCount == 0 && activeColliderLoads == 0 && !visualWarmupRunning)) { ResetCacheLoadingProgress(); return; } if (!cacheLoadingProgressActive) { cacheLoadingProgressActive = true; cacheLoadingProgressStarted = Time.realtimeSinceStartup; } cacheLoadingProgressCompleted = Mathf.Clamp(num, 0, count); cacheLoadingProgressTotal = count; cacheLoadingProgressVisible = Time.realtimeSinceStartup - cacheLoadingProgressStarted >= 2f; } private void UpdateMultiplayerCacheLoadingProgress() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) if (!multiplayerManifestReceived) { ResetCacheLoadingProgress(); } else { if (multiplayerRemoteServerDedicated && !IsDedicatedVanillaStreamingReady()) { return; } Vector3 playerPosition = ((Component)Player.m_localPlayer).transform.position; float requestRadiusSquared = 36864f; if (!multiplayerStartupProgressCaptured) { multiplayerStartupProgressCells.Clear(); multiplayerStartupProgressCells.UnionWith(multiplayerRemoteCells.Keys.Where((Vector2Int cell) => CellDistanceSquared(cell, playerPosition) <= requestRadiusSquared && (!multiplayerRemoteServerDedicated || IsDedicatedVanillaStreamingReady(cell)) && !multiplayerPendingVanillaRestore.Contains(cell))); multiplayerStartupProgressCaptured = true; multiplayerStartupProgressCompleted = multiplayerStartupProgressCells.Count == 0; } if (multiplayerStartupProgressCompleted) { ResetCacheLoadingProgress(); return; } List<Vector2Int> list = multiplayerStartupProgressCells.Where((Vector2Int cell) => multiplayerRemoteCells.ContainsKey(cell) && !multiplayerPendingVanillaRestore.Contains(cell) && CellDistanceSquared(cell, playerPosition) <= requestRadiusSquared && (!multiplayerRemoteServerDedicated || IsDedicatedVanillaStreamingReady(cell))).ToList(); int count = list.Count; foreach (Vector2Int item in list) { if (clusters.ContainsKey(item) && gpuCacheReadyCells.Contains(item) && !suppressedVisualCells.Contains(item) && multiplayerRemotePhysicsReady.Contains(item) && !multiplayerPendingVanillaRestore.Contains(item)) { multiplayerStartupReadyCells.Add(item); } } int num = list.Count((Vector2Int cell) => multiplayerStartupReadyCells.Contains(cell)); if (count <= 0 || num >= count) { multiplayerStartupProgressCompleted = true; ResetCacheLoadingProgress(); return; } if (!cacheLoadingProgressActive) { cacheLoadingProgressActive = true; cacheLoadingProgressStarted = Time.realtimeSinceStartup; } cacheLoadingProgressCompleted = Mathf.Clamp(num, 0, count); cacheLoadingProgressTotal = count; cacheLoadingProgressVisible = Time.realtimeSinceStartup - cacheLoadingProgressStarted >= 2f; } } private void ResetCacheLoadingProgress() { cacheLoadingProgressActive = false; cacheLoadingProgressVisible = false; cacheLoadingProgressStarted = 0f; cacheLoadingProgressCompleted = 0; cacheLoadingProgressTotal = 0; } private void OnGUI() { //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: 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_002a: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0050: 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_006b: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (cacheLoadingProgressVisible && cacheLoadingProgressTotal > 0) { if (cacheLoadingProgressStyle == null) { cacheLoadingProgressStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 20, fontStyle = (FontStyle)1 }; cacheLoadingProgressStyle.normal.textColor = Color.white; cacheLoadingProgressShadowStyle = new GUIStyle(cacheLoadingProgressStyle); cacheLoadingProgressShadowStyle.normal.textColor = new Color(0f, 0f, 0f, 0.9f); } int num = Mathf.Clamp(Mathf.RoundToInt((float)cacheLoadingProgressCompleted * 100f / (float)cacheLoadingProgressTotal), 0, 100); string text = $"Cache loading: {cacheLoadingProgressCompleted} / " + $"{cacheLoadingProgressTotal} zones ({num}%)"; float num2 = Mathf.Min(640f, (float)Screen.width - 20f); Rect val = default(Rect); ((Rect)(ref val))..ctor(((float)Screen.width - num2) * 0.5f, 92f, num2, 34f); GUI.Label(new Rect(((Rect)(ref val)).x + 2f, ((Rect)(ref val)).y + 2f, ((Rect)(ref val)).width, ((Rect)(ref val)).height), text, cacheLoadingProgressShadowStyle); GUI.Label(val, text, cacheLoadingProgressStyle); } } private void UpdateTravelPrediction() { //IL_000a: 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) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)Player.m_localPlayer).transform.position; if (previousPlayerPosition != Vector3.zero) { Vector3 val = position - previousPlayerPosition; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > 0.0025f) { smoothedTravelDirection = Vector3.Lerp(smoothedTravelDirection, val / Mathf.Max(Time.deltaTime, 0.001f), 0.2f); } } previousPlayerPosition = position; } private Vector3 GetPredictedPlayerPosition() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) Vector3 result = ((Component)Player.m_localPlayer).transform.position + Vector3.ClampMagnitude(smoothedTravelDirection * 2f, 64f); result.y = ((Component)Player.m_localPlayer).transform.position.y; return result; } private static Vector3 GetHorizontalViewForward() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0054: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; Vector3 val = (((Object)(object)main != (Object)null && (Object)(object)((Component)main).transform != (Object)null) ? ((Component)main).transform.forward : ((Component)Player.m_localPlayer).transform.forward); val.y = 0f; if (!(((Vector3)(ref val)).sqrMagnitude > 0.0001f)) { return Vector3.forward; } return ((Vector3)(ref val)).normalized; } private static float GetForwardZonePriority(Vector2Int cell, Vector2Int playerCell, Vector3 playerPosition, Vector3 viewForward) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (cell == playerCell) { return -1E+09f; } Vector3 val = new Vector3(((float)((Vector2Int)(ref cell)).x + 0.5f) * 64f, playerPosition.y, ((float)((Vector2Int)(ref cell)).y + 0.5f) * 64f) - playerPosition; val.y = 0f; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; float num = ((sqrMagnitude > 0.001f) ? Vector3.Dot(val / Mathf.Sqrt(sqrMagnitude), viewForward) : 1f); return ((num >= 0.35f) ? 0f : ((num >= -0.35f) ? 1f : 2f)) * 1000000f + sqrMagnitude; } private void UpdateColliderActivation() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } Vector3 position = ((Component)Player.m_localPlayer).transform.position; Vector3 predictedPlayerPosition = GetPredictedPlayerPosition(); Vector2Int cell = GetCell(position); Vector3 val = default(Vector3); foreach (KeyValuePair<Vector2Int, GameObject> cluster in clusters) { if ((Object)(object)cluster.Value == (Object)null) { continue; } Vector2Int key = cluster.Key; float num = ((float)((Vector2Int)(ref key)).x + 0.5f) * 64f; float y = position.y; key = cluster.Key; ((Vector3)(ref val))..ctor(num, y, ((float)((Vector2Int)(ref key)).y + 0.5f) * 64f); bool value; bool flag = colliderCellActive.TryGetValue(cluster.Key, out value) && value; float num2 = (flag ? 96f : 80f); float num3 = num2 * num2; int num4; if (!ShouldRetainPortalPrewarmCell(cluster.Key) && !(cluster.Key == cell)) { Vector3 val2 = val - position; if (!(((Vector3)(ref val2)).sqrMagnitude <= num3)) { val2 = val - predictedPlayerPosition; num4 = ((((Vector3)(ref val2)).sqrMagnitude <= num3) ? 1 : 0); goto IL_011a; } } num4 = 1; goto IL_011a; IL_011a: bool flag2 = (byte)num4 != 0; if (colliderCellActive.ContainsKey(cluster.Key) && flag == flag2) { continue; } Collider[] componentsInChildren = cluster.Value.GetComponentsInChildren<Collider>(true); foreach (Collider val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null)) { bool flag3 = !flag2 && IsProtectedSupportCollider(cluster.Key, val3); val3.enabled = flag2 || flag3; } } colliderCellActive[cluster.Key] = flag2; } } private static bool TryGetColliderCoordinates(Collider collider, out int subX, out int subZ, out int colliderIndex) { subX = (subZ = (colliderIndex = -1)); string[] array = ((Object)((Component)collider).gameObject).name.Split(new char[1] { '_' }); if (array.Length >= 5 && int.TryParse(array[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out subX) && int.TryParse(array[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out subZ)) { return int.TryParse(array[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out colliderIndex); } return false; } private bool IsProtectedSupportCollider(Vector2Int cell, Collider collider) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!protectedSupportColliders.TryGetValue(cell, out var value) || value.Count == 0) { return false; } if (value.Contains("*")) { return true; } if (!TryGetColliderCoordinates(collider, out var subX, out var subZ, out var colliderIndex)) { return true; } return value.Contains($"{subX}:{subZ}:{colliderIndex}"); } private void DrawGpuRenderTest() { //IL_0016: 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) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Unknown result type (might be due to invalid IL or missing references) //IL_0460: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_048c: Unknown result type (might be due to invalid IL or missing references) //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Unknown result type (might be due to invalid IL or missing references) //IL_04d3: Unknown result type (might be due to invalid IL or missing references) CommitRemoteProvisionalVisualPublicationsBeforeDraw(); CommitRemoteFinalVisualHandoffsBeforeDraw(); Vector3 position = ((Component)Player.m_localPlayer).transform.position; Camera main = Camera.main; bool flag = (Object)(object)main != (Object)null; int num; if (flag) { if (!gpuCullVisibilityDirty && !((Object)(object)gpuCullCamera != (Object)(object)main)) { Vector3 val = gpuCullCameraPosition - ((Component)main).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > 0.01f) && !(Quaternion.Angle(gpuCullCameraRotation, ((Component)main).transform.rotation) > 0.25f) && !(Mathf.Abs(gpuCullCameraFieldOfView - main.fieldOfView) > 0.01f)) { num = ((Mathf.Abs(gpuCullCameraAspect - main.aspect) > 0.001f) ? 1 : 0); goto IL_00c4; } } num = 1; } else { num = 0; } goto IL_00c4; IL_00c4: bool flag2 = (byte)num != 0; if (flag2) { GeometryUtility.CalculateFrustumPlanes(main, gpuFrustumPlanes); gpuCullCamera = main; gpuCullCameraPosition = ((Component)main).transform.position; gpuCullCameraRotation = ((Component)main).transform.rotation; gpuCullCameraFieldOfView = main.fieldOfView; gpuCullCameraAspect = main.aspect; gpuCullVisibilityDirty = false; } Vector3 val2 = default(Vector3); foreach (KeyValuePair<Vector2Int, List<GpuDrawGroup>> gpuBakedGroup in gpuBakedGroups) { bool flag3 = pendingSoloBakePublications.ContainsKey(gpuBakedGroup.Key); if (suppressedVisualCells.Contains(gpuBakedGroup.Key) && (!ZNet.IsSinglePlayer || !gpuCacheReadyCells.Contains(gpuBakedGroup.Key))) { continue; } bool value = true; if (flag && !flag3) { if (flag2 && TryGetGpuCellWorldBounds(gpuBakedGroup.Key, gpuBakedGroup.Value, out var bounds)) { value = GeometryUtility.TestPlanesAABB(gpuFrustumPlanes, bounds); gpuCellCameraVisible[gpuBakedGroup.Key] = value; } else if (!flag2 && !gpuCellCameraVisible.TryGetValue(gpuBakedGroup.Key, out value)) { value = true; } if (!value) { continue; } } Vector2Int key = gpuBakedGroup.Key; float num2 = ((float)((Vector2Int)(ref key)).x + 0.5f) * 64f; float y = position.y; key = gpuBakedGroup.Key; ((Vector3)(ref val2))..ctor(num2, y, ((float)((Vector2Int)(ref key)).y + 0.5f) * 64f); float num3 = Vector3.Distance(position, val2); bool flag4 = false; foreach (GpuDrawGroup item in gpuBakedGroup.Value) { if (item == null || (Object)(object)item.mesh == (Object)null || (Object)(object)item.material == (Object)null) { continue; } if (flag && !flag3) { if (flag2) { EnsureGpuGroupWorldBounds(item); item.cameraVisible = !item.hasWorldBounds || GeometryUtility.TestPlanesAABB(gpuFrustumPlanes, item.worldBounds); } if (!item.cameraVisible) { continue; } } if (item.usesTessellation) { bool flag5 = (item.tessellationEnabled ? (num3 < 128f) : (num3 < 96f)); if (flag5 != item.tessellationEnabled) { item.tessellationEnabled = flag5; if (flag5) { item.material.EnableKeyword("TESSELATION_ON"); } else { item.material.DisableKeyword("TESSELATION_ON"); } } } int materialGroup = GetMaterialGroup(item.material); foreach (Matrix4x4[] chunk in item.chunks) { if (ShouldDrawCellHighlight(gpuBakedGroup.Key)) { Material gpuHighlightMaterial = GetGpuHighlightMaterial(item.material, (materialGroup == 0) ? 1 : materialGroup); Graphics.DrawMeshInstanced(item.mesh, item.subMesh, gpuHighlightMaterial, chunk, chunk.Length, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false, 0, main); } else { Graphics.DrawMeshInstanced(item.mesh, item.subMesh, item.material, chunk, chunk.Length, (MaterialPropertyBlock)null, (ShadowCastingMode)0, true, 0, main); } flag4 = true; } } if (flag4) { PublishSoloBakeAfterDraw(gpuBakedGroup.Key); multiplayerGpuSubmittedFrames[gpuBakedGroup.Key] = Time.frameCount; } if (!flag4 || !singlePlayerVisualHandoffStarted.TryGetValue(gpuBakedGroup.Key, out var _)) { continue; } if (singlePlayerVisualHandoffNeedsParking.Contains(gpuBakedGroup.Key)) { if (CanParkSinglePlayerCell(gpuBakedGroup.Key) && ((Behaviour)this).isActiveAndEnabled && ((Component)this).gameObject.activeInHierarchy && singlePlayerReparkRunning.Add(gpuBakedGroup.Key)) { ReparkBakedCell(gpuBakedGroup.Key); singlePlayerVisualHandoffNeedsParking.Remove(gpuBakedGroup.Key); singlePlayerVisualHandoffStarted.Remove(gpuBakedGroup.Key); singlePlayerReparkRunning.Remove(gpuBakedGroup.Key); } } else { singlePlayerVisualHandoffStarted.Remove(gpuBakedGroup.Key); } } } private void CommitRemoteVisualHandoffsBeforeMainCameraCull() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) if (!multiplayerRemoteServerDedicated || multiplayerPendingVisualHandoffs.Count == 0) { return; } foreach (Vector2Int item in multiplayerPendingVisualHandoffs.Keys.ToList()) { if (!multiplayerGpuSubmittedFrames.TryGetValue(item, out var value) || value != Time.frameCount) { continue; } foreach (RemoteVisualHandoff item2 in multiplayerPendingVisualHandoffs[item]) { if (item2 == null) { continue; } if (!hiddenRenderers.TryGetValue(item2.id, out var value2)) { value2 = (hiddenRenderers[item2.id] = new List<MeshRenderer>()); } foreach (MeshRenderer enabledRenderer in item2.enabledRenderers) { if ((Object)(object)enabledRenderer != (Object)null && !value2.Contains(enabledRenderer)) { value2.Add(enabledRenderer); } } MeshRenderer[] allRenderers = item2.allRenderers; foreach (MeshRenderer val in allRenderers) { if ((Object)(object)val != (Object)null) { ((Renderer)val).enabled = false; } } if (!hiddenLodGroups.TryGetValue(item2.id, out var value3)) { value3 = (hiddenLodGroups[item2.id] = new List<LODGroup>()); } foreach (LODGroup enabledLodGroup in item2.enabledLodGroups) { if ((Object)(object)enabledLodGroup != (Object)null && !value3.Contains(enabledLodGroup)) { value3.Add(enabledLodGroup); } } LODGroup[] allLodGroups = item2.allLodGroups; foreach (LODGroup val2 in allLodGroups) { if ((Object)(object)val2 != (Object)null) { val2.enabled = false; } } } multiplayerPendingVisualHandoffs.Remove(item); multiplayerGpuSubmittedFrames.Remove(item); multiplayerHandoffPublishedFrames.TryGetValue(item, out var _); if (!multiplayerHandoffPublishedTimes.TryGetValue(item, out var _)) { _ = Time.realtimeSinceStartup; } multiplayerHandoffPublishedFrames.Remove(item); multiplayerHandoffPublishedTimes.Remove(item); } } private bool TryGetGpuCellWorldBounds(Vector2Int cell, List<GpuDrawGroup> groups, out Bounds bounds) { //IL_0006: 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) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (gpuCellWorldBounds.TryGetValue(cell, out bounds)) { return true; } bool flag = false; bounds = default(Bounds); foreach (GpuDrawGroup group in groups) { if (group == null) { continue; } EnsureGpuGroupWorldBounds(group); if (group.hasWorldBounds) { if (!flag) { bounds = group.worldBounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(group.worldBounds); } } } if (flag) { gpuCellWorldBounds[cell] = bounds; } return flag; } private static void EnsureGpuGroupWorldBounds(GpuDrawGroup group) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) if (group.hasWorldBounds || (Object)(object)group.mesh == (Object)null) { return; } Bounds bounds = group.mesh.bounds; bool flag = false; Bounds worldBounds = default(Bounds); Vector3 val3 = default(Vector3); Bounds val4 = default(Bounds); foreach (Matrix4x4[] chunk in group.chunks) { if (chunk == null) { continue; } Matrix4x4[] array = chunk; for (int i = 0; i < array.Length; i++) { Matrix4x4 val = array[i]; Vector3 val2 = ((Matrix4x4)(ref val)).MultiplyPoint3x4(((Bounds)(ref bounds)).center); Vector3 extents = ((Bounds)(ref bounds)).extents; ((Vector3)(ref val3))..ctor(Mathf.Abs(val.m00) * extents.x + Mathf.Abs(val.m01) * extents.y + Mathf.Abs(val.m02) * extents.z, Mathf.Abs(val.m10) * extents.x + Mathf.Abs(val.m11) * extents.y + Mathf.Abs(val.m12) * extents.z, Mathf.Abs(val.m20) * extents.x + Mathf.Abs(val.m21) * extents.y + Mathf.Abs(val.m22) * extents.z); ((Bounds)(ref val4))..ctor(val2, val3 * 2f); if (!flag) { worldBounds = val4; flag = true; } else { ((Bounds)(ref worldBounds)).Encapsulate(val4); } } } if (flag) { ((Bounds)(ref worldBounds)).Expand(4f); group.worldBounds = worldBounds; group.hasWorldBounds = true; } } private void EnableGpuBakedRenderTest(Vector2Int cell, List<(ZNetView view, Piece piece)> targets, GameObject cluster) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Invalid comparison between Unknown and I4 //IL_0142: Unknown result type (might be due to invalid IL or missing references) RemoveGpuBakedCell(cell, restoreRenderers: true); List<GpuDrawGroup> list = new List<GpuDrawGroup>(); Dictionary<string, (Mesh, int, Material, List<Matrix4x4>)> dictionary = new Dictionary<string, (Mesh, int, Material, List<Matrix4x4>)>(StringComparer.Ordinal); foreach (var target in targets) { foreach (MeshFilter remoteGpuVisualMeshFilter in GetRemoteGpuVisualMeshFilters(target.piece)) { MeshRenderer component = ((Component)remoteGpuVisualMeshFilter).GetComponent<MeshRenderer>(); if ((Object)(object)component == (Object)null || !((Renderer)component).enabled || (Object)(object)remoteGpuVisualMeshFilter.sharedMesh == (Object)null || (((Renderer)component).sharedMaterials.Length != 0 && ((Renderer)component).sharedMaterials.All((Material material) => (Object)(object)material != (Object)null && NormalizeMaterialName(((Object)material).name).Equals("crystal_window_lod", StringComparison.OrdinalIgnoreCase)))) { continue; } for (int num = 0; num < remoteGpuVisualMeshFilter.sharedMesh.subMeshCount && num < ((Renderer)component).sharedMaterials.Length; num++) { Material val = ((Renderer)component).sharedMaterials[num]; if (!((Object)(object)val == (Object)null)) { string key = $"{((Object)remoteGpuVisualMeshFilter.sharedMesh).GetInstanceID()}|{num}|{((Object)val).GetInstanceID()}"; if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = (remoteGpuVisualMeshFilter.sharedMesh, num, val, new List<Matrix4x4>())); } value.Item4.Add(((Component)remoteGpuVisualMeshFilter).transform.localToWorldMatrix); } } } } foreach (var value2 in dictionary.Values) { Material val2 = Object.Instantiate<Material>(value2.Item3); val2.enableInstancing = true; GpuDrawGroup gpuDrawGroup = new GpuDrawGroup { mesh = value2.Item1, subMesh = value2.Item2, material = val2, usesTessellation = val2.IsKeywordEnabled("TESSELATION_ON"), tessellationEnabled = true }; for (int num2 = 0; num2 < value2.Item4.Count; num2 += 1023) { gpuDrawGroup.chunks.Add(value2.Item4.Skip(num2).Take(1023).ToArray()); } list.Add(gpuDrawGroup); } List<MeshRenderer> list2 = new List<MeshRenderer>(); MeshRenderer[] componentsInChildren = cluster.GetComponentsInChildren<MeshRenderer>(false); foreach (MeshRenderer val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null) && ((Renderer)val3).enabled && (int)((Renderer)val3).shadowCastingMode != 3) { list2.Add(val3); ((Renderer)val3).enabled = false; } } gpuBakedGroups[cell] = list; gpuCellWorldBounds.Remove(cell); gpuCellCameraVisible.Remove(cell); gpuCullVisibilityDirty = true; gpuClusterHidden[cell] = list2; BuildRoofDepthRenderers(cell, cluster, list); BuildCompositeAshwoodDepthRenderers(cell, cluster, targets); } private void HideClusterRenderersForGpu(Vector2Int cell, GameObject root) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Invalid comparison between Unknown and I4 if ((Object)(object)root == (Object)null || !gpuBakedGroups.ContainsKey(cell)) { return; } if (!gpuClusterHidden.TryGetValue(cell, out var value)) { value = new List<MeshRenderer>(); gpuClusterHidden[cell] = value; } MeshRenderer[] componentsInChildren = root.GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && ((Renderer)val).enabled && (int)((Renderer)val).shadowCastingMode != 3) { if (!value.Contains(val)) { value.Add(val); } ((Renderer)val).enabled = false; } } } private void BuildRoofDepthRenderers(Vector2Int cell, GameObject root, IEnumerable<GpuDrawGroup> groups) { //IL_0015: 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) //IL_00a8: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null || groups == null) { return; } int num = 0; Matrix4x4 worldToLocalMatrix = root.transform.worldToLocalMatrix; foreach (GpuDrawGroup group in groups) { if (group == null || (Object)(object)group.mesh == (Object)null || (Object)(object)group.material == (Object)null || group.subMesh != 0 || !NeedsGpuPrecipitationMask(((Object)group.material).name, group.mesh.isReadable)) { continue; } foreach (Matrix4x4[] chunk in group.chunks) { foreach (Matrix4x4 val in chunk) { Matrix4x4 val2 = worldToLocalMatrix * val; GameObject val3 = new GameObject("PUP_DarkwoodDepth") { layer = 10 }; val3.transform.SetParent(root.transform, false); val3.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val2)).GetColumn(3)); val3.transform.localRotation = ((Matrix4x4)(ref val2)).rotation; val3.transform.localScale = ((Matrix4x4)(ref val2)).lossyScale; val3.AddComponent<MeshFilter>().sharedMesh = group.mesh; MeshRenderer val4 = val3.AddComponent<MeshRenderer>(); ((Renderer)val4).sharedMaterial = group.material; ((Renderer)val4).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val4).receiveShadows = false; ((Renderer)val4).enabled = false; RegisterPrecipitationRenderer(cell, val4); num++; } } } } private static bool NeedsGpuPrecipitationMask(string materialName, bool readable) { string text = NormalizeMaterialName(materialName); if (text.Equals("RoofShingles", StringComparison.OrdinalIgnoreCase)) { return true; } if (!readable) { if (!text.Equals("woodwall_67_mat", StringComparison.OrdinalIgnoreCase) && !text.Equals("DarkWood_mat", StringComparison.OrdinalIgnoreCase) && !text.Equals("AshWood_mat", StringComparison.OrdinalIgnoreCase)) { return text.Equals("stonefence_mat", StringComparison.OrdinalIgnoreCase); } return true; } return false; } private void BuildCompositeAshwoodDepthRenderers(Vector2Int cell, GameObject root, IEnumerable<(ZNetView view, Piece piece)> targets) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null || targets == null) { return; } Matrix4x4 worldToLocalMatrix = root.transform.worldToLocalMatrix; foreach (var target in targets) { if (!IsCompositeAshwoodPrefab(target.view)) { continue; } foreach (MeshFilter visualMeshFilter in GetVisualMeshFilters(target.view, target.piece)) { if (!((Object)(object)visualMeshFilter == (Object)null) && !((Object)(object)visualMeshFilter.sharedMesh == (Object)null)) { MeshRenderer component = ((Component)visualMeshFilter).GetComponent<MeshRenderer>(); if (!((Object)(object)component == (Object)null) && ((Renderer)component).sharedMaterials.Length != 0) { Matrix4x4 val = worldToLocalMatrix * ((Component)visualMeshFilter).transform.localToWorldMatrix; GameObject val2 = new GameObject("PUP_AshwoodDepth") { layer = 10 }; val2.transform.SetParent(root.transform, false); val2.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val)).GetColumn(3)); val2.transform.localRotation = ((Matrix4x4)(ref val)).rotation; val2.transform.localScale = ((Matrix4x4)(ref val)).lossyScale; val2.AddComponent<MeshFilter>().sharedMesh = visualMeshFilter.sharedMesh; MeshRenderer val3 = val2.AddComponent<MeshRenderer>(); ((Renderer)val3).sharedMaterials = ((Renderer)component).sharedMaterials; ((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val3).receiveShadows = false; ((Renderer)val3).enabled = false; RegisterPrecipitationRenderer(cell, val3); } } } } } private void DisableGpuRenderTest() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) foreach (Vector2Int item in gpuBakedGroups.Keys.ToList()) { RemoveGpuBakedCell(item, restoreRenderers: true); } } private void RemoveGpuBakedCell(Vector2Int cell, bool restoreRenderers) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) if (gpuClusterHidden.TryGetValue(cell, out var value)) { if (restoreRenderers) { foreach (MeshRenderer item in value) { if ((Object)(object)item != (Object)null) { ((Renderer)item).enabled = true; } } } gpuClusterHidden.Remove(cell); } if (!gpuBakedGroups.TryGetValue(cell, out var value2)) { return; } bool flag = (Object)(object)ZNet.instance != (Object)null && ZNet.IsSinglePlayer && singlePlayerFullGpuCells.Contains(cell) && ((Behaviour)this).isActiveAndEnabled && ((Component)this).gameObject.activeInHierarchy && !applicationQuitting; foreach (Material item2 in (from @group in value2 where @group != null && (Object)(object)@group.material != (Object)null select @group.material).Distinct()) { if ((Object)(object)item2 != (Object)null) { if (flag) { ((MonoBehaviour)this).StartCoroutine(DestroySinglePlayerFastMaterialDeferred(item2)); } else { retiredGpuMaterials.Add(item2); } } } gpuBakedGroups.Remove(cell); gpuCellWorldBounds.Remove(cell); gpuCellCameraVisible.Remove(cell); gpuCullVisibilityDirty = true; } private static Vector2Int GetCell(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) return new Vector2Int(Mathf.FloorToInt(position.x / 64f), Mathf.FloorToInt(position.z / 64f)); } private void UpdateVisibleClusters() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due