Decompiled source of False Gods v0.4.0
FalseGods.Application.dll
Decompiled 9 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using FalseGods.Application.ReadyGate; using FalseGods.Application.Replication; using FalseGods.Application.Wire; using FalseGods.Core.Arena; using FalseGods.Core.Arena.Events; using FalseGods.Core.Bosses; using FalseGods.Core.Bosses.Combat; using FalseGods.Core.Bosses.Events; using FalseGods.Core.Encounters; using FalseGods.Core.Simulation; using FalseGods.Protocol.Arena; using FalseGods.Protocol.Wire; using FalseGods.RuntimeContracts.Arena; using FalseGods.RuntimeContracts.Diagnostics; using FalseGods.RuntimeContracts.Multiplayer; using FalseGods.RuntimeContracts.Presentation; using FalseGods.RuntimeContracts.Transport; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FalseGods.Application")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6e5740a80f810ab422551028733810b527fb614d")] [assembly: AssemblyProduct("FalseGods.Application")] [assembly: AssemblyTitle("FalseGods.Application")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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; } } internal static class IsExternalInit { } } namespace FalseGods.Application.Wire { public static class ArenaWireMapping { public static ArenaSnapshot ToSnapshot(ArenaSimulation arena, EncounterId encounter, string arenaId, int arenaVersion, SimulationTick tick, Sequence lastProcessedArenaEventSequence) { //IL_001a: 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_0022: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (arena == null) { throw new ArgumentNullException("arena"); } List<MechanismGroupId> list = new List<MechanismGroupId>(arena.ActiveMechanismGroups); return new ArenaSnapshot(encounter, arenaId, arenaVersion, ProtocolVersion.Current, tick, (IReadOnlyList<MechanismGroupId>)list, arena.IsExitUnlocked, lastProcessedArenaEventSequence); } public static IArenaWireEvent ToWireEvent(IArenaDomainEvent domainEvent, Sequence sequence, SimulationTick tick) { //IL_0017: 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_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_0025: Expected O, but got Unknown //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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown MechanismGroupActivated val = (MechanismGroupActivated)(object)((domainEvent is MechanismGroupActivated) ? domainEvent : null); if (val == null) { if (!(domainEvent is ArenaExitUnlocked)) { if (domainEvent == null) { throw new ArgumentNullException("domainEvent"); } throw new ArgumentOutOfRangeException("domainEvent", ((object)domainEvent).GetType().Name, "No wire mapping for this arena domain event."); } return (IArenaWireEvent)new ArenaExitUnlockedEvent(sequence, tick); } return (IArenaWireEvent)new ArenaMechanismGroupActivatedEvent(sequence, tick, val.Group); } } public static class BossWireMapping { public static BossSnapshot ToSnapshot(BossSimulation boss, EncounterId encounter, DefinitionId definition, SimulationTick tick, Sequence lastProcessedBossEventSequence) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected I4, but got Unknown //IL_0035: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_004f: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected I4, but got Unknown //IL_0092: Expected I4, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown if (boss == null) { throw new ArgumentNullException("boss"); } AttackInstanceId? currentAttack = boss.CurrentAttack; int? num = (currentAttack.HasValue ? new int?((int)boss.CurrentAttackKind) : ((int?)null)); return new BossSnapshot(encounter, boss.Id, definition, ProtocolVersion.Current, tick, (int)boss.Phase, (int)boss.Activity, tick, currentAttack, num, (ParticipantId?)null, boss.Position, boss.PositionHeight, boss.Facing, boss.Health, boss.MaxHealth, boss.IsWeakPointExposed, boss.IsEnraged, boss.HasBegun, lastProcessedBossEventSequence); } public static IBossWireEvent ToWireEvent(IBossDomainEvent domainEvent, Sequence sequence, SimulationTick tick) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_009e: Expected I4, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_009f: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00a7: 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_00aa: 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected I4, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_00c7: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected I4, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_00e1: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_00ef: 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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected I4, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown //IL_00fe: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_011b: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown BossSpawned val = (BossSpawned)(object)((domainEvent is BossSpawned) ? domainEvent : null); if (val == null) { if (!(domainEvent is BossBegan)) { AttackTelegraphed val2 = (AttackTelegraphed)(object)((domainEvent is AttackTelegraphed) ? domainEvent : null); if (val2 == null) { AttackCommitted val3 = (AttackCommitted)(object)((domainEvent is AttackCommitted) ? domainEvent : null); if (val3 == null) { WeakPointExposed val4 = (WeakPointExposed)(object)((domainEvent is WeakPointExposed) ? domainEvent : null); if (val4 == null) { BossPhaseChanged val5 = (BossPhaseChanged)(object)((domainEvent is BossPhaseChanged) ? domainEvent : null); if (val5 == null) { BossDamaged val6 = (BossDamaged)(object)((domainEvent is BossDamaged) ? domainEvent : null); if (val6 == null) { BossRelocated val7 = (BossRelocated)(object)((domainEvent is BossRelocated) ? domainEvent : null); if (val7 == null) { BossEnraged val8 = (BossEnraged)(object)((domainEvent is BossEnraged) ? domainEvent : null); if (val8 == null) { if (!(domainEvent is BossDied)) { if (domainEvent == null) { throw new ArgumentNullException("domainEvent"); } throw new ArgumentOutOfRangeException("domainEvent", ((object)domainEvent).GetType().Name, "No wire mapping for this boss domain event."); } return (IBossWireEvent)new BossDefeatedEvent(sequence, tick); } return (IBossWireEvent)new BossEnragedEvent(sequence, tick, val8.Enraged); } return (IBossWireEvent)new BossRelocatedEvent(sequence, tick, val7.StationIndex, val7.AnchorIndex, val7.Position, val7.Height); } return (IBossWireEvent)new BossDamagedEvent(sequence, tick, val6.Amount, val6.RemainingHealth, val6.WeakPointHit); } return (IBossWireEvent)new BossPhaseChangedEvent(sequence, tick, (int)val5.Phase); } return (IBossWireEvent)new BossWeakPointChangedEvent(sequence, tick, val4.Exposed); } return (IBossWireEvent)new BossAttackCommittedEvent(sequence, tick, val3.Attack, (int)val3.Kind, val3.AimPoint); } return (IBossWireEvent)new BossAttackTelegraphedEvent(sequence, tick, val2.Attack, (int)val2.Kind, val2.AimPoint, val2.TelegraphSeconds); } return (IBossWireEvent)new BossBeganEvent(sequence, tick); } return (IBossWireEvent)new BossAppearedEvent(sequence, tick, (int)val.Phase); } } } namespace FalseGods.Application.Replication { public enum ReplicationKind : byte { BossSnapshot = 1, ArenaSnapshot, BossEvent, ArenaEvent, EncounterBaseline, EnterArena, ArenaReady, ArenaLoadFailed, EncounterAborted, EncounterEnded, ClientHitRequest, BossHitPlayer, ArenaLevelDeclared, ArenaLevelRequested, CrateDropped, CrateThrown, CrateVolleyFired, CratesTaken, CratesSetDown, CrateDestroyed, CrateDestroyRequested } public readonly struct DecodedMessage { public ReplicationKind Kind { get; } public object Value { get; } public DecodedMessage(ReplicationKind kind, object value) { Kind = kind; Value = value; } } public static class EncounterCodec { public static EncodedPayload Encode(BossSnapshot snapshot) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.BossSnapshot, WireCodec.Serialize(snapshot)); } public static EncodedPayload Encode(ArenaSnapshot snapshot) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.ArenaSnapshot, WireCodec.Serialize(snapshot)); } public static EncodedPayload Encode(IBossWireEvent bossEvent) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.BossEvent, WireCodec.Serialize(bossEvent)); } public static EncodedPayload Encode(IArenaWireEvent arenaEvent) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.ArenaEvent, WireCodec.Serialize(arenaEvent)); } public static EncodedPayload Encode(EncounterBaseline baseline) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.EncounterBaseline, WireCodec.Serialize(baseline)); } public static EncodedPayload Encode(EnterArena message) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.EnterArena, WireCodec.Serialize(message)); } public static EncodedPayload Encode(ArenaReady message) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.ArenaReady, WireCodec.Serialize(message)); } public static EncodedPayload Encode(ArenaLoadFailed message) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.ArenaLoadFailed, WireCodec.Serialize(message)); } public static EncodedPayload Encode(EncounterAborted message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.EncounterAborted, WireCodec.Serialize(message)); } public static EncodedPayload Encode(EncounterEnded message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.EncounterEnded, WireCodec.Serialize(message)); } public static EncodedPayload Encode(ClientHitRequest message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.ClientHitRequest, WireCodec.Serialize(message)); } public static EncodedPayload Encode(BossHitPlayer message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.BossHitPlayer, WireCodec.Serialize(message)); } public static EncodedPayload Encode(ArenaLevelDeclared message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.ArenaLevelDeclared, WireCodec.Serialize(message)); } public static EncodedPayload Encode(ArenaLevelRequested message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.ArenaLevelRequested, WireCodec.Serialize(message)); } public static EncodedPayload Encode(CrateDropped message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.CrateDropped, WireCodec.Serialize(message)); } public static EncodedPayload Encode(CrateThrown message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.CrateThrown, WireCodec.Serialize(message)); } public static EncodedPayload Encode(CrateVolleyFired message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.CrateVolleyFired, WireCodec.Serialize(message)); } public static EncodedPayload Encode(CratesTaken message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.CratesTaken, WireCodec.Serialize(message)); } public static EncodedPayload Encode(CratesSetDown message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.CratesSetDown, WireCodec.Serialize(message)); } public static EncodedPayload Encode(CrateDestroyed message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.CrateDestroyed, WireCodec.Serialize(message)); } public static EncodedPayload Encode(CrateDestroyRequested message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return Wrap(ReplicationKind.CrateDestroyRequested, WireCodec.Serialize(message)); } public static DecodedMessage Decode(EncodedPayload payload) { byte[] array = ((EncodedPayload)(ref payload)).ToArray(); if (array.Length == 0) { throw new InvalidDataException("Empty replication payload: no kind tag."); } ReplicationKind replicationKind = (ReplicationKind)array[0]; byte[] array2 = new byte[array.Length - 1]; Array.Copy(array, 1, array2, 0, array2.Length); return replicationKind switch { ReplicationKind.BossSnapshot => new DecodedMessage(replicationKind, WireCodec.DeserializeBossSnapshot(array2)), ReplicationKind.ArenaSnapshot => new DecodedMessage(replicationKind, WireCodec.DeserializeArenaSnapshot(array2)), ReplicationKind.BossEvent => new DecodedMessage(replicationKind, WireCodec.DeserializeBossEvent(array2)), ReplicationKind.ArenaEvent => new DecodedMessage(replicationKind, WireCodec.DeserializeArenaEvent(array2)), ReplicationKind.EncounterBaseline => new DecodedMessage(replicationKind, WireCodec.DeserializeBaseline(array2)), ReplicationKind.EnterArena => new DecodedMessage(replicationKind, WireCodec.DeserializeEnterArena(array2)), ReplicationKind.ArenaReady => new DecodedMessage(replicationKind, WireCodec.DeserializeArenaReady(array2)), ReplicationKind.ArenaLoadFailed => new DecodedMessage(replicationKind, WireCodec.DeserializeArenaLoadFailed(array2)), ReplicationKind.EncounterAborted => new DecodedMessage(replicationKind, WireCodec.DeserializeEncounterAborted(array2)), ReplicationKind.EncounterEnded => new DecodedMessage(replicationKind, WireCodec.DeserializeEncounterEnded(array2)), ReplicationKind.ClientHitRequest => new DecodedMessage(replicationKind, WireCodec.DeserializeClientHitRequest(array2)), ReplicationKind.BossHitPlayer => new DecodedMessage(replicationKind, WireCodec.DeserializeBossHitPlayer(array2)), ReplicationKind.ArenaLevelDeclared => new DecodedMessage(replicationKind, WireCodec.DeserializeArenaLevelDeclared(array2)), ReplicationKind.ArenaLevelRequested => new DecodedMessage(replicationKind, WireCodec.DeserializeArenaLevelRequested(array2)), ReplicationKind.CrateDropped => new DecodedMessage(replicationKind, WireCodec.DeserializeCrateDropped(array2)), ReplicationKind.CrateThrown => new DecodedMessage(replicationKind, WireCodec.DeserializeCrateThrown(array2)), ReplicationKind.CrateVolleyFired => new DecodedMessage(replicationKind, WireCodec.DeserializeCrateVolleyFired(array2)), ReplicationKind.CratesTaken => new DecodedMessage(replicationKind, WireCodec.DeserializeCratesTaken(array2)), ReplicationKind.CratesSetDown => new DecodedMessage(replicationKind, WireCodec.DeserializeCratesSetDown(array2)), ReplicationKind.CrateDestroyed => new DecodedMessage(replicationKind, WireCodec.DeserializeCrateDestroyed(array2)), ReplicationKind.CrateDestroyRequested => new DecodedMessage(replicationKind, WireCodec.DeserializeCrateDestroyRequested(array2)), _ => throw new InvalidDataException($"Unknown replication kind tag {array[0]}."), }; } private static EncodedPayload Wrap(ReplicationKind kind, byte[] wireBytes) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) byte[] array = new byte[wireBytes.Length + 1]; array[0] = (byte)kind; Array.Copy(wireBytes, 0, array, 1, wireBytes.Length); return new EncodedPayload(array); } } public sealed class EncounterHostReplication { private static readonly Sequence NoEvents = new Sequence(-1L); private readonly ReplicationSender _sender; private readonly IMultiplayerSession _session; private readonly IPlayerRoster _roster; private readonly EncounterId _encounter; private readonly DefinitionId _definition; private readonly ArenaManifest _manifest; private readonly WorldPosition _arenaOrigin; private readonly HashSet<SessionPeerId> _baselinedPeers = new HashSet<SessionPeerId>(); private Sequence _lastBossSequence = NoEvents; private Sequence _lastArenaSequence = NoEvents; public Sequence LastBossSequence => _lastBossSequence; public Sequence LastArenaSequence => _lastArenaSequence; public EncounterHostReplication(ReplicationSender sender, IMultiplayerSession session, IPlayerRoster roster, EncounterId encounter, DefinitionId definition, ArenaManifest manifest, WorldPosition arenaOrigin = default(WorldPosition)) { //IL_000c: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_006c: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) _sender = sender ?? throw new ArgumentNullException("sender"); _session = session ?? throw new ArgumentNullException("session"); _roster = roster ?? throw new ArgumentNullException("roster"); _encounter = encounter; _definition = definition; _manifest = manifest ?? throw new ArgumentNullException("manifest"); _arenaOrigin = arenaOrigin; } public void Publish(BossSimulation boss, IReadOnlyList<IBossDomainEvent> drainedEvents, SimulationTick tick) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) PublishCore(boss, drainedEvents, null, Array.Empty<IArenaDomainEvent>(), null, tick); } public void Publish(BossSimulation boss, IReadOnlyList<IBossDomainEvent> drainedBossEvents, ArenaSimulation arena, IReadOnlyList<IArenaDomainEvent> drainedArenaEvents, EncounterPhase phase, SimulationTick tick) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (arena == null) { throw new ArgumentNullException("arena"); } PublishCore(boss, drainedBossEvents, arena, drainedArenaEvents, phase, tick); } private void PublishCore(BossSimulation boss, IReadOnlyList<IBossDomainEvent> drainedBossEvents, ArenaSimulation? arena, IReadOnlyList<IArenaDomainEvent> drainedArenaEvents, EncounterPhase? phase, SimulationTick tick) { //IL_0030: 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_0047: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) if (boss == null) { throw new ArgumentNullException("boss"); } if (drainedBossEvents == null) { throw new ArgumentNullException("drainedBossEvents"); } if (drainedArenaEvents == null) { throw new ArgumentNullException("drainedArenaEvents"); } BaselineNewPeers(boss, arena, phase, tick); for (int i = 0; i < drainedBossEvents.Count; i++) { _lastBossSequence = ((Sequence)(ref _lastBossSequence)).Next(); _sender.BroadcastBossEvent(BossWireMapping.ToWireEvent(drainedBossEvents[i], _lastBossSequence, tick)); } for (int j = 0; j < drainedArenaEvents.Count; j++) { _lastArenaSequence = ((Sequence)(ref _lastArenaSequence)).Next(); _sender.BroadcastArenaEvent(ArenaWireMapping.ToWireEvent(drainedArenaEvents[j], _lastArenaSequence, tick)); } _sender.BroadcastBossSnapshot(BossWireMapping.ToSnapshot(boss, _encounter, _definition, tick, _lastBossSequence)); if (arena != null) { _sender.BroadcastArenaSnapshot(BuildArenaSnapshot(arena, tick)); } } private void BaselineNewPeers(BossSimulation boss, ArenaSimulation? arena, EncounterPhase? phase, SimulationTick tick) { //IL_003a: 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_0040: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_007e: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<SessionPeerId> members = _roster.Members; _baselinedPeers.RemoveWhere((SessionPeerId peer) => !Contains(members, peer)); for (int num = 0; num < members.Count; num++) { SessionPeerId val = members[num]; if (!(val == _session.LocalPeer) && !_baselinedPeers.Contains(val)) { _sender.SendBaseline(BuildBaseline(boss, arena, phase, tick), val); _baselinedPeers.Add(val); } } } private EncounterBaseline BuildBaseline(BossSimulation boss, ArenaSimulation? arena, EncounterPhase? phase, SimulationTick tick) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected I4, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected I4, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown ArenaSnapshot val = (ArenaSnapshot)((arena != null) ? ((object)BuildArenaSnapshot(arena, tick)) : ((object)new ArenaSnapshot(_encounter, _manifest.ArenaId, _manifest.ArenaVersion, ProtocolVersion.Current, tick, (IReadOnlyList<MechanismGroupId>)Array.Empty<MechanismGroupId>(), false, NoEvents))); EncounterPhase val2 = (EncounterPhase)(((int?)phase) ?? ((!boss.IsDead) ? 1 : 2)); return new EncounterBaseline(_encounter, ProtocolVersion.Current, _manifest.ArenaId, _manifest.ArenaVersion, _manifest.ContentHash, _arenaOrigin, tick, (int)val2, BossWireMapping.ToSnapshot(boss, _encounter, _definition, tick, _lastBossSequence), val, _lastBossSequence, _lastArenaSequence); } private ArenaSnapshot BuildArenaSnapshot(ArenaSimulation arena, SimulationTick tick) { //IL_0002: 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) return ArenaWireMapping.ToSnapshot(arena, _encounter, _manifest.ArenaId, _manifest.ArenaVersion, tick, _lastArenaSequence); } private static bool Contains(IReadOnlyList<SessionPeerId> members, SessionPeerId peer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < members.Count; i++) { if (members[i] == peer) { return true; } } return false; } } public sealed class ReplicationReceiver : IDisposable { private readonly IEncounterChannel _channel; private readonly IMultiplayerSession _session; private readonly HashSet<long> _appliedBossSequences = new HashSet<long>(); private readonly HashSet<long> _appliedArenaSequences = new HashSet<long>(); private readonly HashSet<long> _committedAttacks = new HashSet<long>(); private readonly List<IBossWireEvent> _appliedBossEvents = new List<IBossWireEvent>(); private readonly List<IArenaWireEvent> _appliedArenaEvents = new List<IArenaWireEvent>(); private long _bossFloor = -1L; private long _arenaFloor = -1L; private long _lastBossSnapshotTick = long.MinValue; private long _lastArenaSnapshotTick = long.MinValue; public int DroppedFromNonHost { get; private set; } public int DroppedMalformed { get; private set; } public int DroppedVersionMismatch { get; private set; } public IReadOnlyList<IBossWireEvent> AppliedBossEvents => _appliedBossEvents; public IReadOnlyList<IArenaWireEvent> AppliedArenaEvents => _appliedArenaEvents; public int CommittedAttackCount => _committedAttacks.Count; public BossSnapshot? LatestBossSnapshot { get; private set; } public ArenaSnapshot? LatestArenaSnapshot { get; private set; } public bool HasBaseline { get; private set; } public EncounterBaseline? Baseline { get; private set; } public ReplicationReceiver(IEncounterChannel channel, IMultiplayerSession session) { _channel = channel ?? throw new ArgumentNullException("channel"); _session = session ?? throw new ArgumentNullException("session"); _channel.Received += OnReceived; } public void Dispose() { _channel.Received -= OnReceived; } public void Apply(EncodedPayload payload) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) ApplyDecoded(EncounterCodec.Decode(payload)); } private void OnReceived(SessionPeerId sender, EncodedPayload payload) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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) if (sender != _session.HostPeer) { DroppedFromNonHost++; return; } DecodedMessage message; try { message = EncounterCodec.Decode(payload); } catch (Exception) { DroppedMalformed++; return; } ApplyDecoded(message); } private void ApplyDecoded(DecodedMessage message) { //IL_0088: 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_00c7: Unknown result type (might be due to invalid IL or missing references) object value = message.Value; BossSnapshot val = (BossSnapshot)((value is BossSnapshot) ? value : null); if (val == null) { ArenaSnapshot val2 = (ArenaSnapshot)((value is ArenaSnapshot) ? value : null); if (val2 == null) { IBossWireEvent val3 = (IBossWireEvent)((value is IBossWireEvent) ? value : null); if (val3 == null) { IArenaWireEvent val4 = (IArenaWireEvent)((value is IArenaWireEvent) ? value : null); if (val4 == null) { EncounterBaseline val5 = (EncounterBaseline)((value is EncounterBaseline) ? value : null); if (val5 == null) { if (!(value is EnterArena) && !(value is ArenaReady) && !(value is ArenaLoadFailed) && !(value is EncounterAborted) && !(value is EncounterEnded)) { throw new InvalidOperationException("Unhandled replication value " + (message.Value?.GetType().Name ?? "null") + "."); } } else if (!RejectVersion(val5.ProtocolVersion)) { ApplyBaseline(val5); } } else { ApplyArenaEvent(val4); } } else { ApplyBossEvent(val3); } } else if (!RejectVersion(val2.ProtocolVersion)) { ApplyArenaSnapshot(val2); } } else if (!RejectVersion(val.ProtocolVersion)) { ApplyBossSnapshot(val); } } private bool RejectVersion(ProtocolVersion version) { //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) if (version != ProtocolVersion.Current) { DroppedVersionMismatch++; return true; } return false; } private void ApplyBossSnapshot(BossSnapshot snapshot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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) SimulationTick tick = snapshot.Tick; if (((SimulationTick)(ref tick)).Value >= _lastBossSnapshotTick) { LatestBossSnapshot = snapshot; tick = snapshot.Tick; _lastBossSnapshotTick = ((SimulationTick)(ref tick)).Value; } } private void ApplyArenaSnapshot(ArenaSnapshot snapshot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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) SimulationTick tick = snapshot.Tick; if (((SimulationTick)(ref tick)).Value >= _lastArenaSnapshotTick) { LatestArenaSnapshot = snapshot; tick = snapshot.Tick; _lastArenaSnapshotTick = ((SimulationTick)(ref tick)).Value; } } private void ApplyBossEvent(IBossWireEvent bossEvent) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_003d: Unknown result type (might be due to invalid IL or missing references) Sequence sequence = bossEvent.Sequence; long value = ((Sequence)(ref sequence)).Value; if (value > _bossFloor && _appliedBossSequences.Add(value)) { BossAttackCommittedEvent val = (BossAttackCommittedEvent)(object)((bossEvent is BossAttackCommittedEvent) ? bossEvent : null); if (val != null) { HashSet<long> committedAttacks = _committedAttacks; AttackInstanceId attack = val.Attack; committedAttacks.Add(((AttackInstanceId)(ref attack)).Value); } _appliedBossEvents.Add(bossEvent); } } private void ApplyArenaEvent(IArenaWireEvent arenaEvent) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) Sequence sequence = arenaEvent.Sequence; long value = ((Sequence)(ref sequence)).Value; if (value > _arenaFloor && _appliedArenaSequences.Add(value)) { _appliedArenaEvents.Add(arenaEvent); } } private void ApplyBaseline(EncounterBaseline baseline) { //IL_0019: 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_002d: 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_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_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) if (!HasBaseline) { HasBaseline = true; Baseline = baseline; Sequence val = baseline.LastProcessedBossEventSequence; _bossFloor = ((Sequence)(ref val)).Value; val = baseline.LastProcessedArenaEventSequence; _arenaFloor = ((Sequence)(ref val)).Value; LatestBossSnapshot = baseline.Boss; LatestArenaSnapshot = baseline.Arena; SimulationTick tick = baseline.Boss.Tick; _lastBossSnapshotTick = ((SimulationTick)(ref tick)).Value; tick = baseline.Arena.Tick; _lastArenaSnapshotTick = ((SimulationTick)(ref tick)).Value; } } } public sealed class ReplicationSender { private readonly IEncounterChannel _channel; private readonly IMultiplayerSession _session; public ReplicationSender(IEncounterChannel channel, IMultiplayerSession session) { _channel = channel ?? throw new ArgumentNullException("channel"); _session = session ?? throw new ArgumentNullException("session"); } public void BroadcastBossSnapshot(BossSnapshot snapshot) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Send(EncounterCodec.Encode(snapshot), (MessageDelivery)1, MessageTarget.AllClients); } public void BroadcastArenaSnapshot(ArenaSnapshot snapshot) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Send(EncounterCodec.Encode(snapshot), (MessageDelivery)1, MessageTarget.AllClients); } public void BroadcastBossEvent(IBossWireEvent bossEvent) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Send(EncounterCodec.Encode(bossEvent), (MessageDelivery)0, MessageTarget.AllClients); } public void BroadcastArenaEvent(IArenaWireEvent arenaEvent) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Send(EncounterCodec.Encode(arenaEvent), (MessageDelivery)0, MessageTarget.AllClients); } public void SendBaseline(EncounterBaseline baseline, SessionPeerId peer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Send(EncounterCodec.Encode(baseline), (MessageDelivery)0, MessageTarget.ToPeer(peer)); } public void BroadcastEnterArena(EnterArena message) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Send(EncounterCodec.Encode(message), (MessageDelivery)0, MessageTarget.AllClients); } public void BroadcastAborted(EncounterAborted message) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Send(EncounterCodec.Encode(message), (MessageDelivery)0, MessageTarget.AllClients); } public void BroadcastEnded(EncounterEnded message) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Send(EncounterCodec.Encode(message), (MessageDelivery)0, MessageTarget.AllClients); } public void SendBossHitPlayer(BossHitPlayer message, SessionPeerId peer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Send(EncounterCodec.Encode(message), (MessageDelivery)0, MessageTarget.ToPeer(peer)); } private void Send(EncodedPayload payload, MessageDelivery delivery, MessageTarget target) { //IL_0006: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if ((int)_session.Role != 0) { throw new InvalidOperationException("Only the host replicates encounter state; a client must not broadcast."); } _channel.Send(payload, delivery, target); } } } namespace FalseGods.Application.ReadyGate { public enum GateStatus { Waiting, Resolved, Aborted } public enum GateAbortReason { None, ContentHashSchemaMismatch, VersionMismatch, ContentMismatch, LoadFailed, Timeout } public sealed class EncounterReadyGate { private readonly ArenaManifest _hostManifest; private readonly IPlayerRoster _roster; private readonly HashSet<SessionPeerId> _ready = new HashSet<SessionPeerId>(); public GateStatus Status { get { if (AbortReason != GateAbortReason.None) { return GateStatus.Aborted; } if (!AllRequiredReady()) { return GateStatus.Waiting; } return GateStatus.Resolved; } } public GateAbortReason AbortReason { get; private set; } public IReadOnlyList<SessionPeerId> Outstanding => _roster.Members.Where((SessionPeerId m) => !_ready.Contains(m)).ToList(); public EncounterReadyGate(ArenaManifest hostManifest, IPlayerRoster roster) { _hostManifest = hostManifest ?? throw new ArgumentNullException("hostManifest"); _roster = roster ?? throw new ArgumentNullException("roster"); } public GateStatus SubmitReady(SessionPeerId peer, ArenaManifest report) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_00b3: 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_00d8: Unknown result type (might be due to invalid IL or missing references) if (report == null) { throw new ArgumentNullException("report"); } if (AbortReason != GateAbortReason.None) { return GateStatus.Aborted; } if (!_roster.Members.Contains(peer)) { return Status; } if (report.ContentHashSchemaVersion != _hostManifest.ContentHashSchemaVersion) { return Abort(GateAbortReason.ContentHashSchemaMismatch); } if (!string.Equals(report.ArenaId, _hostManifest.ArenaId, StringComparison.Ordinal) || report.ArenaVersion != _hostManifest.ArenaVersion || report.ProtocolVersion != _hostManifest.ProtocolVersion || !string.Equals(report.BundleVersion, _hostManifest.BundleVersion, StringComparison.Ordinal)) { return Abort(GateAbortReason.VersionMismatch); } if (report.ContentHash != _hostManifest.ContentHash) { return Abort(GateAbortReason.ContentMismatch); } _ready.Add(peer); return Status; } public GateStatus SubmitLoadFailed(SessionPeerId peer) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (AbortReason != GateAbortReason.None) { return GateStatus.Aborted; } if (!_roster.Members.Contains(peer)) { return Status; } return Abort(GateAbortReason.LoadFailed); } public GateStatus OnTimeout() { if (Status == GateStatus.Waiting) { return Abort(GateAbortReason.Timeout); } return Status; } private bool AllRequiredReady() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<SessionPeerId> members = _roster.Members; if (members.Count == 0) { return false; } for (int i = 0; i < members.Count; i++) { if (!_ready.Contains(members[i])) { return false; } } return true; } private GateStatus Abort(GateAbortReason reason) { AbortReason = reason; return GateStatus.Aborted; } } } namespace FalseGods.Application.Presentation { public static class ArenaPresentationMapping { public static IPresentationEvent ToEvent(IArenaDomainEvent domainEvent) { //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_0023: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown MechanismGroupActivated val = (MechanismGroupActivated)(object)((domainEvent is MechanismGroupActivated) ? domainEvent : null); if (val == null) { if (!(domainEvent is ArenaExitUnlocked)) { if (domainEvent == null) { throw new ArgumentNullException("domainEvent"); } throw new ArgumentOutOfRangeException("domainEvent", ((object)domainEvent).GetType().Name, "No presentation mapping for this arena domain event."); } return (IPresentationEvent)new ExitOpened(); } return (IPresentationEvent)new MechanismGroupEngaged(val.Group); } } public static class BossPresentationMapping { public static PresentationState ToState(BossSimulation boss) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_005b: 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_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) //IL_0083: Expected O, but got Unknown if (boss == null) { throw new ArgumentNullException("boss"); } float num = ((boss.MaxHealth > 0) ? Math.Max(0f, Math.Min(1f, (float)boss.Health / (float)boss.MaxHealth)) : 0f); return new PresentationState(boss.Id, boss.Position, boss.PositionHeight, boss.Facing, ToPhaseVisualId(boss.Phase), ToVisualActivity(boss.Activity), boss.IsWeakPointExposed, boss.IsEnraged, num); } public static IPresentationEvent ToEvent(IBossDomainEvent domainEvent) { //IL_009a: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00bd: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_00e6: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Expected O, but got Unknown //IL_010a: 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_011c: Expected O, but got Unknown //IL_011e: 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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Expected O, but got Unknown //IL_0137: 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_0150: Expected O, but got Unknown //IL_0152: 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) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown BossSpawned val = (BossSpawned)(object)((domainEvent is BossSpawned) ? domainEvent : null); if (val == null) { BossBegan val2 = (BossBegan)(object)((domainEvent is BossBegan) ? domainEvent : null); if (val2 == null) { AttackTelegraphed val3 = (AttackTelegraphed)(object)((domainEvent is AttackTelegraphed) ? domainEvent : null); if (val3 == null) { AttackCommitted val4 = (AttackCommitted)(object)((domainEvent is AttackCommitted) ? domainEvent : null); if (val4 == null) { WeakPointExposed val5 = (WeakPointExposed)(object)((domainEvent is WeakPointExposed) ? domainEvent : null); if (val5 == null) { BossPhaseChanged val6 = (BossPhaseChanged)(object)((domainEvent is BossPhaseChanged) ? domainEvent : null); if (val6 == null) { BossDamaged val7 = (BossDamaged)(object)((domainEvent is BossDamaged) ? domainEvent : null); if (val7 == null) { BossRelocated val8 = (BossRelocated)(object)((domainEvent is BossRelocated) ? domainEvent : null); if (val8 == null) { BossEnraged val9 = (BossEnraged)(object)((domainEvent is BossEnraged) ? domainEvent : null); if (val9 == null) { BossDied val10 = (BossDied)(object)((domainEvent is BossDied) ? domainEvent : null); if (val10 == null) { if (domainEvent == null) { throw new ArgumentNullException("domainEvent"); } throw new ArgumentOutOfRangeException("domainEvent", ((object)domainEvent).GetType().Name, "No presentation mapping is defined for this boss domain event."); } return (IPresentationEvent)new BossDefeated(val10.Boss); } return (IPresentationEvent)new RageChanged(val9.Boss, val9.Enraged); } return (IPresentationEvent)new BossMoved(val8.Boss, val8.Position, val8.Height); } return (IPresentationEvent)new BossHit(val7.Boss, val7.Amount, val7.WeakPointHit); } return (IPresentationEvent)new PhaseTransition(val6.Boss, ToPhaseVisualId(val6.Phase)); } return (IPresentationEvent)new WeakPointVisibilityChanged(val5.Boss, val5.Exposed); } return (IPresentationEvent)new AttackLanded(val4.Boss, val4.Attack, ToVisualKind(val4.Kind), val4.AimPoint); } return (IPresentationEvent)new AttackTelegraphStarted(val3.Boss, val3.Attack, ToVisualKind(val3.Kind), val3.AimPoint, val3.TelegraphSeconds); } return (IPresentationEvent)new BossRoared(val2.Boss); } return (IPresentationEvent)new BossAppeared(val.Boss, ToPhaseVisualId(val.Phase)); } private static int ToPhaseVisualId(BossPhase phase) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Expected I4, but got Unknown return (int)phase; } private static BossVisualActivity ToVisualActivity(BossActivity activity) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected I4, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) return (BossVisualActivity)((int)activity switch { 0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, _ => throw new ArgumentOutOfRangeException("activity", activity, "Unknown boss activity."), }); } private static AttackVisualKind ToVisualKind(BossAttackKind kind) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) if ((int)kind != 1) { if ((int)kind == 2) { return (AttackVisualKind)2; } throw new ArgumentOutOfRangeException("kind", kind, "Unknown boss attack kind."); } return (AttackVisualKind)1; } } public sealed class BossPresenter { private readonly IEncounterPresentation _presentation; public BossPresenter(IEncounterPresentation presentation) { _presentation = presentation ?? throw new ArgumentNullException("presentation"); } public void Present(BossSimulation boss, IReadOnlyList<IBossDomainEvent> domainEvents) { if (boss == null) { throw new ArgumentNullException("boss"); } if (domainEvents == null) { throw new ArgumentNullException("domainEvents"); } for (int i = 0; i < domainEvents.Count; i++) { _presentation.Handle(BossPresentationMapping.ToEvent(domainEvents[i])); } _presentation.Apply(BossPresentationMapping.ToState(boss)); } } public sealed class FalseGodTitle { private const string SpacedInterpunct = " · "; private const string ChineseInterpunct = "·"; private const string JapaneseInterpunct = "・"; private static readonly FalseGodTitle Fallback = new FalseGodTitle("False God", " · "); private static readonly Dictionary<string, FalseGodTitle> ByLanguageCode = new Dictionary<string, FalseGodTitle>(StringComparer.OrdinalIgnoreCase) { ["en"] = Fallback, ["sv"] = new FalseGodTitle("Falsk gud", " · "), ["fr"] = new FalseGodTitle("Faux Dieu", " · "), ["it"] = new FalseGodTitle("Falso Dio", " · "), ["de"] = new FalseGodTitle("Falscher Gott", " · "), ["es"] = new FalseGodTitle("Falso Dios", " · "), ["pt"] = new FalseGodTitle("Falso Deus", " · "), ["ru"] = new FalseGodTitle("Лжебог", " · "), ["pl"] = new FalseGodTitle("Fałszywy Bóg", " · "), ["ja"] = new FalseGodTitle("偽神", "・"), ["ko"] = new FalseGodTitle("거짓 신", " · "), ["zh-CN"] = new FalseGodTitle("伪神", "·"), ["tr"] = new FalseGodTitle("Sahte Tanrı", " · "), ["ar"] = new FalseGodTitle("إله زائف", " · ") }; public string Word { get; } public string Joiner { get; } private FalseGodTitle(string word, string joiner) { Word = word; Joiner = joiner; } public static FalseGodTitle For(string? languageCode) { if (string.IsNullOrEmpty(languageCode)) { return Fallback; } if (ByLanguageCode.TryGetValue(languageCode, out FalseGodTitle value)) { return value; } string text = LanguageOf(languageCode); if (ByLanguageCode.TryGetValue(text, out FalseGodTitle value2)) { return value2; } foreach (KeyValuePair<string, FalseGodTitle> item in ByLanguageCode) { if (string.Equals(LanguageOf(item.Key), text, StringComparison.OrdinalIgnoreCase)) { return item.Value; } } return Fallback; } private static string LanguageOf(string languageCode) { int num = languageCode.IndexOf('-'); if (num <= 0) { return languageCode; } return languageCode.Substring(0, num); } public static string Compose(string word, string joiner, string? creatureName, bool rightToLeft) { if (string.IsNullOrEmpty(creatureName)) { return word; } if (!rightToLeft) { return word + joiner + creatureName; } return creatureName + joiner + word; } public string Compose(string? creatureName, bool rightToLeft = false) { return Compose(Word, Joiner, creatureName, rightToLeft); } } public interface IArenaAtmospherePort : IDisposable { void Warm(); void SetRoomDepth(float startDistance, float endDistance, float afterSeconds = 0f, float overSeconds = 0f); void StartBattleMusic(); void StopBattleMusic(); } public static class ArenaDepth { public const float OpeningStart = 4f; public const float OpeningEnd = 10f; public const float FightStart = 10f; public const float FightEnd = 72f; public const float RevealHoldSeconds = 1f; public const float RevealSeconds = 3f; } public interface IBossVoicePort { void Roar(ArenaWorldPoint at); void Warm(); } public static class WirePresentationMapping { public static PresentationState ToState(BossSnapshot snapshot) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0066: 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) //IL_007e: Expected O, but got Unknown if (snapshot == null) { throw new ArgumentNullException("snapshot"); } float num = ((snapshot.MaxHealth > 0) ? Math.Max(0f, Math.Min(1f, (float)snapshot.Health / (float)snapshot.MaxHealth)) : 0f); return new PresentationState(snapshot.Boss, snapshot.Position, snapshot.PositionHeight, snapshot.Facing, snapshot.PhaseId, ToVisualActivity(snapshot.StateId), snapshot.WeakPointExposed, snapshot.Enraged, num); } public static IPresentationEvent ToEvent(BossInstanceId boss, IBossWireEvent wireEvent) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_009e: 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_00a5: Expected O, but got Unknown //IL_00a5: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00c9: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_00e7: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_00f4: 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_0102: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown //IL_012c: 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_013a: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown BossAppearedEvent val = (BossAppearedEvent)(object)((wireEvent is BossAppearedEvent) ? wireEvent : null); if (val == null) { if (!(wireEvent is BossBeganEvent)) { BossAttackTelegraphedEvent val2 = (BossAttackTelegraphedEvent)(object)((wireEvent is BossAttackTelegraphedEvent) ? wireEvent : null); if (val2 == null) { BossAttackCommittedEvent val3 = (BossAttackCommittedEvent)(object)((wireEvent is BossAttackCommittedEvent) ? wireEvent : null); if (val3 == null) { BossPhaseChangedEvent val4 = (BossPhaseChangedEvent)(object)((wireEvent is BossPhaseChangedEvent) ? wireEvent : null); if (val4 == null) { BossWeakPointChangedEvent val5 = (BossWeakPointChangedEvent)(object)((wireEvent is BossWeakPointChangedEvent) ? wireEvent : null); if (val5 == null) { BossDamagedEvent val6 = (BossDamagedEvent)(object)((wireEvent is BossDamagedEvent) ? wireEvent : null); if (val6 == null) { BossRelocatedEvent val7 = (BossRelocatedEvent)(object)((wireEvent is BossRelocatedEvent) ? wireEvent : null); if (val7 == null) { BossEnragedEvent val8 = (BossEnragedEvent)(object)((wireEvent is BossEnragedEvent) ? wireEvent : null); if (val8 == null) { if (!(wireEvent is BossDefeatedEvent)) { if (wireEvent == null) { throw new ArgumentNullException("wireEvent"); } throw new ArgumentOutOfRangeException("wireEvent", ((object)wireEvent).GetType().Name, "No presentation mapping for this boss wire event."); } return (IPresentationEvent)new BossDefeated(boss); } return (IPresentationEvent)new RageChanged(boss, val8.Enraged); } return (IPresentationEvent)new BossMoved(boss, val7.Position, val7.Height); } return (IPresentationEvent)new BossHit(boss, val6.Amount, val6.WeakPointHit); } return (IPresentationEvent)new WeakPointVisibilityChanged(boss, val5.Exposed); } return (IPresentationEvent)new PhaseTransition(boss, val4.PhaseId); } return (IPresentationEvent)new AttackLanded(boss, val3.Attack, ToVisualKind(val3.AttackDefinitionId), val3.AimPoint); } return (IPresentationEvent)new AttackTelegraphStarted(boss, val2.Attack, ToVisualKind(val2.AttackDefinitionId), val2.AimPoint, val2.TelegraphSeconds); } return (IPresentationEvent)new BossRoared(boss); } return (IPresentationEvent)new BossAppeared(boss, val.PhaseId); } public static IPresentationEvent ToEvent(IArenaWireEvent wireEvent) { //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_0023: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown ArenaMechanismGroupActivatedEvent val = (ArenaMechanismGroupActivatedEvent)(object)((wireEvent is ArenaMechanismGroupActivatedEvent) ? wireEvent : null); if (val == null) { if (!(wireEvent is ArenaExitUnlockedEvent)) { if (wireEvent == null) { throw new ArgumentNullException("wireEvent"); } throw new ArgumentOutOfRangeException("wireEvent", ((object)wireEvent).GetType().Name, "No presentation mapping for this arena wire event."); } return (IPresentationEvent)new ExitOpened(); } return (IPresentationEvent)new MechanismGroupEngaged(val.Group); } public static IReadOnlyList<IPresentationEvent> ToEvents(ArenaSnapshot snapshot) { //IL_002d: 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_003c: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown if (snapshot == null) { throw new ArgumentNullException("snapshot"); } List<IPresentationEvent> list = new List<IPresentationEvent>(snapshot.ActiveMechanismGroups.Count + 1); for (int i = 0; i < snapshot.ActiveMechanismGroups.Count; i++) { list.Add((IPresentationEvent)new MechanismGroupEngaged(snapshot.ActiveMechanismGroups[i])); } if (snapshot.ExitUnlocked) { list.Add((IPresentationEvent)new ExitOpened()); } return list; } private static BossVisualActivity ToVisualActivity(int stateId) { return (BossVisualActivity)(stateId switch { 0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, _ => throw new ArgumentOutOfRangeException("stateId", stateId, "Unknown wire boss state id."), }); } private static AttackVisualKind ToVisualKind(int attackDefinitionId) { return (AttackVisualKind)(attackDefinitionId switch { 1 => 1, 2 => 2, _ => throw new ArgumentOutOfRangeException("attackDefinitionId", attackDefinitionId, "Unknown wire attack definition id."), }); } } } namespace FalseGods.Application.Combat { public sealed class ClientHitReporter { private readonly IEncounterChannel _channel; private readonly IMultiplayerSession _session; private readonly ILogger? _logger; private int _sequence; private EncounterId _announced; public ClientHitReporter(IEncounterChannel channel, IMultiplayerSession session, ILogger? logger = null) { _channel = channel ?? throw new ArgumentNullException("channel"); _session = session ?? throw new ArgumentNullException("session"); _logger = logger; } public void ReportHit(EncounterId encounter, float damageCandidate, WorldPosition? attackerPosition = null) { //IL_000e: 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_0028: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (!_session.IsActive) { return; } ClientHitRequest message = new ClientHitRequest(encounter, ++_sequence, damageCandidate, attackerPosition); _channel.Send(EncounterCodec.Encode(message), (MessageDelivery)0, MessageTarget.Host); if (_announced != encounter) { _announced = encounter; ILogger? logger = _logger; if (logger != null) { logger.Log($"Reporting weapon hits to the host for {encounter}; the first is on its way."); } } } } public sealed class CrateCommandFlow : IDisposable { public const int MaxVolleyCount = 64; public const float MaxFireIntervalSeconds = 5f; public const int MaxLoad = 64; public const float MaxPickUpReach = 50f; public const int MaxVolleyTargets = 32; private readonly IEncounterChannel _channel; private readonly IMultiplayerSession _session; public Action<ArenaWorldPoint, CratePileId, bool>? OnDropped { get; set; } public Action<ArenaWorldPoint, ArenaWorldPoint, float, float>? OnThrown { get; set; } public Action<CratePileId, IReadOnlyList<CrateVolleyAim>, CrateVolleyShape>? OnVolleyFired { get; set; } public Action<ArenaWorldPoint, CratePileId, int, float>? OnTaken { get; set; } public Action<ArenaWorldPoint, ArenaWorldPoint, CratePileId, int, int, int>? OnSetDown { get; set; } public Action<int, CrateDeath>? OnDestroyed { get; set; } public Action<int, CrateDeath>? OnDestroyRequested { get; set; } private bool IsHosting { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 if (_session.IsActive) { return (int)_session.Role == 0; } return false; } } public CrateCommandFlow(IEncounterChannel channel, IMultiplayerSession session) { _channel = channel ?? throw new ArgumentNullException("channel"); _session = session ?? throw new ArgumentNullException("session"); _channel.Received += OnReceived; } public void Dispose() { _channel.Received -= OnReceived; } public void BroadcastDropped(ArenaWorldPoint at, CratePileId pile, bool explosive) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected I4, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (IsHosting) { Broadcast(EncounterCodec.Encode(new CrateDropped(ToWire(at), (int)((CratePileId)(ref pile)).Kind, ((CratePileId)(ref pile)).Index, explosive))); } } public void BroadcastThrown(ArenaWorldPoint from, ArenaWorldPoint to, float flightSeconds, float apexHeight) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (IsHosting) { Broadcast(EncounterCodec.Encode(new CrateThrown(ToWire(from), ToWire(to), flightSeconds, apexHeight))); } } public void BroadcastVolley(CratePileId pile, IReadOnlyList<CrateVolleyAim> aims, CrateVolleyShape shape) { //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_0038: 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_004c: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected I4, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if (IsHosting) { List<CrateVolleyTarget> list = new List<CrateVolleyTarget>(aims.Count); for (int i = 0; i < aims.Count; i++) { list.Add(new CrateVolleyTarget(ToWire(aims[i].Current), ToWire(aims[i].Lead))); } Broadcast(EncounterCodec.Encode(new CrateVolleyFired((IReadOnlyList<CrateVolleyTarget>)list, (int)((CratePileId)(ref pile)).Kind, ((CratePileId)(ref pile)).Index, shape.Seed, shape.Count, shape.SpreadMinRadius, shape.SpreadMaxRadius, shape.LiftHeight, shape.LiftSeconds, shape.HoldSeconds, shape.FlightSeconds, shape.ApexHeight, shape.LeadShare, shape.FireIntervalSeconds))); } } public void BroadcastTaken(ArenaWorldPoint at, CratePileId pile, int count, float radius) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected I4, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (IsHosting) { Broadcast(EncounterCodec.Encode(new CratesTaken(ToWire(at), (int)((CratePileId)(ref pile)).Kind, ((CratePileId)(ref pile)).Index, count, radius))); } } public void BroadcastSetDown(ArenaWorldPoint from, ArenaWorldPoint at, CratePileId pile, int count, int seed, int explosives) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected I4, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (IsHosting) { Broadcast(EncounterCodec.Encode(new CratesSetDown(ToWire(from), ToWire(at), (int)((CratePileId)(ref pile)).Kind, ((CratePileId)(ref pile)).Index, count, seed, explosives))); } } public void ReportDestroyed(int crateId, CrateDeath death) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (IsHosting) { BroadcastDestroyed(crateId, death); } else { RequestDestroy(crateId, death); } } public void BroadcastDestroyed(int crateId, CrateDeath death) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected I4, but got Unknown //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (IsHosting) { Broadcast(EncounterCodec.Encode(new CrateDestroyed(crateId, (int)death))); } } public void RequestDestroy(int crateId, CrateDeath death) { //IL_0013: 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_0028: Expected I4, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0028: 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) if (_session.IsActive && (int)_session.Role != 0) { _channel.Send(EncounterCodec.Encode(new CrateDestroyRequested(crateId, (int)death)), (MessageDelivery)0, MessageTarget.Host); } } private void Broadcast(EncodedPayload payload) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) _channel.Send(payload, (MessageDelivery)0, MessageTarget.AllClients); } private void OnReceived(SessionPeerId sender, EncodedPayload payload) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_002e: 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_013b: Unknown result type (might be due to invalid IL or missing references) //IL_014c: 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_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) DecodedMessage decodedMessage; try { decodedMessage = EncounterCodec.Decode(payload); } catch (Exception) { return; } object value = decodedMessage.Value; CrateDestroyRequested val = (CrateDestroyRequested)((value is CrateDestroyRequested) ? value : null); if (val != null) { if (IsHosting && sender != _session.HostPeer && IsKnownDeath(val.Death)) { OnDestroyRequested?.Invoke(val.CrateId, (CrateDeath)val.Death); } } else { if (sender != _session.HostPeer || IsHosting) { return; } object value2 = decodedMessage.Value; CrateDropped val2 = (CrateDropped)((value2 is CrateDropped) ? value2 : null); if (val2 == null) { CrateThrown val3 = (CrateThrown)((value2 is CrateThrown) ? value2 : null); if (val3 == null) { CratesTaken val4 = (CratesTaken)((value2 is CratesTaken) ? value2 : null); if (val4 == null) { CrateDestroyed val5 = (CrateDestroyed)((value2 is CrateDestroyed) ? value2 : null); if (val5 == null) { CratesSetDown val6 = (CratesSetDown)((value2 is CratesSetDown) ? value2 : null); if (val6 == null) { CrateVolleyFired val7 = (CrateVolleyFired)((value2 is CrateVolleyFired) ? value2 : null); if (val7 != null) { CrateVolleyFired val8 = val7; CratePileId arg = default(CratePileId); if (IsSaneVolley(val8) && CratePileId.TryFrom(val8.PileKind, val8.PileIndex, ref arg)) { OnVolleyFired?.Invoke(arg, ToAims(val8.Targets), new CrateVolleyShape(val8.Seed, val8.Count, val8.SpreadMinRadius, val8.SpreadMaxRadius, val8.LiftHeight, val8.LiftSeconds, val8.HoldSeconds, val8.FlightSeconds, val8.ApexHeight, val8.LeadShare, val8.FireIntervalSeconds)); } } } else { CratesSetDown val9 = val6; CratePileId arg2 = default(CratePileId); if (IsFinite(val9.From) && IsFinite(val9.At) && val9.Count > 0 && val9.Count <= 64 && val9.Explosives >= 0 && val9.Explosives <= val9.Count && CratePileId.TryFrom(val9.PileKind, val9.PileIndex, ref arg2)) { OnSetDown?.Invoke(FromWire(val9.From), FromWire(val9.At), arg2, val9.Count, val9.Seed, val9.Explosives); } } } else { CrateDestroyed val10 = val5; if (IsKnownDeath(val10.Death)) { OnDestroyed?.Invoke(val10.CrateId, (CrateDeath)val10.Death); } } } else { CratesTaken val11 = val4; CratePileId arg3 = default(CratePileId); if (IsFinite(val11.At) && val11.Count > 0 && val11.Count <= 64 && IsPositive(val11.Radius) && val11.Radius <= 50f && CratePileId.TryFrom(val11.PileKind, val11.PileIndex, ref arg3)) { OnTaken?.Invoke(FromWire(val11.At), arg3, val11.Count, val11.Radius); } } } else { CrateThrown val12 = val3; if (IsFinite(val12.From) && IsFinite(val12.To) && IsPositive(val12.FlightSeconds) && IsFinite(val12.ApexHeight)) { OnThrown?.Invoke(FromWire(val12.From), FromWire(val12.To), val12.FlightSeconds, val12.ApexHeight); } } } else { CrateDropped val13 = val2; CratePileId arg4 = default(CratePileId); if (IsFinite(val13.At) && CratePileId.TryFrom(val13.PileKind, val13.PileIndex, ref arg4)) { OnDropped?.Invoke(FromWire(val13.At), arg4, val13.Explosive); } } } } private static IReadOnlyList<CrateVolleyAim> ToAims(IReadOnlyList<CrateVolleyTarget> targets) { //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_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) List<CrateVolleyAim> list = new List<CrateVolleyAim>(targets.Count); for (int i = 0; i < targets.Count; i++) { list.Add(new CrateVolleyAim(FromWire(targets[i].Current), FromWire(targets[i].Lead))); } return list; } private static bool IsSaneVolley(CrateVolleyFired v) { if (HasSaneTargets(v.Targets) && v.Count > 0 && v.Count <= 64 && IsFinite(v.SpreadMinRadius) && IsFinite(v.SpreadMaxRadius) && v.SpreadMinRadius >= 0f && v.SpreadMaxRadius >= v.SpreadMinRadius && IsFinite(v.LiftHeight) && IsPositive(v.LiftSeconds) && IsFinite(v.HoldSeconds) && v.HoldSeconds >= 0f && IsPositive(v.FlightSeconds) && IsFinite(v.ApexHeight) && IsFinite(v.LeadShare) && v.LeadShare >= 0f && v.LeadShare <= 1f && IsFinite(v.FireIntervalSeconds) && v.FireIntervalSeconds >= 0f) { return v.FireIntervalSeconds <= 5f; } return false; } private static bool HasSaneTargets(IReadOnlyList<CrateVolleyTarget> targets) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (targets == null || targets.Count == 0 || targets.Count > 32) { return false; } for (int i = 0; i < targets.Count; i++) { if (!IsFinite(targets[i].Current) || !IsFinite(targets[i].Lead)) { return false; } } return true; } private static bool IsKnownDeath(int death) { if (death != 0) { return death == 1; } return true; } private static bool IsPositive(float value) { if (IsFinite(value)) { return value > 0f; } return false; } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private static bool IsFinite(WorldPosition p) { if (IsFinite(((WorldPosition)(ref p)).X) && IsFinite(((WorldPosition)(ref p)).Y)) { return IsFinite(((WorldPosition)(ref p)).Z); } return false; } private static WorldPosition ToWire(ArenaWorldPoint p) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) return new WorldPosition(((ArenaWorldPoint)(ref p)).X, ((ArenaWorldPoint)(ref p)).Y, ((ArenaWorldPoint)(ref p)).Z); } private static ArenaWorldPoint FromWire(WorldPosition p) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) return new ArenaWorldPoint(((WorldPosition)(ref p)).X, ((WorldPosition)(ref p)).Y, ((WorldPosition)(ref p)).Z); } } public readonly struct CrateVolleyAim { public ArenaWorldPoint Current { get; } public ArenaWorldPoint Lead { get; } public CrateVolleyAim(ArenaWorldPoint current, ArenaWorldPoint lead) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Current = current; Lead = lead; } } public readonly struct CrateVolleyShape { public int Seed { get; } public int Count { get; } public float SpreadMinRadius { get; } public float SpreadMaxRadius { get; } public float LiftHeight { get; } public float LiftSeconds { get; } public float HoldSeconds { get; } public float FlightSeconds { get; } public float ApexHeight { get; } public float LeadShare { get; } public float FireIntervalSeconds { get; } public CrateVolleyShape(int seed, int count, float spreadMinRadius, float spreadMaxRadius, float liftHeight, float liftSeconds, float holdSeconds, float flightSeconds, float apexHeight, float leadShare, float fireIntervalSeconds = 0f) { Seed = seed; Count = count; SpreadMinRadius = spreadMinRadius; SpreadMaxRadius = spreadMaxRadius; LiftHeight = liftHeight; LiftSeconds = liftSeconds; HoldSeconds = holdSeconds; FlightSeconds = flightSeconds; ApexHeight = apexHeight; LeadShare = leadShare; FireIntervalSeconds = fireIntervalSeconds; } } public sealed class HostHitIntake : IDisposable { private readonly IEncounterChannel _channel; private readonly IPlayerRoster _roster; private readonly EncounterId _encounter; private readonly float _maxDamagePerHit; private readonly Action<float> _applyDamage; private readonly Action<string>? _log; public HostHitIntake(IEncounterChannel channel, IPlayerRoster roster, EncounterId encounter, float maxDamagePerHit, Action<float> applyDamage, Action<string>? log = null) { //IL_004a: 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) _channel = channel ?? throw new ArgumentNullException("channel"); _roster = roster ?? throw new ArgumentNullException("roster"); _applyDamage = applyDamage ?? throw new ArgumentNullException("applyDamage"); _encounter = encounter; _maxDamagePerHit = maxDamagePerHit; _log = log; _channel.Received += OnReceived; } public void Dispose() { _channel.Received -= OnReceived; } private void OnReceived(SessionPeerId sender, EncodedPayload payload) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_00a6: Unknown result type (might be due to invalid IL or missing references) DecodedMessage decodedMessage; try { decodedMessage = EncounterCodec.Decode(payload); } catch (Exception) { return; } object value = decodedMessage.Value; ClientHitRequest val = (ClientHitRequest)((value is ClientHitRequest) ? value : null); if (val == null || val.Encounter != _encounter) { return; } if (!IsMember(sender)) { _log?.Invoke($"Dropped a hit request from non-member {sender} for {_encounter}."); return; } float damageCandidate = val.DamageCandidate; if (!float.IsNaN(damageCandidate) && !float.IsInfinity(damageCandidate) && !(damageCandidate <= 0f)) { float num = Math.Min(damageCandidate, _maxDamagePerHit); _log?.Invoke($"Client {sender} hit seq={val.RequestSequence}: candidate {damageCandidate:0.##} " + $"-> applying {num:0.##} (host clamps; the simulation decides the result)."); _applyDamage(num); } } private bool IsMember(SessionPeerId sender) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<SessionPeerId> members = _roster.Members; for (int i = 0; i < members.Count; i++) { if (members[i] == sender) { return true; } } return false; } } public interface IBattlefieldCleanupPort { int SweepCorpses(ArenaWorldPoint around, float radius); } public static class BattlefieldSweep { public const float ArenaReach = 120f; } public readonly record struct ArmPlacement(ArenaWorldPoint BossAt, SimVector2 BossFacing, float SideDistance, float ForwardOffset, float Lift, float Scale); public interface IBossArmPort { int Raised { get; } void Raise(int count, ArmPlacement placement); void Follow(ArmPlacement placement); void LowerAll(); void Adopt(int count); void Release(); } public static class RageArms { public const int Count = 2; public const float SideDistance = 3.1f; public const float ForwardOffset = 1f; public const float Lift = 1.5f; public const float Scale = 1.5f; } public interface IBossDamageSink { void ApplyWeaponDamage(float amount); } public interface IBossPresencePort { void Declare(); void Withdraw(); void ShowHealthBar(); void ReportHealth(float fraction); void HideHealthBar(); } public interface IBossRewardPort { void DropReward(ArenaWorldPoint at); } public interface ICarrierPort { int Working { get; } int Carried { get; } float ObservedWalkSpeed { get; } void Warm(ArenaWorldPoint at); void Advance(float deltaSeconds, int wanted, int loadPerCarrier, float replaceAfterSeconds, IReadOnlyList<ArenaWorldPoint> sources, ArenaWorldPoint deliverTo, CratePileId deliverPile); void DismissAll(); void Disband(); } public interface IDamagePort { void ApplyDamage(ParticipantId target, int amount); } public interface IMinionSpawnPort { int Alive { get; } int SizeOf(MinionBandId band); void Summon(MinionBandId band, IReadOnlyList<ArenaWorldPoint> places); void DespawnAll(); } public readonly struct PlayerAim { public int Index { get; } public SimVector2 Position { get; } public float Height { get; } public SimVector2 Velocity { get; } public bool VelocityKnown { get; } public PlayerAim(int index, SimVector2 position, float height, SimVector2 velocity, bool velocityKnown) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_0018: Unknown result type (might be due to invalid IL or missing references) Index = index; Position = position; Height = height; Velocity = velocity; VelocityKnown = velocityKnown; } } public readonly struct PlayerMotion { public SimVector2 Position { get; } public SimVector2 Velocity { get; } public bool Known { get; } public PlayerMotion(SimVector2 position, SimVector2 velocity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Position = position; Velocity = velocity; Known = true; } } public interface IPlayerMotionPort { PlayerMotion TryReadLocalPlayer(); void ReadPlayersToThrowAt(IList<PlayerAim> into); } public interface IThrownCrateImpact { bool Contact(ArenaWorldPoint at); bool Splash(ArenaWorldPoint at); } public interface IThrownCratePort { Action<int, CrateDeath>? Died { get; set; } int InFlight { get; } int Resting { get; } bool Prepare(); bool Throw(ArenaWorldPoint from, ArenaWorldPoint to, float flightSeconds, float apexHeight); bool ThrowExplosive(ArenaWorldPoint from, ArenaWorldPoint to, float flightSeconds, float apexHeight, Action whenItGoesOff); bool Drop(ArenaWorldPoint at, CratePileId pile, bool explosive = false); void Clear(); int LaunchVolley(CratePileId pile, IReadOnlyList<CrateVolleyAim> aims, CrateVolleyShape shape); int TossRing(ArenaWorldPoint from, ArenaWorldPoint at, CratePileId pile, int count, int seed, int explosives); int RestingOn(CratePileId pile); int TakeFrom(CratePileId pile, int count, ArenaWorldPoint near, float radius); bool TryFindNearestResting(CratePileId pile, ArenaWorldPoint near, out ArenaWorldPoint at, IReadOnlyList<ArenaWorldPoint> spokenFor = null, float keepApart = 0f); bool Destroy(int crateId, CrateDeath death); void Advance(float deltaSeconds); void Release(); } public static class WeaponDamage { public static int ToSimAmount(float amount) { if (float.IsNaN(amount) || float.IsInfinity(amount) || amount <= 0f) { return 0; } if (amo
FalseGods.Core.dll
Decompiled 9 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using FalseGods.Core.Arena; using FalseGods.Core.Arena.Events; using FalseGods.Core.Bosses; using FalseGods.Core.Bosses.Combat; using FalseGods.Core.Bosses.Events; using FalseGods.Core.Simulation; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FalseGods.Core")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6e5740a80f810ab422551028733810b527fb614d")] [assembly: AssemblyProduct("FalseGods.Core")] [assembly: AssemblyTitle("FalseGods.Core")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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; } } internal static class IsExternalInit { } } namespace FalseGods.Core.Simulation { public readonly struct DefinitionId : IEquatable<DefinitionId> { private readonly int _value; public int Value => _value; public DefinitionId(int value) { _value = value; } public bool Equals(DefinitionId other) { return _value == other._value; } public override bool Equals(object? obj) { if (obj is DefinitionId other) { return Equals(other); } return false; } public override int GetHashCode() { return _value; } public override string ToString() { return $"definition:{_value}"; } public static bool operator ==(DefinitionId left, DefinitionId right) { return left.Equals(right); } public static bool operator !=(DefinitionId left, DefinitionId right) { return !left.Equals(right); } } public readonly struct EncounterId : IEquatable<EncounterId> { private readonly int _value; public int Value => _value; public EncounterId(int value) { _value = value; } public bool Equals(EncounterId other) { return _value == other._value; } public override bool Equals(object? obj) { if (obj is EncounterId other) { return Equals(other); } return false; } public override int GetHashCode() { return _value; } public override string ToString() { return $"encounter:{_value}"; } public static bool operator ==(EncounterId left, EncounterId right) { return left.Equals(right); } public static bool operator !=(EncounterId left, EncounterId right) { return !left.Equals(right); } } public interface IAuthoritativeRandom { int NextInt(int minInclusive, int maxExclusive); float NextFloat(); } public interface IEncounterParticipantQuery { IReadOnlyList<ParticipantId> Participants { get; } bool TryGetPosition(ParticipantId participant, out SimVector2 position); } public interface ISimulationClock { long Tick { get; } float Time { get; } } public readonly struct ParticipantId : IEquatable<ParticipantId> { private readonly int _value; public int Value => _value; public ParticipantId(int value) { _value = value; } public bool Equals(ParticipantId other) { return _value == other._value; } public override bool Equals(object? obj) { if (obj is ParticipantId other) { return Equals(other); } return false; } public override int GetHashCode() { return _value; } public override string ToString() { return $"participant:{_value}"; } public static bool operator ==(ParticipantId left, ParticipantId right) { return left.Equals(right); } public static bool operator !=(ParticipantId left, ParticipantId right) { return !left.Equals(right); } } public readonly struct SimVector2 : IEquatable<SimVector2> { public float X { get; } public float Z { get; } public static SimVector2 Zero => new SimVector2(0f, 0f); public SimVector2(float x, float z) { X = x; Z = z; } public float DistanceTo(SimVector2 other) { float num = other.X - X; float num2 = other.Z - Z; return (float)Math.Sqrt(num * num + num2 * num2); } public SimVector2 MoveToward(SimVector2 target, float maxDistance) { if (maxDistance <= 0f) { return this; } float num = target.X - X; float num2 = target.Z - Z; float num3 = (float)Math.Sqrt(num * num + num2 * num2); if (num3 <= maxDistance || num3 <= 0f) { return target; } float num4 = maxDistance / num3; return new SimVector2(X + num * num4, Z + num2 * num4); } public SimVector2 DirectionTo(SimVector2 target) { float num = target.X - X; float num2 = target.Z - Z; float num3 = (float)Math.Sqrt(num * num + num2 * num2); if (num3 <= 0f) { return Zero; } return new SimVector2(num / num3, num2 / num3); } public bool Equals(SimVector2 other) { if (X.Equals(other.X)) { return Z.Equals(other.Z); } return false; } public override bool Equals(object? obj) { if (obj is SimVector2 other) { return Equals(other); } return false; } public override int GetHashCode() { return (X.GetHashCode() * 397) ^ Z.GetHashCode(); } public override string ToString() { return $"({X}, {Z})"; } public static bool operator ==(SimVector2 left, SimVector2 right) { return left.Equals(right); } public static bool operator !=(SimVector2 left, SimVector2 right) { return !left.Equals(right); } } } namespace FalseGods.Core.Encounters { public sealed class EncounterCoordinator { private readonly ArenaSimulation _arena; private readonly MechanismGroupId _phaseTwoGroup; public EncounterId Id { get; } public EncounterPhase Phase { get; private set; } public EncounterCoordinator(EncounterId id, ArenaSimulation arena, MechanismGroupId phaseTwoGroup) { Id = id; _arena = arena ?? throw new ArgumentNullException("arena"); _phaseTwoGroup = phaseTwoGroup; Phase = EncounterPhase.PreFight; } public void Begin() { if (Phase == EncounterPhase.PreFight) { Phase = EncounterPhase.Fighting; } } public void BeginExit() { Phase = EncounterPhase.Exiting; } public void Process(IReadOnlyList<IBossDomainEvent> bossEvents) { if (bossEvents == null) { throw new ArgumentNullException("bossEvents"); } for (int i = 0; i < bossEvents.Count; i++) { IBossDomainEvent bossDomainEvent = bossEvents[i]; if (!(bossDomainEvent is BossPhaseChanged bossPhaseChanged)) { if (bossDomainEvent is BossDied) { Phase = EncounterPhase.Defeated; } } else if (bossPhaseChanged.Phase == BossPhase.Two) { _arena.ActivateMechanismGroup(_phaseTwoGroup); } } } } public enum EncounterPhase { PreFight, Fighting, Defeated, Exiting } } namespace FalseGods.Core.Bosses { public readonly struct AttackInstanceId : IEquatable<AttackInstanceId> { private readonly long _value; public long Value => _value; public AttackInstanceId(long value) { _value = value; } public AttackInstanceId Next() { return new AttackInstanceId(_value + 1); } public bool Equals(AttackInstanceId other) { return _value == other._value; } public override bool Equals(object? obj) { if (obj is AttackInstanceId other) { return Equals(other); } return false; } public override int GetHashCode() { long value = _value; return value.GetHashCode(); } public override string ToString() { return $"attack:{_value}"; } public static bool operator ==(AttackInstanceId left, AttackInstanceId right) { return left.Equals(right); } public static bool operator !=(AttackInstanceId left, AttackInstanceId right) { return !left.Equals(right); } } public enum BossActivity { Idle, Telegraphing, Committing, Recovering, Dead, Vanishing, Hidden, Appearing } public enum BossAttackKind { AimedProjectile = 1, AreaTelegraph } public sealed record BossDefinition { public int MaxHealth { get; } public float PhaseTwoHealthFraction { get; } public float MoveSpeed { get; } public float IdleSeconds { get; } public float TelegraphSeconds { get; } public float CommitSeconds { get; } public float RecoverSeconds { get; } public int WeakPointDamageMultiplier { get; } public int AttackDamage { get; } public float AimedHitRadius { get; } public float AreaHitRadius { get; } public int PhaseTwoHealthThreshold => (int)Math.Floor((float)MaxHealth * PhaseTwoHealthFraction); public IReadOnlyList<BossStation> Stations { get; } public bool HasItinerary => Stations.Count > 0; public float VanishSeconds { get; } public float HiddenSeconds { get; } public float AppearSeconds { get; } public float RelocationSeconds => VanishSeconds + HiddenSeconds + AppearSeconds; public float OpeningSeconds { get; } public bool AttacksOnItsOwn { get; } public float RageDamageMultiplier { get; } public float RageEndsAfterHealthFraction { get; } private const float DefaultVanishSeconds = 0.45f; private const float DefaultHiddenSeconds = 0.6f; private const float DefaultAppearSeconds = 0.6f; public BossDefinition(int maxHealth, float phaseTwoHealthFraction, float moveSpeed, float idleSeconds, float telegraphSeconds, float commitSeconds, float recoverSeconds, int weakPointDamageMultiplier, int attackDamage, float aimedHitRadius, float areaHitRadius, IReadOnlyList<BossStation>? stations = null, float vanishSeconds = 0.45f, float hiddenSeconds = 0.6f, float appearSeconds = 0.6f, float openingSeconds = 0f, bool attacksOnItsOwn = true, float rageDamageMultiplier = 1f, float rageEndsAfterHealthFraction = 0f) { if (maxHealth <= 0) { throw new ArgumentOutOfRangeException("maxHealth", maxHealth, "Max health must be positive."); } if (phaseTwoHealthFraction <= 0f || phaseTwoHealthFraction >= 1f) { throw new ArgumentOutOfRangeException("phaseTwoHealthFraction", phaseTwoHealthFraction, "Phase-two health fraction must be strictly between 0 and 1."); } if (moveSpeed < 0f) { throw new ArgumentOutOfRangeException("moveSpeed", moveSpeed, "Move speed cannot be negative."); } RequireNonNegative(idleSeconds, "idleSeconds"); RequirePositive(telegraphSeconds, "telegraphSeconds"); RequirePositive(commitSeconds, "commitSeconds"); RequirePositive(recoverSeconds, "recoverSeconds"); if (weakPointDamageMultiplier < 1) { throw new ArgumentOutOfRangeException("weakPointDamageMultiplier", weakPointDamageMultiplier, "Weak-point damage multiplier must be at least 1."); } if (attackDamage <= 0) { throw new ArgumentOutOfRangeException("attackDamage", attackDamage, "Attack damage must be positive."); } RequirePositive(aimedHitRadius, "aimedHitRadius"); RequirePositive(areaHitRadius, "areaHitRadius"); RequirePositive(vanishSeconds, "vanishSeconds"); RequirePositive(hiddenSeconds, "hiddenSeconds"); RequirePositive(appearSeconds, "appearSeconds"); RequireNonNegative(openingSeconds, "openingSeconds"); if (rageDamageMultiplier < 1f || float.IsNaN(rageDamageMultiplier)) { throw new ArgumentOutOfRangeException("rageDamageMultiplier", rageDamageMultiplier, "A rage cannot make the boss take less damage than usual; use 1 for no amplification."); } if (rageEndsAfterHealthFraction < 0f || rageEndsAfterHealthFraction >= 1f || float.IsNaN(rageEndsAfterHealthFraction)) { throw new ArgumentOutOfRangeException("rageEndsAfterHealthFraction", rageEndsAfterHealthFraction, "A rage that ends only after the boss's whole health bar is not an end; use a fraction below 1, or 0 for a rage that is never cut short."); } Stations = ValidateItinerary(stations, moveSpeed); VanishSeconds = vanishSeconds; HiddenSeconds = hiddenSeconds; AppearSeconds = appearSeconds; OpeningSeconds = openingSeconds; AttacksOnItsOwn = attacksOnItsOwn; RageDamageMultiplier = rageDamageMultiplier; RageEndsAfterHealthFraction = rageEndsAfterHealthFraction; MaxHealth = maxHealth; PhaseTwoHealthFraction = phaseTwoHealthFraction; MoveSpeed = moveSpeed; IdleSeconds = idleSeconds; TelegraphSeconds = telegraphSeconds; CommitSeconds = commitSeconds; RecoverSeconds = recoverSeconds; WeakPointDamageMultiplier = weakPointDamageMultiplier; AttackDamage = attackDamage; AimedHitRadius = aimedHitRadius; AreaHitRadius = areaHitRadius; } private static IReadOnlyList<BossStation> ValidateItinerary(IReadOnlyList<BossStation>? stations, float moveSpeed) { if (stations == null || stations.Count == 0) { return Array.Empty<BossStation>(); } if (moveSpeed > 0f) { throw new ArgumentOutOfRangeException("moveSpeed", moveSpeed, "A boss with an itinerary stands where its stations put it, so it must not also move: give it a move speed of zero, or no stations."); } if (stations[0].EnterAtHealthFraction < 1f) { throw new ArgumentException("The first station is where the boss starts, so it is entered at full health (fraction 1).", "stations"); } for (int i = 1; i < stations.Count; i++) { if (stations[i].EnterAtHealthFraction >= stations[i - 1].EnterAtHealthFraction) { throw new ArgumentException($"Station {i} is entered at {stations[i].EnterAtHealthFraction:P0} health, which is not " + $"below station {i - 1}'s {stations[i - 1].EnterAtHealthFraction:P0}; an itinerary must " + "descend strictly.", "stations"); } } BossStation[] array = new BossStation[stations.Count]; for (int j = 0; j < stations.Count; j++) { array[j] = stations[j]; } return array; } private static void RequireNonNegative(float value, string name) { if (value < 0f || float.IsNaN(value)) { throw new ArgumentOutOfRangeException(name, value, "Duration cannot be negative or NaN."); } } private static void RequirePositive(float value, string name) { if (value <= 0f || float.IsNaN(value)) { throw new ArgumentOutOfRangeException(name, value, "Duration must be positive."); } } [CompilerGenerated] private BossDefinition(BossDefinition original) { MaxHealth = original.MaxHealth; PhaseTwoHealthFraction = original.PhaseTwoHealthFraction; MoveSpeed = original.MoveSpeed; IdleSeconds = original.IdleSeconds; TelegraphSeconds = original.TelegraphSeconds; CommitSeconds = original.CommitSeconds; RecoverSeconds = original.RecoverSeconds; WeakPointDamageMultiplier = original.WeakPointDamageMultiplier; AttackDamage = original.AttackDamage; AimedHitRadius = original.AimedHitRadius; AreaHitRadius = original.AreaHitRadius; Stations = original.Stations; VanishSeconds = original.VanishSeconds; HiddenSeconds = original.HiddenSeconds; AppearSeconds = original.AppearSeconds; OpeningSeconds = original.OpeningSeconds; AttacksOnItsOwn = original.AttacksOnItsOwn; RageDamageMultiplier = original.RageDamageMultiplier; RageEndsAfterHealthFraction = original.RageEndsAfterHealthFraction; } } public readonly struct BossInstanceId : IEquatable<BossInstanceId> { private readonly int _value; public int Value => _value; public BossInstanceId(int value) { _value = value; } public bool Equals(BossInstanceId other) { return _value == other._value; } public override bool Equals(object? obj) { if (obj is BossInstanceId other) { return Equals(other); } return false; } public override int GetHashCode() { return _value; } public override string ToString() { return $"boss:{_value}"; } public static bool operator ==(BossInstanceId left, BossInstanceId right) { return left.Equals(right); } public static bool operator !=(BossInstanceId left, BossInstanceId right) { return !left.Equals(right); } } public enum BossPhase { One = 1, Two } public sealed class BossSimulation { private readonly BossDefinition _definition; private readonly ISimulationClock _clock; private readonly IAuthoritativeRandom _random; private readonly IEncounterParticipantQuery _participants; private readonly List<IBossDomainEvent> _events = new List<IBossDomainEvent>(); private readonly List<DamageRequest> _damageRequests = new List<DamageRequest>(); private readonly List<SummonRequest> _summonRequests = new List<SummonRequest>(); private readonly IReadOnlyList<BossAnchor> _anchors; private bool _spawned; private float _beganTime; private int _healthWhenEnraged; private int _pendingStation = -1; private float _activityEnteredTime; private float _lastAdvanceTime; private AttackInstanceId _lastAttackId; public BossInstanceId Id { get; } public bool IsSpawned => _spawned; public bool HasBegun { get; private set; } private float OpeningEndsAt => _beganTime + _definition.OpeningSeconds; public bool IsOpening { get { if (HasBegun) { return _clock.Time < OpeningEndsAt; } return false; } } public bool IsOutsideTheFight { get { if (HasBegun) { return IsOpening; } return true; } } public int Health { get; private set; } public int MaxHealth => _definition.MaxHealth; public float HealthFraction { get { if (_definition.MaxHealth <= 0) { return 0f; } return (float)Health / (float)_definition.MaxHealth; } } public BossPhase Phase { get; private set; } public BossActivity Activity { get; private set; } public bool IsDead => Activity == BossActivity.Dead; public bool IsWeakPointExposed => Activity == BossActivity.Recovering; public bool IsEnraged { get; private set; } public SimVector2 Position { get; private set; } public float PositionHeight { get; private set; } public int StationIndex { get; private set; } public int PendingStationIndex => _pendingStation; public bool IsRelocating { get { if (Activity != BossActivity.Vanishing && Activity != BossActivity.Hidden) { return Activity == BossActivity.Appearing; } return true; } } public SimVector2 Facing { get; private set; } public AttackInstanceId? CurrentAttack { get; private set; } public BossAttackKind CurrentAttackKind { get; private set; } public SimVector2 CurrentAttackAimPoint { get; private set; } public BossSimulation(BossInstanceId id, BossDefinition definition, ISimulationClock clock, IAuthoritativeRandom random, IEncounterParticipantQuery participants, IReadOnlyList<BossAnchor>? anchors = null) { Id = id; _definition = definition ?? throw new ArgumentNullException("definition"); _clock = clock ?? throw new ArgumentNullException("clock"); _random = random ?? throw new ArgumentNullException("random"); _participants = participants ?? throw new ArgumentNullException("participants"); _anchors = anchors ?? Array.Empty<BossAnchor>(); _lastAttackId = new AttackInstanceId(0L); Activity = BossActivity.Idle; Phase = BossPhase.One; StationIndex = -1; } public void Spawn(SimVector2 startPosition, float startHeight = 0f, bool waitToBegin = false) { if (!_spawned) { _spawned = true; Health = _definition.MaxHealth; Phase = BossPhase.One; Activity = BossActivity.Idle; Position = startPosition; PositionHeight = startHeight; Facing = SimVector2.Zero; StationIndex = -1; if (TryEnterStation(0)) { StationIndex = 0; } _activityEnteredTime = _clock.Time; _lastAdvanceTime = _clock.Time; _events.Add(new BossSpawned(Id, Phase, Health)); if (!waitToBegin) { Begin(); } } } public bool Begin() { if (!_spawned || IsDead || HasBegun) { return false; } HasBegun = true; _beganTime = _clock.Time; _activityEnteredTime = _beganTime; _lastAdvanceTime = _beganTime; _events.Add(new BossBegan(Id)); return true; } public void Advance() { if (!_spawned || IsDead) { return; } if (!HasBegun || _clock.Time < OpeningEndsAt) { _lastAdvanceTime = _clock.Time; _activityEnteredTime = _clock.Time; return; } if (_activityEnteredTime < OpeningEndsAt) { _activityEnteredTime = OpeningEndsAt; if (_lastAdvanceTime < OpeningEndsAt) { _lastAdvanceTime = OpeningEndsAt; } } float time = _clock.Time; float num = Math.Max(0f, time - _lastAdvanceTime); _lastAdvanceTime = time; ParticipantId nearest; SimVector2 position; bool flag = TryGetNearestTarget(out nearest, out position); if (flag && !IsRelocating) { Facing = Position.DirectionTo(position); } if (Activity == BossActivity.Idle && flag && _definition.MoveSpeed > 0f) { Position = Position.MoveToward(position, _definition.MoveSpeed * num); } float num2 = Math.Max(0f, time - _activityEnteredTime); switch (Activity) { case BossActivity.Vanishing: if (num2 >= _definition.VanishSeconds) { EnterHidden(time); } break; case BossActivity.Hidden: if (num2 >= _definition.HiddenSeconds) { EnterAppearing(time); } break; case BossActivity.Appearing: if (num2 >= _definition.AppearSeconds) { FinishRelocation(time); } break; case BossActivity.Idle: if (!flag || !_definition.AttacksOnItsOwn) { _activityEnteredTime = time; } else if (num2 >= _definition.IdleSeconds) { SelectAttack(time, position); } break; case BossActivity.Telegraphing: if (num2 >= _definition.TelegraphSeconds) { CommitAttack(time); } break; case BossActivity.Committing: if (num2 >= _definition.CommitSeconds) { BeginRecovery(time); } break; case BossActivity.Recovering: if (num2 >= _definition.RecoverSeconds) { EndRecovery(time); } break; case BossActivity.Dead: break; } } public void ApplyDamage(int rawAmount) { if (!_spawned || IsDead || rawAmount <= 0 || IsRelocating || IsOutsideTheFight) { return; } bool isWeakPointExposed = IsWeakPointExposed; int num = rawAmount * ((!isWeakPointExposed) ? 1 : _definition.WeakPointDamageMultiplier); if (IsEnraged) { num = (int)Math.Round((double)num * (double)_definition.RageDamageMultiplier, MidpointRounding.AwayFromZero); } Health = Math.Max(0, Health - num); _events.Add(new BossDamaged(Id, num, Health, isWeakPointExposed)); if (Health == 0) { Activity = BossActivity.Dead; CurrentAttack = null; Facing = SimVector2.Zero; IsEnraged = false; _events.Add(new BossDied(Id)); return; } SpendTheRage(); AdvanceStations(); if (Phase == BossPhase.One && Health <= _definition.PhaseTwoHealthThreshold) { Phase = BossPhase.Two; _events.Add(new BossPhaseChanged(Id, Phase)); } } public bool SetEnraged(bool enraged) { if (!_spawned || IsDead || enraged == IsEnraged) { return false; } IsEnraged = enraged; if (enraged) { _healthWhenEnraged = Health; } _events.Add(new BossEnraged(Id, enraged)); return true; } private void SpendTheRage() { if (IsEnraged && !(_definition.RageEndsAfterHealthFraction <= 0f) && !((float)(_healthWhenEnraged - Health) < (float)_definition.MaxHealth * _definition.RageEndsAfterHealthFraction)) { SetEnraged(enraged: false); } } public IReadOnlyList<IBossDomainEvent> DrainEvents() { if (_events.Count == 0) { return Array.Empty<IBossDomainEvent>(); } IBossDomainEvent[] result = _events.ToArray(); _events.Clear(); return result; } public IReadOnlyList<DamageRequest> DrainDamageRequests() { if (_damageRequests.Count == 0) { return Array.Empty<DamageRequest>(); } DamageRequest[] result = _damageRequests.ToArray(); _damageRequests.Clear(); return result; } private void AdvanceStations() { IReadOnlyList<BossStation> stations = _definition.Stations; if (StationIndex >= 0 && !IsRelocating && _pendingStation < 0) { int num = StationIndex + 1; if (num < stations.Count && !(HealthFraction > stations[num].EnterAtHealthFraction)) { _pendingStation = num; BeginRelocation(_clock.Time); } } } private void BeginRelocation(float now) { if (Activity == BossActivity.Recovering) { _events.Add(new WeakPointExposed(Id, Exposed: false)); } CurrentAttack = null; Facing = SimVector2.Zero; Activity = BossActivity.Vanishing; _activityEnteredTime = now; } private void EnterHidden(float now) { Activity = BossActivity.Hidden; _activityEnteredTime = now; int pendingStation = _pendingStation; _pendingStation = -1; if (pendingStation >= 0 && TryEnterStation(pendingStation)) { StationIndex = pendingStation; _events.Add(new BossRelocated(Id, pendingStation, _definition.Stations[pendingStation].AnchorIndex, Position, PositionHeight)); } } private void EnterAppearing(float now) { Activity = BossActivity.Appearing; _activityEnteredTime = now; IReadOnlyList<BossStation> stations = _definition.Stations; if (StationIndex >= 0 && StationIndex < stations.Count && stations[StationIndex].Summons.NamesABand) { _summonRequests.Add(new SummonRequest(StationIndex, stations[StationIndex].Summons)); } } private void FinishRelocation(float now) { Activity = BossActivity.Idle; _activityEnteredTime = now; AdvanceStations(); } private bool TryEnterStation(int stationIndex) { IReadOnlyList<BossStation> stations = _definition.Stations; if (stationIndex < 0 || stationIndex >= stations.Count) { return false; } int anchorIndex = stations[stationIndex].AnchorIndex; if (anchorIndex < 0 || anchorIndex >= _anchors.Count) { return false; } BossAnchor bossAnchor = _anchors[anchorIndex]; Position = bossAnchor.Ground; PositionHeight = bossAnchor.Height; return true; } public IReadOnlyList<SummonRequest> DrainSummonRequests() { if (_summonRequests.Count == 0) { return Array.Empty<SummonRequest>(); } SummonRequest[] result = _summonRequests.ToArray(); _summonRequests.Clear(); return result; } private void SelectAttack(float now, SimVector2 targetPosition) { BossAttackKind bossAttackKind = ((_random.NextInt(0, 2) == 0) ? BossAttackKind.AimedProjectile : BossAttackKind.AreaTelegraph); _lastAttackId = _lastAttackId.Next(); CurrentAttack = _lastAttackId; CurrentAttackKind = bossAttackKind; CurrentAttackAimPoint = targetPosition; Activity = BossActivity.Telegraphing; _activityEnteredTime = now; _events.Add(new AttackTelegraphed(Id, _lastAttackId, bossAttackKind, targetPosition, _definition.TelegraphSeconds)); } private void CommitAttack(float now) { Activity = BossActivity.Committing; _activityEnteredTime = now; _events.Add(new AttackCommitted(Id, _lastAttackId, CurrentAttackKind, CurrentAttackAimPoint)); ResolveAttackHits(); } private void ResolveAttackHits() { float num = ((CurrentAttackKind == BossAttackKind.AimedProjectile) ? _definition.AimedHitRadius : _definition.AreaHitRadius); IReadOnlyList<ParticipantId> participants = _participants.Participants; for (int i = 0; i < participants.Count; i++) { ParticipantId participantId = participants[i]; if (_participants.TryGetPosition(participantId, out var position) && CurrentAttackAimPoint.DistanceTo(position) <= num) { _damageRequests.Add(new DamageRequest(participantId, _definition.AttackDamage, _lastAttackId)); } } } private void BeginRecovery(float now) { CurrentAttack = null; Activity = BossActivity.Recovering; _activityEnteredTime = now; _events.Add(new WeakPointExposed(Id, Exposed: true)); } private void EndRecovery(float now) { Activity = BossActivity.Idle; _activityEnteredTime = now; _events.Add(new WeakPointExposed(Id, Exposed: false)); } private bool TryGetNearestTarget(out ParticipantId nearest, out SimVector2 position) { nearest = default(ParticipantId); position = default(SimVector2); bool flag = false; float num = float.MaxValue; IReadOnlyList<ParticipantId> participants = _participants.Participants; for (int i = 0; i < participants.Count; i++) { ParticipantId participantId = participants[i]; if (_participants.TryGetPosition(participantId, out var position2)) { float num2 = Position.DistanceTo(position2); if (!flag || num2 < num) { flag = true; num = num2; nearest = participantId; position = position2; } } } return flag; } } public readonly struct BossAnchor : IEquatable<BossAnchor> { public SimVector2 Ground { get; } public float Height { get; } public BossAnchor(SimVector2 ground, float height) { Ground = ground; Height = height; } public bool Equals(BossAnchor other) { if (Ground.Equals(other.Ground)) { return Height.Equals(other.Height); } return false; } public override bool Equals(object? obj) { if (obj is BossAnchor other) { return Equals(other); } return false; } public override int GetHashCode() { return (Ground.GetHashCode() * 397) ^ Height.GetHashCode(); } public override string ToString() { return $"({Ground.X:0.0}, {Height:0.0}, {Ground.Z:0.0})"; } } public readonly struct BossStation : IEquatable<BossStation> { public int AnchorIndex { get; } public float EnterAtHealthFraction { get; } public MinionBandId Summons { get; } public BossStation(int anchorIndex, float enterAtHealthFraction, MinionBandId summons = default(MinionBandId)) { if (anchorIndex < 0) { throw new ArgumentOutOfRangeException("anchorIndex", anchorIndex, "An anchor index cannot be negative."); } if (enterAtHealthFraction <= 0f || enterAtHealthFraction > 1f) { throw new ArgumentOutOfRangeException("enterAtHealthFraction", enterAtHealthFraction, "A station is entered at a health fraction in (0, 1] — a station entered at zero health would be entered by a dead boss."); } AnchorIndex = anchorIndex; EnterAtHealthFraction = enterAtHealthFraction; Summons = summons; } public bool Equals(BossStation other) { if (AnchorIndex == other.AnchorIndex && EnterAtHealthFraction.Equals(other.EnterAtHealthFraction)) { return Summons.Equals(other.Summons); } return false; } public override bool Equals(object? obj) { if (obj is BossStation other) { return Equals(other); } return false; } public override int GetHashCode() { return (AnchorIndex * 397) ^ EnterAtHealthFraction.GetHashCode(); } public override string ToString() { if (!Summons.NamesABand) { return $"anchor {AnchorIndex} at <= {EnterAtHealthFraction:P0} health"; } return $"anchor {AnchorIndex} at <= {EnterAtHealthFraction:P0} health, summoning the {Summons} band"; } } } namespace FalseGods.Core.Bosses.Events { public sealed record BossSpawned(BossInstanceId Boss, BossPhase Phase, int Health) : IBossDomainEvent; public sealed record BossBegan(BossInstanceId Boss) : IBossDomainEvent; public sealed record AttackTelegraphed(BossInstanceId Boss, AttackInstanceId Attack, BossAttackKind Kind, SimVector2 AimPoint, float TelegraphSeconds) : IBossDomainEvent; public sealed record AttackCommitted(BossInstanceId Boss, AttackInstanceId Attack, BossAttackKind Kind, SimVector2 AimPoint) : IBossDomainEvent; public sealed record WeakPointExposed(BossInstanceId Boss, bool Exposed) : IBossDomainEvent; public sealed record BossPhaseChanged(BossInstanceId Boss, BossPhase Phase) : IBossDomainEvent; public sealed record BossDamaged(BossInstanceId Boss, int Amount, int RemainingHealth, bool WeakPointHit) : IBossDomainEvent; public sealed record BossRelocated(BossInstanceId Boss, int StationIndex, int AnchorIndex, SimVector2 Position, float Height) : IBossDomainEvent; public sealed record BossEnraged(BossInstanceId Boss, bool Enraged) : IBossDomainEvent; public sealed record BossDied(BossInstanceId Boss) : IBossDomainEvent; public interface IBossDomainEvent { BossInstanceId Boss { get; } } } namespace FalseGods.Core.Bosses.Combat { public static class BallisticArc { public static float HorizontalFraction(float normalizedTime) { return Clamp01(normalizedTime); } public static float Height(float normalizedTime, float apexHeight) { float num = Clamp01(normalizedTime); return 4f * apexHeight * num * (1f - num); } private static float Clamp01(float value) { if (value < 0f) { return 0f; } if (!(value > 1f)) { return value; } return 1f; } } public enum CrateDeath { Shot, Struck } public enum CratePileKind { Loose, Source, Delivery } public readonly struct CratePileId : IEquatable<CratePileId> { public static CratePileId Loose => new CratePileId(CratePileKind.Loose, 0); public CratePileKind Kind { get; } public int Index { get; } private CratePileId(CratePileKind kind, int index) { Kind = kind; Index = index; } public static CratePileId Source(int index) { return Of(CratePileKind.Source, index); } public static CratePileId Delivery(int index) { return Of(CratePileKind.Delivery, index); } public static bool TryFrom(int kind, int index, out CratePileId pile) { pile = Loose; if (index < 0) { return false; } switch ((CratePileKind)kind) { case CratePileKind.Loose: return true; case CratePileKind.Source: case CratePileKind.Delivery: pile = new CratePileId((CratePileKind)kind, index); return true; default: return false; } } private static CratePileId Of(CratePileKind kind, int index) { if (index < 0) { throw new ArgumentOutOfRangeException("index", index, "A pile index is a position in the room's authored group, never negative."); } return new CratePileId(kind, index); } public bool Equals(CratePileId other) { if (Kind == other.Kind) { return Index == other.Index; } return false; } public override bool Equals(object? obj) { if (obj is CratePileId other) { return Equals(other); } return false; } public override int GetHashCode() { return ((int)Kind * 397) ^ Index; } public static bool operator ==(CratePileId left, CratePileId right) { return left.Equals(right); } public static bool operator !=(CratePileId left, CratePileId right) { return !left.Equals(right); } public override string ToString() { if (Kind != CratePileKind.Loose) { return $"{Kind.ToString().ToLowerInvariant()} #{Index}"; } return "loose"; } } public sealed record DamageRequest(ParticipantId Target, int Amount, AttackInstanceId Attack); public static class LeadAim { public static SimVector2 Predict(SimVector2 position, SimVector2 velocity, float seconds) { return new SimVector2(position.X + velocity.X * seconds, position.Z + velocity.Z * seconds); } } public readonly struct MinionBandId : IEquatable<MinionBandId> { private readonly string _value; public string Value => _value ?? string.Empty; public bool NamesABand => !string.IsNullOrEmpty(_value); public MinionBandId(string value) { if (string.IsNullOrEmpty(value)) { throw new ArgumentException("A minion band id must be a non-empty string.", "value"); } _value = value; } public bool Equals(MinionBandId other) { return string.Equals(Value, other.Value, StringComparison.Ordinal); } public override bool Equals(object? obj) { if (obj is MinionBandId other) { return Equals(other); } return false; } public override int GetHashCode() { return StringComparer.Ordinal.GetHashCode(Value); } public override string ToString() { if (!NamesABand) { return "(no band)"; } return Value; } public static bool operator ==(MinionBandId left, MinionBandId right) { return left.Equals(right); } public static bool operator !=(MinionBandId left, MinionBandId right) { return !left.Equals(right); } } public static class MinionBands { public static readonly MinionBandId Vanguard = new MinionBandId("vanguard"); public static readonly MinionBandId Warband = new MinionBandId("warband"); public static readonly MinionBandId Coven = new MinionBandId("coven"); public static readonly MinionBandId Emergency = new MinionBandId("emergency"); } public static class SeededRandom { public static double Unit01(int seed, int salt) { int num = seed * -1640531535 + salt * -2048144777 + 374761393; int num2 = (num ^ (num >>> 15)) * -2048144777; int num3 = (num2 ^ (num2 >>> 13)) * -1028477379; return (double)(uint)(num3 ^ (num3 >>> 16)) / 4294967296.0; } public static float Range(int seed, int salt, float min, float max) { return min + (float)Unit01(seed, salt) * (max - min); } } public readonly struct SpreadOffset { public float X { get; } public float Z { get; } public SpreadOffset(float x, float z) { X = x; Z = z; } } public static class ShotgunSpread { public static SpreadOffset Offset(int seed, int index, int count, float minRadius, float maxRadius) { if (count < 1) { count = 1; } if (index < 0) { index = 0; } double num = Math.PI * 2.0 / (double)count; double num2 = SeededRandom.Unit01(seed, 0) * 2.0 * Math.PI; double num3 = (SeededRandom.Unit01(seed, index * 2 + 1) - 0.5) * (num * 0.5); double num4 = num2 + num * (double)index + num3; float num5 = SeededRandom.Range(seed, index * 2 + 2, minRadius, maxRadius); return new SpreadOffset((float)(Math.Cos(num4) * (double)num5), (float)(Math.Sin(num4) * (double)num5)); } } public sealed class StarvationWatch { private float _sinceDelivery; private float _sinceHit; public bool Enraged { get; private set; } public float SinceDelivery => _sinceDelivery; public float SinceHit => _sinceHit; public StarvationReason Reason { get; private set; } public StarvationChange Advance(float deltaSeconds, bool deliveryArrived, float patienceSeconds, int emergencyBandAlive, bool hitSomebody = false, float futilitySeconds = 0f) { float num = ((deltaSeconds > 0f) ? deltaSeconds : 0f); _sinceDelivery = (deliveryArrived ? 0f : (_sinceDelivery + num)); _sinceHit = (hitSomebody ? 0f : (_sinceHit + num)); bool flag = _sinceDelivery < patienceSeconds; bool flag2 = futilitySeconds <= 0f || _sinceHit < futilitySeconds; if (!Enraged) { if (flag && flag2) { return StarvationChange.Nothing; } Enraged = true; Reason = (flag ? StarvationReason.NothingLanding : StarvationReason.NothingArriving); return StarvationChange.Enraged; } if (flag && flag2 && emergencyBandAlive <= 0) { Enraged = false; return StarvationChange.Calmed; } return StarvationChange.Nothing; } public void Reset() { Enraged = false; _sinceDelivery = 0f; _sinceHit = 0f; } } public enum StarvationReason { NothingArriving, NothingLanding } public enum StarvationChange { Nothing, Enraged, Calmed } public sealed record SummonRequest(int StationIndex, MinionBandId Band); public readonly struct SupplyStep { public float AboveHealthFraction { get; } public int Carriers { get; } public int LoadPerCarrier { get; } public float ExplosiveChance { get; } public int Throughput => Carriers * LoadPerCarrier; public SupplyStep(float aboveHealthFraction, int carriers, int loadPerCarrier, float explosiveChance = 0f) { if (explosiveChance < 0f || explosiveChance > 1f || float.IsNaN(explosiveChance)) { throw new ArgumentOutOfRangeException("explosiveChance", explosiveChance, "A chance lies in [0, 1]."); } if (aboveHealthFraction < 0f || aboveHealthFraction > 1f) { throw new ArgumentOutOfRangeException("aboveHealthFraction", aboveHealthFraction, "A health fraction lies in [0, 1]."); } if (carriers < 0) { throw new ArgumentOutOfRangeException("carriers", carriers, "A step cannot put a negative number of carriers on the route."); } if (loadPerCarrier < 0) { throw new ArgumentOutOfRangeException("loadPerCarrier", loadPerCarrier, "A carrier cannot haul a negative load."); } AboveHealthFraction = aboveHealthFraction; Carriers = carriers; LoadPerCarrier = loadPerCarrier; ExplosiveChance = explosiveChance; } } public sealed class SupplyEscalation { private readonly SupplyStep[] _steps; public int Count => _steps.Length; public SupplyEscalation(params SupplyStep[] steps) { _steps = steps ?? Array.Empty<SupplyStep>(); for (int i = 1; i < _steps.Length; i++) { if (_steps[i].AboveHealthFraction > _steps[i - 1].AboveHealthFraction) { throw new ArgumentException("Supply steps are read in order as the boss loses health, so their thresholds must " + $"descend; step {i} sits above step {i - 1}.", "steps"); } } } public SupplyStep At(float healthFraction) { if (_steps.Length == 0) { return new SupplyStep(0f, 0, 0); } for (int i = 0; i < _steps.Length; i++) { if (healthFraction > _steps[i].AboveHealthFraction) { return _steps[i]; } } return _steps[_steps.Length - 1]; } public static float RatePerSecond(SupplyStep step, float roundTripSeconds) { if (!(roundTripSeconds > 0f)) { return 0f; } return (float)step.Throughput / roundTripSeconds; } } public readonly struct SupplyLineShape { public float SecondsPerCrate { get; } public int SourceCapacity { get; } public int DeliveryCapacity { get; } public SupplyLineShape(float secondsPerCrate, int sourceCapacity, int deliveryCapacity) { if (!(secondsPerCrate > 0f)) { throw new ArgumentOutOfRangeException("secondsPerCrate", secondsPerCrate, "A production interval must be a positive number of seconds; zero would produce a crate every frame."); } if (sourceCapacity < 0) { throw new ArgumentOutOfRangeException("sourceCapacity", sourceCapacity, "A capacity cannot be negative."); } if (deliveryCapacity < 0) { throw new ArgumentOutOfRangeException("deliveryCapacity", deliveryCapacity, "A capacity cannot be negative."); } SecondsPerCrate = secondsPerCrate; SourceCapacity = sourceCapacity; DeliveryCapacity = deliveryCapacity; } } public sealed class SupplyLine { private readonly SupplyLineShape _shape; private readonly float[] _sinceProduced; private readonly List<int> _due = new List<int>(); public int SourceCount => _sinceProduced.Length; public SupplyLine(SupplyLineShape shape, int sourceCount) { if (sourceCount < 0) { throw new ArgumentOutOfRangeException("sourceCount", sourceCount, "A room cannot have a negative number of production points."); } _shape = shape; _sinceProduced = new float[sourceCount]; } public void Advance(float deltaSeconds, IReadOnlyList<int> restingAtSource) { _due.Clear(); if (deltaSeconds <= 0f) { return; } for (int i = 0; i < _sinceProduced.Length; i++) { if (((restingAtSource != null && i < restingAtSource.Count) ? restingAtSource[i] : 0) >= _shape.SourceCapacity) { _sinceProduced[i] = 0f; continue; } _sinceProduced[i] += deltaSeconds; if (!(_sinceProduced[i] < _shape.SecondsPerCrate)) { _sinceProduced[i] = 0f; _due.Add(i); } } } public IReadOnlyList<int> DrainProductionRequests() { return _due; } public bool AcceptsDelivery(int resting) { return resting < _shape.DeliveryCapacity; } } public sealed class TargetMotionTracker { private readonly float _smoothingSeconds; private SimVector2 _smoothed = SimVector2.Zero; private bool _hasSample; public SimVector2 SmoothedVelocity { get { if (!_hasSample) { return SimVector2.Zero; } return _smoothed; } } public TargetMotionTracker(float smoothingSeconds) { _smoothingSeconds = smoothingSeconds; } public void Observe(SimVector2 velocity, float deltaSeconds) { if (!_hasSample || _smoothingSeconds <= 0f || deltaSeconds <= 0f) { _smoothed = velocity; _hasSample = true; return; } float num = deltaSeconds / _smoothingSeconds; if (num > 1f) { num = 1f; } _smoothed = new SimVector2(_smoothed.X + (velocity.X - _smoothed.X) * num, _smoothed.Z + (velocity.Z - _smoothed.Z) * num); } public void Reset() { _smoothed = SimVector2.Zero; _hasSample = false; } } } namespace FalseGods.Core.Arena { public sealed class ArenaSimulation { private readonly HashSet<MechanismGroupId> _activeGroups = new HashSet<MechanismGroupId>(); private readonly List<IArenaDomainEvent> _events = new List<IArenaDomainEvent>(); public bool IsExitUnlocked { get; private set; } public IReadOnlyCollection<MechanismGroupId> ActiveMechanismGroups => _activeGroups; public bool IsMechanismGroupActive(MechanismGroupId group) { return _activeGroups.Contains(group); } public void ActivateMechanismGroup(MechanismGroupId group) { if (_activeGroups.Add(group)) { _events.Add(new MechanismGroupActivated(group)); } } public void UnlockExit() { if (!IsExitUnlocked) { IsExitUnlocked = true; _events.Add(new ArenaExitUnlocked()); } } public IReadOnlyList<IArenaDomainEvent> DrainEvents() { if (_events.Count == 0) { return Array.Empty<IArenaDomainEvent>(); } IArenaDomainEvent[] result = _events.ToArray(); _events.Clear(); return result; } } public readonly struct MechanismGroupId : IEquatable<MechanismGroupId> { private readonly string _value; public string Value => _value ?? string.Empty; public MechanismGroupId(string value) { if (string.IsNullOrEmpty(value)) { throw new ArgumentException("A mechanism group id must be a non-empty string.", "value"); } _value = value; } public bool Equals(MechanismGroupId other) { return string.Equals(Value, other.Value, StringComparison.Ordinal); } public override bool Equals(object? obj) { if (obj is MechanismGroupId other) { return Equals(other); } return false; } public override int GetHashCode() { return StringComparer.Ordinal.GetHashCode(Value); } public override string ToString() { return Value; } public static bool operator ==(MechanismGroupId left, MechanismGroupId right) { return left.Equals(right); } public static bool operator !=(MechanismGroupId left, MechanismGroupId right) { return !left.Equals(right); } } } namespace FalseGods.Core.Arena.Events { public sealed record MechanismGroupActivated(MechanismGroupId Group) : IArenaDomainEvent; public sealed record ArenaExitUnlocked : IArenaDomainEvent; public interface IArenaDomainEvent { } }
FalseGods.Integration.Sulfur.dll
Decompiled 9 hours 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.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using CMF; using FalseGods.Application.Arena; using FalseGods.Application.Combat; using FalseGods.Application.Presentation; using FalseGods.Core.Bosses.Combat; using FalseGods.Core.Simulation; using FalseGods.Integration.Sulfur.Arena; using FalseGods.Integration.Sulfur.Combat; using FalseGods.Protocol.Wire; using FalseGods.RuntimeContracts.Arena; using FalseGods.RuntimeContracts.Diagnostics; using FalseGods.RuntimeContracts.Multiplayer; using HarmonyLib; using I2.Loc; using LevelGeneration; using MakerGraphTool; using MakerGraphTool.Nodes; using Microsoft.CodeAnalysis; using Pathfinding; using Pathfinding.Graphs.Navmesh; using PerfectRandom.Sulfur.Core; using PerfectRandom.Sulfur.Core.DevTools; using PerfectRandom.Sulfur.Core.Effects; using PerfectRandom.Sulfur.Core.Items; using PerfectRandom.Sulfur.Core.LevelGeneration; using PerfectRandom.Sulfur.Core.Movement; using PerfectRandom.Sulfur.Core.Stats; using PerfectRandom.Sulfur.Core.UI; using PerfectRandom.Sulfur.Core.Units; using PerfectRandom.Sulfur.Core.Units.AI; using PerfectRandom.Sulfur.Core.Weapons; using PerfectRandom.Sulfur.Gameplay; using PerfectRandom.Sulfur.Gameplay.Triggers; using Sonity; using Sonity.Internal; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.Events; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceLocations; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FalseGods.Integration.Sulfur")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6e5740a80f810ab422551028733810b527fb614d")] [assembly: AssemblyProduct("FalseGods.Integration.Sulfur")] [assembly: AssemblyTitle("FalseGods.Integration.Sulfur")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FalseGods.Integration.Sulfur.Simulation { public sealed class SeededAuthoritativeRandom : IAuthoritativeRandom { private readonly Random _random; public SeededAuthoritativeRandom(int seed) { _random = new Random(seed); } public int NextInt(int minInclusive, int maxExclusive) { return _random.Next(minInclusive, maxExclusive); } public float NextFloat() { return (float)_random.NextDouble(); } } public sealed class SulfurLocalPlayer { public bool TryGetLocalParticipantIndex(out int playerIndex) { GameManager instance = StaticInstance<GameManager>.Instance; Player val = (((Object)(object)instance != (Object)null) ? instance.PlayerScript : null); if ((Object)(object)val != (Object)null) { playerIndex = val.playerIndex; return true; } playerIndex = -1; return false; } } public sealed class SulfurParticipantQuery : IEncounterParticipantQuery { private readonly List<ParticipantId> _ids = new List<ParticipantId>(); public IReadOnlyList<ParticipantId> Participants { get { //IL_0044: Unknown result type (might be due to invalid IL or missing references) _ids.Clear(); List<Player> list = ActivePlayers(); if (list == null) { return _ids; } for (int i = 0; i < list.Count; i++) { Player val = list[i]; if ((Object)(object)val != (Object)null && FightingPlayers.IsFighting(val)) { _ids.Add(new ParticipantId(val.playerIndex)); } } return _ids; } } public bool TryGetPosition(ParticipantId participant, out SimVector2 position) { //IL_0068: 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_0040: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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) List<Player> list = ActivePlayers(); if (list != null) { for (int i = 0; i < list.Count; i++) { Player val = list[i]; if ((Object)(object)val != (Object)null && val.playerIndex == ((ParticipantId)(ref participant)).Value && FightingPlayers.IsFighting(val)) { Vector3 position2 = ((Component)val).transform.position; position = new SimVector2(position2.x, position2.z); return true; } } } position = default(SimVector2); return false; } private static List<Player>? ActivePlayers() { GameManager instance = StaticInstance<GameManager>.Instance; if (!((Object)(object)instance != (Object)null)) { return null; } return instance.Players; } } public sealed class SulfurSimulationClock : ISimulationClock { public long Tick => Time.frameCount; public float Time => Time.time; } } namespace FalseGods.Integration.Sulfur.Presentation { public sealed class SulfurArenaAtmosphere : IArenaAtmospherePort, IDisposable { private const string CaveBossRoomKey = "Assets/_Core/Prefabs/LevelGeneration/Chunks/Caves/CaveCousinNew.prefab"; private const float MusicFadeSeconds = 10f; private readonly MonoBehaviour _host; private readonly ILogger _logger; private AssetReference _room; private MusicTrigger _music; private bool _searchedForMusic; private Coroutine _pendingDepth; private bool _playing; public SulfurArenaAtmosphere(MonoBehaviour host, ILogger logger = null) { if (!((Object)(object)host != (Object)null)) { throw new ArgumentNullException("host"); } _host = host; _logger = logger; } public void Warm() { FindTheMusic(); } public void SetRoomDepth(float startDistance, float endDistance, float afterSeconds = 0f, float overSeconds = 0f) { CancelPendingDepth(); if (afterSeconds <= 0f) { Apply(startDistance, endDistance, overSeconds); } else { _pendingDepth = _host.StartCoroutine(AfterAPause(startDistance, endDistance, afterSeconds, overSeconds)); } } public void StartBattleMusic() { MusicTrigger val = FindTheMusic(); if ((Object)(object)val == (Object)null) { return; } try { val.StartMusic(); _playing = true; ILogger logger = _logger; if (logger != null) { logger.Log("[music] the boss's own battle music is playing, on the game's music mix."); } } catch (Exception ex) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[music] the battle music would not start (" + ex.Message + ")."); } } } public void StopBattleMusic() { if (!_playing || (Object)(object)_music == (Object)null) { return; } _playing = false; try { _music.StopMusic(10f); ILogger logger = _logger; if (logger != null) { logger.Log($"[music] the battle music is fading out over {10f:0}s."); } } catch (Exception ex) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[music] the battle music would not stop (" + ex.Message + ")."); } } } public void Dispose() { CancelPendingDepth(); _music = null; _searchedForMusic = false; if (_room != null) { try { _room.ReleaseAsset(); } catch (Exception) { } _room = null; } } private IEnumerator AfterAPause(float start, float end, float afterSeconds, float overSeconds) { yield return (object)new WaitForSecondsRealtime(afterSeconds); _pendingDepth = null; Apply(start, end, overSeconds); } private void Apply(float start, float end, float overSeconds) { SulfurLevelFog.TryApply(start, end, _logger, overSeconds); } private void CancelPendingDepth() { if (_pendingDepth != null) { _host.StopCoroutine(_pendingDepth); _pendingDepth = null; } } private MusicTrigger FindTheMusic() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_music != (Object)null || _searchedForMusic) { return _music; } try { if (_room == null) { _room = new AssetReference("Assets/_Core/Prefabs/LevelGeneration/Chunks/Caves/CaveCousinNew.prefab"); } AsyncOperationHandle<GameObject> val = _room.LoadAssetAsync<GameObject>(); GameObject val2 = val.WaitForCompletion(); if ((int)val.Status != 1 || (Object)(object)val2 == (Object)null) { ILogger logger = _logger; if (logger != null) { logger.LogWarning($"[music] the cave boss's room would not load ({val.Status}); the fight " + "will be fought without its music."); } return null; } _searchedForMusic = true; _music = val2.GetComponentInChildren<MusicTrigger>(true); if ((Object)(object)_music == (Object)null) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[music] the cave boss's room carries no music trigger any more; the fight will be fought without its music."); } return null; } ILogger logger3 = _logger; if (logger3 != null) { logger3.Log("[music] the boss's battle music has been found on its own room."); } return _music; } catch (Exception ex) { ILogger logger4 = _logger; if (logger4 != null) { logger4.LogWarning("[music] the battle music could not be fetched (" + ex.Message + "); trying again at the next encounter."); } return null; } } } public sealed class SulfurBossVoice : IBossVoicePort { private const string RoarFieldName = "roarSoundEvent"; private const float RoarCarriesTimes = 4f; private readonly Transform _mouth; private readonly SoundParameterInternals[] _carry = (SoundParameterInternals[])(object)new SoundParameterInternals[1] { (SoundParameterInternals)new SoundParameterDistanceScale(4f) }; private readonly ILogger? _logger; private const int MaxAttempts = 8; private SoundEvent? _roar; private bool _fetching; private int _attempts; private int _roars; public SulfurBossVoice(Transform lifetime, ILogger? logger = null) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown if ((Object)(object)lifetime == (Object)null) { throw new ArgumentNullException("lifetime"); } GameObject val = new GameObject("FalseGodsBossVoice"); val.transform.SetParent(lifetime, false); _mouth = val.transform; _logger = logger; } public void Warm() { Fetch(); } public void Roar(ArenaWorldPoint at) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) SoundEvent roar = _roar; if ((Object)(object)roar == (Object)null) { Fetch(); return; } try { _mouth.position = new Vector3(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y, ((ArenaWorldPoint)(ref at)).Z); roar.Play(_mouth, _carry); CheckItCarried(roar, ++_roars == 1); } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[voice] the boss's roar would not play (" + ex.Message + ")."); } } } private void CheckItCarried(SoundEvent roar, bool first) { //IL_001c: 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_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) try { AudioListener val = Object.FindObjectOfType<AudioListener>(); string text = (((Object)(object)val != (Object)null) ? (Vector3.Distance(((Component)val).transform.position, _mouth.position).ToString("0.#") + "m") : "nobody listening"); AudioSource lastPlayedAudioSource = roar.GetLastPlayedAudioSource(_mouth); if ((Object)(object)lastPlayedAudioSource == (Object)null) { ILogger? logger = _logger; if (logger != null) { string[] obj = new string[5] { "[voice] the roar made no sound: nothing was allocated for it, from ", null, null, null, null }; Vector3 position = _mouth.position; obj[1] = ((Vector3)(ref position)).ToString("0.#"); obj[2] = " with the ear "; obj[3] = text; obj[4] = " off."; logger.LogWarning(string.Concat(obj)); } } else if (first) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log($"[voice] the boss roars {lastPlayedAudioSource.maxDistance:0.#}m, on the game's " + "'" + (((Object)(object)lastPlayedAudioSource.outputAudioMixerGroup == (Object)null) ? "<none>" : ((Object)lastPlayedAudioSource.outputAudioMixerGroup).name) + "' " + $"mix; the ear was {text} off and heard it at {lastPlayedAudioSource.volume:0.##}."); } } } catch (Exception ex) { ILogger? logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[voice] could not tell whether the roar carried (" + ex.Message + ")."); } } } private async void Fetch() { if ((Object)(object)_roar != (Object)null || _fetching || _attempts >= 8) { return; } _fetching = true; _attempts++; try { UnitSO asset = AssetAccess.GetAsset(UnitIds.GoblinCousin); if ((Object)(object)asset == (Object)null) { Gave("the game has no definition for the cave boss"); return; } GameObject val = await asset.FetchAndLoadUnitLoader().Task; CousinHelper val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<CousinHelper>() : null); if ((Object)(object)val2 == (Object)null) { Gave("the cave boss carries no helper to take a roar from"); return; } ref SoundEvent? roar = ref _roar; object? obj = typeof(CousinHelper).GetField("roarSoundEvent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val2); roar = (SoundEvent?)((obj is SoundEvent) ? obj : null); if ((Object)(object)_roar == (Object)null) { Gave("the cave boss's 'roarSoundEvent' is not where it was"); return; } ILogger? logger = _logger; if (logger != null) { logger.Log("[voice] the boss has found its voice ('" + ((Object)_roar).name + "')."); } } catch (Exception ex) { Gave("could not be fetched (" + ex.Message + ")"); } finally { _fetching = false; } } private void Gave(string reason) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning((_attempts >= 8) ? $"[voice] the boss's roar {reason}; after {_attempts} tries it will rage silently." : ("[voice] the boss's roar " + reason + "; trying again at the next encounter.")); } } } } namespace FalseGods.Integration.Sulfur.Navigation { public sealed class AstarNavigationPort : INavigationPort { private const float BakeClearHeight = 300f; private const float NavBoundsHeight = 4f; private const float FloorBandHalf = 1.5f; private readonly Func<GameObject> _arenaRoot; private readonly ILogger _logger; private AstarPath _appliedGraph; private TileMeshes _savedTiles; private bool[][] _savedWalkable; private IntRect _appliedRect; private bool _applied; public AstarNavigationPort(Func<GameObject> arenaRoot, ILogger logger = null) { _arenaRoot = arenaRoot ?? throw new ArgumentNullException("arenaRoot"); _logger = logger; } public NavigationApplyResult Apply() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_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_00d0: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012d: 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_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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) //IL_019a: 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_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_03b8: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_0453: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Unknown result type (might be due to invalid IL or missing references) if (_applied) { return NavigationApplyResult.Failed("arena navigation is already applied"); } AstarPath active = AstarPath.active; RecastGraph recast = (((Object)(object)active != (Object)null && active.data != null) ? active.data.recastGraph : null); if (recast == null) { return NavigationApplyResult.Failed("no active recast graph (no loaded level)"); } if (!((NavGraph)recast).isScanned) { return NavigationApplyResult.Failed("the level's navigation is not built here (no scanned recast tiles)"); } GameObject val = _arenaRoot(); if ((Object)(object)val == (Object)null) { return NavigationApplyResult.Failed("no realized arena to build navigation for"); } Bounds val2 = WorldBounds(val); TileLayout val3 = default(TileLayout); ((TileLayout)(ref val3))..ctor(recast); IntRect touchingTiles = ((TileLayout)(ref val3)).GetTouchingTiles(val2, 0.5f); Bounds tileBoundsInGraphSpace = ((TileLayout)(ref val3)).GetTileBoundsInGraphSpace(touchingTiles.xmin, touchingTiles.ymin, ((IntRect)(ref touchingTiles)).Width, ((IntRect)(ref touchingTiles)).Height); Vector3 val4 = val3.transform.Transform(((Bounds)(ref tileBoundsInGraphSpace)).center); Vector3 val5 = default(Vector3); ((Vector3)(ref val5))..ctor((float)((IntRect)(ref touchingTiles)).Width * ((TileLayout)(ref val3)).TileWorldSizeX, 4f, (float)((IntRect)(ref touchingTiles)).Height * ((TileLayout)(ref val3)).TileWorldSizeZ); IntRect val6 = default(IntRect); int num = default(int); float yOffset = default(float); NavmeshPrefab.SnapToGraph(val3, new Vector3(val4.x, ((Bounds)(ref val2)).center.y, val4.z), Quaternion.identity, new Bounds(Vector3.zero, val5), ref val6, ref num, ref yOffset); if (val6.xmin < 0 || val6.ymin < 0 || val6.xmax >= ((NavmeshBase)recast).tileXCount || val6.ymax >= ((NavmeshBase)recast).tileZCount) { return NavigationApplyResult.Failed($"arena navigation footprint tiles [{val6.xmin},{val6.ymin}]..[{val6.xmax}," + $"{val6.ymax}] extend past the level's navigable area ({((NavmeshBase)recast).tileXCount}x{((NavmeshBase)recast).tileZCount} " + "tiles); move toward the level centre and try again"); } byte[] array; try { array = BakeInClearSpace(recast, val, val4, val5); } catch (Exception ex) { return NavigationApplyResult.Failed("arena navmesh bake threw: " + ex.Message); } if (array == null) { return NavigationApplyResult.Failed("arena navmesh bake produced no data"); } TileMeshes tiles = TileMeshes.Deserialize(array); int num2 = 0; if (tiles.tileMeshes != null) { for (int i = 0; i < tiles.tileMeshes.Length; i++) { int num3 = num2; int[] triangles = tiles.tileMeshes[i].triangles; num2 = num3 + ((triangles != null) ? triangles.Length : 0) / 3; } } if (num2 == 0) { return NavigationApplyResult.Failed("arena navmesh baked 0 triangles (floor did not rasterize)"); } ((TileMeshes)(ref tiles)).Rotate(num); if (((IntRect)(ref tiles.tileRect)).Width != ((IntRect)(ref val6)).Width || ((IntRect)(ref tiles.tileRect)).Height != ((IntRect)(ref val6)).Height) { return NavigationApplyResult.Failed($"baked tile dims {((IntRect)(ref tiles.tileRect)).Width}x{((IntRect)(ref tiles.tileRect)).Height} do not match the graph rect " + $"{((IntRect)(ref val6)).Width}x{((IntRect)(ref val6)).Height}"); } tiles.tileRect = val6; TileMeshes val7; bool[][] walkablePerTile; try { val7 = SnapshotTiles(recast, val6, out walkablePerTile); } catch (Exception ex2) { return NavigationApplyResult.Failed("level tile snapshot threw: " + ex2.Message); } active.AddWorkItem((Action)delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) recast.ReplaceTiles(tiles, yOffset); }); active.FlushWorkItems(); float y = val.transform.position.y; int num4 = CountWalkable(recast, val2, y - 1.5f, y + 1.5f); if (num4 == 0) { RestoreSnapshot(active, recast, val7, val6, walkablePerTile); return NavigationApplyResult.Failed("applied arena navmesh added no walkable floor nodes; level tiles restored"); } _appliedGraph = active; _savedTiles = val7; _savedWalkable = walkablePerTile; _appliedRect = val6; _applied = true; ILogger logger = _logger; if (logger != null) { logger.Log($"[arena-nav] applied {num2} baked triangles over tiles " + $"[{val6.xmin},{val6.ymin}] {((IntRect)(ref val6)).Width}x{((IntRect)(ref val6)).Height}; " + $"{num4} walkable floor node(s)"); } return NavigationApplyResult.Applied(num4); } public void Remove() { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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) if (!_applied) { return; } try { AstarPath active = AstarPath.active; if ((Object)(object)active == (Object)null || active != _appliedGraph) { ILogger logger = _logger; if (logger != null) { logger.Log("[arena-nav] graph was rebuilt since apply; nothing to restore"); } return; } RecastGraph val = ((active.data != null) ? active.data.recastGraph : null); if (val != null) { RestoreSnapshot(active, val, _savedTiles, _appliedRect, _savedWalkable); ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("[arena-nav] level tiles restored to baseline (geometry + walkability)"); } } } finally { _applied = false; _appliedGraph = null; _savedTiles = default(TileMeshes); _savedWalkable = null; } } private static void RestoreSnapshot(AstarPath astar, RecastGraph recast, TileMeshes saved, IntRect rect, bool[][] savedWalkable) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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) astar.AddWorkItem((Action)delegate { //IL_0007: 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) recast.ReplaceTiles(saved, 0f); RestoreWalkability(recast, rect, savedWalkable); }); astar.FlushWorkItems(); } private static byte[] BakeInClearSpace(RecastGraph recast, GameObject root, Vector3 alignedCentre, Vector3 alignedSize) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_001b: 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_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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0054: 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_0066: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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) GameObject val = Object.Instantiate<GameObject>(root, root.transform.position + Vector3.up * 300f, root.transform.rotation); ((Object)val).name = "FalseGodsArenaNavBake"; try { Bounds val2 = WorldBounds(val); GameObject val3 = new GameObject("FalseGodsArenaNavBakeHolder"); val3.transform.position = new Vector3(alignedCentre.x, ((Bounds)(ref val2)).center.y, alignedCentre.z); try { NavmeshPrefab obj = val3.AddComponent<NavmeshPrefab>(); obj.applyOnStart = false; obj.removeTilesWhenDisabled = false; obj.bounds = new Bounds(Vector3.zero, alignedSize); return obj.Scan(recast); } finally { Object.Destroy((Object)(object)val3); } } finally { Object.Destroy((Object)(object)val); } } private static TileMeshes SnapshotTiles(RecastGraph recast, IntRect rect, out bool[][] walkablePerTile) { //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: 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_0044: 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_0094: 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_00aa: 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_00d0: 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_00da: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) int width = ((IntRect)(ref rect)).Width; int height = ((IntRect)(ref rect)).Height; TileMesh[] array = (TileMesh[])(object)new TileMesh[width * height]; walkablePerTile = new bool[width * height][]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int num = j + i * width; NavmeshTile tile = ((NavmeshBase)recast).GetTile(rect.xmin + j, rect.ymin + i); if (tile == null || tile.tris.Length == 0) { array[num] = new TileMesh { triangles = Array.Empty<int>(), verticesInTileSpace = Array.Empty<Int3>(), tags = Array.Empty<uint>() }; walkablePerTile[num] = Array.Empty<bool>(); continue; } Int3 val = (Int3)new Vector3((float)(rect.xmin + j) * ((NavmeshBase)recast).TileWorldSizeX, 0f, (float)(rect.ymin + i) * ((NavmeshBase)recast).TileWorldSizeZ); Int3[] array2 = (Int3[])(object)new Int3[tile.vertsInGraphSpace.Length]; for (int k = 0; k < array2.Length; k++) { array2[k] = tile.vertsInGraphSpace[k] - val; } int[] array3 = new int[tile.tris.Length]; for (int l = 0; l < array3.Length; l++) { array3[l] = tile.tris[l]; } int num2 = array3.Length / 3; uint[] array4 = new uint[num2]; bool[] array5 = new bool[num2]; TriangleMeshNode[] nodes = tile.nodes; if (nodes != null) { for (int m = 0; m < num2 && m < nodes.Length; m++) { if (nodes[m] != null) { array4[m] = ((GraphNode)nodes[m]).Tag; array5[m] = ((GraphNode)nodes[m]).Walkable; } } } array[num] = new TileMesh { triangles = array3, verticesInTileSpace = array2, tags = array4 }; walkablePerTile[num] = array5; } } return new TileMeshes { tileMeshes = array, tileRect = rect, tileWorldSize = new Vector2(((NavmeshBase)recast).TileWorldSizeX, ((NavmeshBase)recast).TileWorldSizeZ) }; } private static void RestoreWalkability(RecastGraph recast, IntRect rect, bool[][] walkablePerTile) { //IL_002f: 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) if (walkablePerTile == null) { return; } int width = ((IntRect)(ref rect)).Width; int height = ((IntRect)(ref rect)).Height; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { bool[] array = walkablePerTile[j + i * width]; if (array == null || array.Length == 0) { continue; } TriangleMeshNode[] array2 = ((NavmeshBase)recast).GetTile(rect.xmin + j, rect.ymin + i)?.nodes; if (array2 == null) { continue; } for (int k = 0; k < array2.Length && k < array.Length; k++) { if (array2[k] != null) { ((GraphNode)array2[k]).Walkable = array[k]; } } } } } private static int CountWalkable(RecastGraph recast, Bounds xzBounds, float yMin, float yMax) { //IL_0017: 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_0036: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) float minX = ((Bounds)(ref xzBounds)).center.x - ((Bounds)(ref xzBounds)).extents.x; float maxX = ((Bounds)(ref xzBounds)).center.x + ((Bounds)(ref xzBounds)).extents.x; float minZ = ((Bounds)(ref xzBounds)).center.z - ((Bounds)(ref xzBounds)).extents.z; float maxZ = ((Bounds)(ref xzBounds)).center.z + ((Bounds)(ref xzBounds)).extents.z; int count = 0; ((NavGraph)recast).GetNodes((Action<GraphNode>)delegate(GraphNode node) { //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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_0031: 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_004d: 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) if (node.Walkable) { Vector3 val = (Vector3)node.position; if (!(val.y < yMin) && !(val.y > yMax) && !(val.x < minX) && !(val.x > maxX) && !(val.z < minZ) && !(val.z > maxZ)) { count++; } } }); return count; } private static Bounds WorldBounds(GameObject go) { //IL_0034: 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_0012: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true); if (componentsInChildren.Length == 0) { return new Bounds(go.transform.position, new Vector3(24f, 8f, 24f)); } Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } return bounds; } } public sealed class NativeLevelNavigationPort : INavigationPort { private readonly ILogger? _logger; public NativeLevelNavigationPort(ILogger? logger = null) { _logger = logger; } public NavigationApplyResult Apply() { ILogger? logger = _logger; if (logger != null) { logger.Log("[nav] arena navigation left to the level's own scan (native level load)."); } return NavigationApplyResult.Applied(0); } public void Remove() { } } } namespace FalseGods.Integration.Sulfur.Combat { public static class BossWeaponDamage { private sealed class Binding : IDisposable { private BossAttackReceiver? _receiver; public Binding(BossAttackReceiver receiver) { _receiver = receiver; } public void Dispose() { if ((Object)(object)_receiver != (Object)null) { Object.Destroy((Object)(object)_receiver); } _receiver = null; } } public static IDisposable Bind(GameObject collisionBody, IBossDamageSink sink, ILogger? logger) { if ((Object)(object)collisionBody == (Object)null) { throw new ArgumentNullException("collisionBody"); } if (sink == null) { throw new ArgumentNullException("sink"); } BossAttackReceiver bossAttackReceiver = collisionBody.AddComponent<BossAttackReceiver>(); bossAttackReceiver.Initialize(sink); LogProjectileLayerDiagnosis(collisionBody, logger); return new Binding(bossAttackReceiver); } private static void LogProjectileLayerDiagnosis(GameObject collisionBody, ILogger? logger) { try { ProjectileSystem instance = StaticInstance<ProjectileSystem>.Instance; if ((Object)(object)instance == (Object)null) { if (logger != null) { logger.LogWarning("ProjectileSystem is not up yet; cannot verify the boss layer is in its collision mask."); } return; } int value = ((LayerMask)(ref instance.collisionLayers)).value; string text = LayerMask.LayerToName(collisionBody.layer); bool flag = (value & (1 << collisionBody.layer)) != 0; if (logger != null) { logger.Log($"weapon-damage bound: projectile mask=0x{value:X8}, boss layer '{text}' included={flag}."); } if (!flag && logger != null) { logger.LogWarning("Projectiles do not raycast layer '" + text + "' - bullets will pass through the boss."); } } catch (Exception ex) { if (logger != null) { logger.LogWarning("Projectile layer diagnosis failed: " + ex.Message); } } } } internal sealed class BossAttackReceiver : MonoBehaviour, IAttackReceiver { private IBossDamageSink? _sink; public void Initialize(IBossDamageSink sink) { _sink = sink; } public bool ReceiveAttack(float damage, DamageTypes damageType, DamageSourceData sourceData, Data hitbox, Vector3? collisionPoint = null) { if (_sink == null || float.IsNaN(damage) || damage <= 0f) { return false; } _sink.ApplyWeaponDamage(damage); return true; } } public static class FightingPlayers { private static IPlayerLifeQuery? _lives; public static void AskedOf(IPlayerLifeQuery? lives) { _lives = lives; } public static bool IsFighting(Unit? playerUnit) { if ((Object)(object)playerUnit == (Object)null) { return false; } IPlayerLifeQuery lives = _lives; if (lives == null) { return true; } try { return !lives.IsOutOfTheFight((object)playerUnit); } catch (Exception) { return true; } } public static bool IsFighting(Player? player) { if ((Object)(object)player != (Object)null) { return IsFighting(player.playerUnit); } return false; } public static void FillFighting(List<Unit> into) { if (into == null) { return; } into.Clear(); GameManager instance = StaticInstance<GameManager>.Instance; List<Player> list = (((Object)(object)instance != (Object)null) ? instance.Players : null); if (list == null) { return; } for (int i = 0; i < list.Count; i++) { Player val = list[i]; Unit val2 = (((Object)(object)val != (Object)null) ? val.playerUnit : null); if ((Object)(object)val2 != (Object)null && IsFighting(val)) { into.Add(val2); } } } public static Unit? NearestTo(Vector3 from) { //IL_0065: 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_006b: 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) GameManager instance = StaticInstance<GameManager>.Instance; List<Player> list = (((Object)(object)instance != (Object)null) ? instance.Players : null); if (list == null) { return null; } Unit result = null; float num = float.MaxValue; for (int i = 0; i < list.Count; i++) { Player val = list[i]; Unit val2 = (((Object)(object)val != (Object)null) ? val.playerUnit : null); if (!((Object)(object)val2 == (Object)null) && IsFighting(val)) { Vector3 val3 = ((Component)val2).transform.position - from; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = val2; } } } return result; } } public static class OurDestructibles { private static IDestructibleOwnership? _ownership; public static void ClaimedWith(IDestructibleOwnership? ownership) { _ownership = ownership; } public static void Claim(GameObject? destructible) { if ((Object)(object)destructible == (Object)null) { return; } try { IDestructibleOwnership? ownership = _ownership; if (ownership != null) { ownership.ClaimAsOurs((object)destructible); } } catch (Exception) { } } } public sealed class SulfurBattlefieldCleanup : IBattlefieldCleanupPort { private readonly ILogger? _logger; public SulfurBattlefieldCleanup(ILogger? logger = null) { _logger = logger; } public int SweepCorpses(ArenaWorldPoint around, float radius) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) int result = SweepBodies(new Vector3(((ArenaWorldPoint)(ref around)).X, ((ArenaWorldPoint)(ref around)).Y, ((ArenaWorldPoint)(ref around)).Z), radius); SweepGore(); return result; } private int SweepBodies(Vector3 around, float radius) { //IL_0071: 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_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) UnitManager instance = StaticInstance<UnitManager>.Instance; List<Unit> list = (((Object)(object)instance != (Object)null) ? instance.KilledUnits : null); if (list == null) { return 0; } float num = radius * radius; int num2 = 0; for (int num3 = list.Count - 1; num3 >= 0; num3--) { Unit val = list[num3]; if ((Object)(object)val == (Object)null) { list.RemoveAt(num3); } else if (!val.isPlayer && !val.IsAlive) { Vector3 val2 = ((Component)val).transform.position - around; if (!(((Vector3)(ref val2)).sqrMagnitude > num)) { try { Npc val3 = (Npc)(object)((val is Npc) ? val : null); if (val3 != null) { val3.SinkIntoGroundEndless(); } else { Object.Destroy((Object)(object)((Component)val).gameObject); } list.RemoveAt(num3); num2++; } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[cleanup] a body could not be cleared (" + ex.Message + "); leaving it."); } } } } } return num2; } private void SweepGore() { try { GibSystemNEW instance = StaticInstance<GibSystemNEW>.Instance; if (instance != null) { instance.DeactivateAllGibs(); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[cleanup] the gore could not be cleared (" + ex.Message + ")."); } } } } public sealed class SulfurBossArmPort : IBossArmPort { private const string ArtRootName = "Root"; private const float ThrowRange = 100f; private readonly MonoBehaviour _host; private readonly ILogger? _logger; private readonly List<Unit> _raised = new List<Unit>(); private readonly List<int> _stations = new List<int>(); private readonly List<Transform?> _artRoots = new List<Transform>(); private readonly List<List<Unit>> _quarry = new List<List<Unit>>(); private static readonly List<Unit> EmptyQuarry = new List<Unit>(0); private ArmPlacement _placement; private int _generation; private bool _ours; public int Raised { get { Forget(); return _raised.Count; } } public SulfurBossArmPort(MonoBehaviour host, ILogger? logger = null) { _host = host ?? throw new ArgumentNullException("host"); _logger = logger; } public void Raise(int count, ArmPlacement placement) { //IL_000e: 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_003a: 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_0060: Unknown result type (might be due to invalid IL or missing references) if (count <= 0 || Raised > 0) { return; } UnitSO asset = AssetAccess.GetAsset(UnitIds.GoblinCousinArm); if ((Object)(object)asset == (Object)null) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[arm] the game has no definition for the cousin's arm; the boss rages empty-handed."); } return; } _placement = placement; _ours = true; int generation = ++_generation; for (int i = 0; i < count; i++) { RaiseOne(asset, StandingPoint(placement, i), i, generation); } ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log($"[arm] {count} arm(s) rising at the boss's sides ({((ArmPlacement)(ref placement)).SideDistance:0.#}m out, " + $"{((ArmPlacement)(ref placement)).ForwardOffset:0.#}m forward, {((ArmPlacement)(ref placement)).Lift:0.#}m up, {((ArmPlacement)(ref placement)).Scale:0.##}x); " + "they follow it until it is supplied again."); } } public void Follow(ArmPlacement placement) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) _placement = placement; for (int i = 0; i < _raised.Count; i++) { Put(_raised[i], _artRoots[i], _stations[i], placement); if (_ours) { FightingPlayers.FillFighting(_quarry[i]); } } } public void Adopt(int count) { if (count <= 0 || Raised >= count) { return; } GameManager instance = StaticInstance<GameManager>.Instance; List<Npc> list = (((Object)(object)instance != (Object)null) ? instance.aliveNpcs : null); if (list == null) { return; } ushort value = UnitIds.GoblinCousinArm.value; for (int i = 0; i < list.Count; i++) { if (_raised.Count >= count) { break; } Npc val = list[i]; if (!((Object)(object)val == (Object)null) && ((Unit)val).IsAlive && !((Object)(object)((Unit)val).unitSO == (Object)null) && ((Unit)val).unitSO.id.value == value && !Holding((Unit)(object)val)) { _ours = false; _raised.Add((Unit)(object)val); _stations.Add(_raised.Count - 1); _artRoots.Add(FindArtRoot((Unit)(object)val)); _quarry.Add(EmptyQuarry); } } if (_raised.Count > 0) { ILogger? logger = _logger; if (logger != null) { logger.Log($"[arm] carrying {_raised.Count} arm(s) the session put here; this peer places them " + "itself from now on."); } } } public void Release() { if (_raised.Count != 0) { _generation++; ILogger? logger = _logger; if (logger != null) { logger.Log($"[arm] letting go of {_raised.Count} arm(s); they are the host's to end."); } _raised.Clear(); _stations.Clear(); _artRoots.Clear(); _quarry.Clear(); } } private bool Holding(Unit arm) { for (int i = 0; i < _raised.Count; i++) { if (_raised[i] == arm) { return true; } } return false; } public void LowerAll() { _generation++; int num = 0; for (int i = 0; i < _raised.Count; i++) { Unit val = _raised[i]; if ((Object)(object)val == (Object)null) { continue; } try { val.Die(); num++; } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[arm] an arm could not be taken down (" + ex.Message + "); leaving it."); } } } _raised.Clear(); _stations.Clear(); _artRoots.Clear(); _quarry.Clear(); if (num > 0) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log($"[arm] {num} arm(s) sink back into the ground."); } } } private async void RaiseOne(UnitSO definition, Vector3 position, int station, int generation) { //IL_001e: 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) Unit val; try { val = await definition.SpawnUnitAsync(_host, position, default(Quaternion)); } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[arm] an arm failed to rise: " + ex.Message); } return; } if ((Object)(object)val == (Object)null) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[arm] an arm failed to rise (the game returned no unit)."); } return; } if (generation != _generation) { try { val.Die(); return; } catch (Exception) { return; } } try { val.SetInvulnerable(true); } catch (Exception ex3) { ILogger? logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[arm] an arm could not be made invulnerable (" + ex3.Message + ")."); } } ReachAcrossTheRoom(val); Transform val2 = FindArtRoot(val); List<Unit> list = new List<Unit>(4); FightingPlayers.FillFighting(list); AimWithoutSight(val, list); _raised.Add(val); _stations.Add(station); _artRoots.Add(val2); _quarry.Add(list); Put(val, val2, station, _placement); } private static void Put(Unit? arm, Transform? artRoot, int station, ArmPlacement placement) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) //IL_0074: 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_004f: 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) if (!((Object)(object)arm == (Object)null)) { Transform transform = ((Component)arm).transform; if (((ArmPlacement)(ref placement)).Scale > 0f) { transform.localScale = new Vector3(((ArmPlacement)(ref placement)).Scale, ((ArmPlacement)(ref placement)).Scale, ((ArmPlacement)(ref placement)).Scale); } Vector3 val = Vector3.zero; if ((Object)(object)artRoot != (Object)null) { val = artRoot.position - transform.position; val.y = 0f; } transform.position = StandingPoint(placement, station) - val; } } private void ReachAcrossTheRoom(Unit arm) { try { Npc val = (Npc)(object)((arm is Npc) ? arm : null); if (val != null) { val.rangedAttackRange = 100f; } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[arm] an arm kept its own throwing range (" + ex.Message + "); it will only answer players close to the boss."); } } } private void AimWithoutSight(Unit arm, List<Unit> quarry) { try { Unit obj = ((arm is Npc) ? arm : null); AiAgent val = ((obj != null) ? ((Npc)obj).AiAgent : null); if (!((Object)(object)val == (Object)null)) { val.overridetargets.AddUnits(quarry, (TargetType)2); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[arm] an arm could not be told who to throw at (" + ex.Message + "); it will only answer players it can see."); } } } private static Transform? FindArtRoot(Unit unit) { Transform val = ((Component)unit).transform.Find("Root"); if (!((Object)(object)val != (Object)null)) { return null; } return val; } private static Vector3 StandingPoint(ArmPlacement placement, int station) { //IL_001c: 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) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_006b: 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_007b: 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_008b: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00b6: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) float num = ((station % 2 == 0) ? 1f : (-1f)); int num2 = station / 2 + 1; SimVector2 bossFacing = ((ArmPlacement)(ref placement)).BossFacing; float x = ((SimVector2)(ref bossFacing)).X; bossFacing = ((ArmPlacement)(ref placement)).BossFacing; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(x, 0f, ((SimVector2)(ref bossFacing)).Z); Vector3 val2 = Vector3.right; if (((Vector3)(ref val)).sqrMagnitude > 0.0001f) { val = ((Vector3)(ref val)).normalized; val2 = Vector3.Cross(Vector3.up, val); } else { val = Vector3.forward; } ArenaWorldPoint bossAt = ((ArmPlacement)(ref placement)).BossAt; float x2 = ((ArenaWorldPoint)(ref bossAt)).X; bossAt = ((ArmPlacement)(ref placement)).BossAt; float y = ((ArenaWorldPoint)(ref bossAt)).Y; bossAt = ((ArmPlacement)(ref placement)).BossAt; return new Vector3(x2, y, ((ArenaWorldPoint)(ref bossAt)).Z) + val2 * (num * ((ArmPlacement)(ref placement)).SideDistance * (float)num2) + Vector3.up * ((ArmPlacement)(ref placement)).Lift + val * ((ArmPlacement)(ref placement)).ForwardOffset; } private void Forget() { for (int num = _raised.Count - 1; num >= 0; num--) { Unit val = _raised[num]; if ((Object)(object)val == (Object)null || !val.IsAlive) { _raised.RemoveAt(num); _stations.RemoveAt(num); _artRoots.RemoveAt(num); _quarry.RemoveAt(num); } } } } public sealed class SulfurBossPresence : IBossPresencePort { private const string ArmourFieldName = "armor"; private const string BossBarLabelFieldName = "bossName"; private readonly Func<Collider?> _solidBody; private readonly ILogger? _logger; private GameObject? _listing; private Npc? _npc; private bool _onTheBar; private float _shownHealth = -1f; private OnLanguageChange? _renameOnLanguageChange; public SulfurBossPresence(Func<Collider?> solidBody, ILogger? logger = null) { _solidBody = solidBody ?? throw new ArgumentNullException("solidBody"); _logger = logger; } public void Declare() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_npc != (Object)null) { return; } Collider val = _solidBody(); if ((Object)(object)val == (Object)null) { return; } UnitSO asset; try { asset = AssetAccess.GetAsset(UnitIds.GoblinCousin); } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[presence] the game would not give up a creature definition to borrow (" + ex.Message + "); homing weapons and aim assist will not see the boss."); } return; } if ((Object)(object)asset == (Object)null) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[presence] the game has no cave-boss definition to borrow; homing weapons and aim assist will not see the boss."); } return; } try { _listing = new GameObject("FalseGodsBossPresence"); _listing.transform.SetParent(((Component)val).transform, false); _listing.transform.localPosition = MiddleOf(val); Npc val2 = _listing.AddComponent<Npc>(); ((Unit)val2).unitSO = asset; ((Unit)val2).mainCollider = val; val2.center = _listing.transform; EmptyTheArmour(val2); StaticInstance<GameManager>.Instance.aliveNpcs.Add(val2); _npc = val2; ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log("[presence] the boss is on the game's enemy list: homing weapons follow it and aim assist holds on it. It is listed only - the game does not run it."); } } catch (Exception ex2) { ILogger? logger4 = _logger; if (logger4 != null) { logger4.LogWarning("[presence] the boss could not be listed as an enemy (" + ex2.Message + "); homing weapons and aim assist will not see it."); } Withdraw(); } } public void ShowHealthBar() { Npc npc = _npc; if ((Object)(object)npc == (Object)null || _onTheBar) { return; } try { ((Unit)npc).AttachToBossUI(true); _onTheBar = true; _shownHealth = 1f; NameTheBoss(npc); KeepTheNameInThePlayersLanguage(); ILogger? logger = _logger; if (logger != null) { logger.Log("[boss-bar] the boss is on the game's own boss bar."); } } catch (Exception ex) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[boss-bar] the boss could not be put on the game's boss bar (" + ex.Message + "); the fight runs without it."); } } } public void ReportHealth(float fraction) { Npc npc = _npc; if ((Object)(object)npc == (Object)null || !_onTheBar) { return; } float num = ((fraction < 0f) ? 0f : ((fraction > 1f) ? 1f : fraction)); if (Math.Abs(num - _shownHealth) < 0.0001f) { return; } _shownHealth = num; try { OnHealthChange onHealthChange = ((Unit)npc).onHealthChange; if (onHealthChange != null) { onHealthChange.Invoke(num); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[boss-bar] the boss's health could not be shown (" + ex.Message + ")."); } } } public void HideHealthBar() { Npc npc = _npc; if ((Object)(object)npc == (Object)null || !_onTheBar) { return; } _onTheBar = false; _shownHealth = -1f; StopFollowingTheLanguage(); try { ((Unit)npc).AttachToBossUI(false); } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[boss-bar] the boss could not be taken off the boss bar (" + ex.Message + ")."); } } } private void NameTheBoss(Npc npc) { try { UIManager instance = StaticInstance<UIManager>.Instance; BossHealth val = (((Object)(object)instance != (Object)null) ? instance.bossUI : null); if ((Object)(object)val == (Object)null) { return; } object? obj = typeof(BossHealth).GetField("bossName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val); TMP_Text val2 = (TMP_Text)((obj is TMP_Text) ? obj : null); if ((Object)(object)val2 == (Object)null) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[boss-bar] the bar's 'bossName' is not where it was; the borrowed creature's own name will be shown."); } } else { FalseGodTitle val3 = FalseGodTitle.For(LocalizationManager.CurrentLanguageCode); val2.text = FalseGodTitle.Compose(LocalizationManager.FixRTL_IfNeeded(val3.Word, 0, false), val3.Joiner, ((Unit)npc).GetActorName(), LocalizationManager.IsRight2Left); } } catch (Exception ex) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[boss-bar] the boss's name could not be set (" + ex.Message + ")."); } } } private void KeepTheNameInThePlayersLanguage() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown if (_renameOnLanguageChange != null) { return; } try { AsyncAssetLoading instance = StaticInstance<AsyncAssetLoading>.Instance; if ((Object)(object)instance == (Object)null) { return; } _renameOnLanguageChange = (OnLanguageChange)delegate { Npc npc = _npc; if ((Object)(object)npc != (Object)null && _onTheBar) { NameTheBoss(npc); } }; instance.onLanguageChange = (OnLanguageChange)Delegate.Combine((Delegate?)(object)instance.onLanguageChange, (Delegate?)(object)_renameOnLanguageChange); } catch (Exception ex) { _renameOnLanguageChange = null; ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[boss-bar] the boss's name will not follow a language change (" + ex.Message + ")."); } } } private void StopFollowingTheLanguage() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown OnLanguageChange renameOnLanguageChange = _renameOnLanguageChange; _renameOnLanguageChange = null; if (renameOnLanguageChange == null) { return; } try { AsyncAssetLoading instance = StaticInstance<AsyncAssetLoading>.Instance; if ((Object)(object)instance != (Object)null) { instance.onLanguageChange = (OnLanguageChange)Delegate.Remove((Delegate?)(object)instance.onLanguageChange, (Delegate?)(object)renameOnLanguageChange); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[boss-bar] the boss's rename could not be unsubscribed from language changes (" + ex.Message + ")."); } } } public void Withdraw() { HideHealthBar(); StopFollowingTheLanguage(); Npc npc = _npc; _npc = null; if ((Object)(object)npc != (Object)null) { try { GameManager instance = StaticInstance<GameManager>.Instance; if (instance != null) { instance.aliveNpcs.Remove(npc); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[presence] the boss could not be taken off the enemy list (" + ex.Message + ")."); } } } if ((Object)(object)_listing != (Object)null) { try { Object.Destroy((Object)(object)_listing); } catch (Exception) { } _listing = null; } } private static Vector3 MiddleOf(Collider body) { //IL_0022: 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_0014: Unknown result type (might be due to invalid IL or missing references) CapsuleCollider val = (CapsuleCollider)(object)((body is CapsuleCollider) ? body : null); if (val == null) { BoxCollider val2 = (BoxCollider)(object)((body is BoxCollider) ? body : null); if (val2 == null) { return Vector3.zero; } return val2.center; } return val.center; } private void EmptyTheArmour(Npc npc) { try { FieldInfo field = typeof(Unit).GetField("armor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Type type = field?.FieldType.GetElementType(); if (field != null && type != null && field.GetValue(npc) == null) { field.SetValue(npc, Array.CreateInstance(type, 0)); } } catch (Exception ex) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[presence] the listing's armour could not be emptied (" + ex.Message + ")."); } } } } public sealed class SulfurBossReward : IBossRewardPort { private const int Draws = 2; private const int Money = 2500; private static readonly (ItemId Item, float Weight)[] Table = new(ItemId, float)[42] { (ItemIds.Weapon_Gravekeeper, 20f), (ItemIds.Weapon_Mario, 20f), (ItemIds.Weapon_Termite, 20f), (ItemIds.Weapon_Knop, 20f), (ItemIds.Weapon_Bronco, 20f), (ItemIds.Weapon_Mossman, 20f), (ItemIds.Weapon_Beck, 20f), (ItemIds.Weapon_Breacher8, 20f), (ItemIds.Weapon_Socom9, 20f), (ItemIds.Weapon_WyattPulsar, 30f), (ItemIds.Weapon_FlickerZip, 30f), (ItemIds.Weapon_StarAndWitness, 30f), (ItemIds.Weapon_Augusta, 30f), (ItemIds.Weapon_PalehorseTopclipper, 30f), (ItemIds.Weapon_Vrede, 30f), (ItemIds.Weapon_Balthazar, 30f), (ItemIds.Weapon_D4RT, 30f), (ItemIds.Weapon_DeathStar, 30f), (ItemIds.Weapon_Dolphin99, 30f), (ItemIds.Weapon_ImpalaGravita, 30f), (ItemIds.Weapon_Flock, 30f), (ItemIds.Weapon_Nunchaku, 30f), (ItemIds.Weapon_TailorMarksman, 30f), (ItemIds.Weapon_Sai, 40f), (ItemIds.Weapon_Bo, 40f), (ItemIds.Weapon_Corpsemaker, 40f), (ItemIds.Weapon_Katana, 40f), (ItemIds.Weapon_Valet, 40f), (ItemIds.Item_CryptKey, 40f), (ItemIds.Weapon_NeuraxisF22, 40f), (ItemIds.Weapon_PierreFusil, 40f), (ItemIds.Weapon_Salamander, 40f), (ItemIds.Weapon_Typhoon, 40f), (ItemIds.Weapon_Rokua, 18f), (ItemIds.Weapon_M11Ramshack, 18f), (ItemIds.Weapon_Catacoil, 18f), (ItemIds.Weapon_Duhar, 18f), (ItemIds.Weapon_Majordome, 18f), (ItemIds.Weapon_Rektor, 18f), (ItemIds.Weapon_Ferryman, 18f), (ItemIds.Attachment_Insurance, 18f), (ItemIds.Manual_GoblinCooking, 18f) }; private readonly ILogger? _logger; public SulfurBossReward(ILogger? logger = null) { _logger = logger; } public void DropReward(ArenaWorldPoint at) { //IL_0072: 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_00a0: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y, ((ArenaWorldPoint)(ref at)).Z); try { LootManager instance = StaticInstance<LootManager>.Instance; if ((Object)(object)instance == (Object)null) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[reward] the game has no loot manager to pay through; nothing dropped."); } return; } int missing; LootTable val2 = BuildTable(out missing); if ((Object)(object)val2 == (Object)null) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[reward] not one item of the boss's table could be resolved; nothing dropped. The item database is loaded on demand, so this means it was asked too early."); } return; } Room val3 = Room.FindClosestRoom(val, (Room)null, 3f); for (int i = 0; i < 2; i++) { instance.SpawnLootFrom(val2, val, val3); } instance.SpawnMoney(2500, val, val3); ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log($"[reward] the boss pays out: {2} draw(s) from a table of " + $"{val2.entries.Count} and {2500} in money" + ((missing > 0) ? $" ({missing} item(s) this build does not have were left out)" : string.Empty) + ". This peer rolled its own."); } } catch (Exception ex) { ILogger? logger4 = _logger; if (logger4 != null) { logger4.LogWarning("[reward] the boss's payout failed (" + ex.Message + "); nothing dropped."); } } } private static LootTable? BuildTable(out int missing) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) missing = 0; LootTable val = ScriptableObject.CreateInstance<LootTable>(); val.entries = new List<LootEntry>(Table.Length); for (int i = 0; i < Table.Length; i++) { ItemDefinition asset = AssetAccess.GetAsset(Table[i].Item); if ((Object)(object)asset == (Object)null) { missing++; } else { val.AddEntry(asset, Table[i].Weight); } } if (val.entries.Count <= 0) { return null; } return val; } } public sealed class SulfurCarriedLoadMirror { private sealed class Load { private readonly List<GameObject> _drawn = new List<GameObject>(); public Unit Goblin { get; } public int Shown => _drawn.Count; public Load(Unit goblin) { Goblin = goblin; } public void Show(int crates, Mesh look, Material lookMaterial) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown if ((Object)(object)Goblin == (Object)null) { return; } while (_drawn.Count < crates) { GameObject val; if ((Object)(object)look != (Object)null && (Object)(object)lookMaterial != (Object)null) { val = new GameObject("FalseGods_CarriedCrate"); val.AddComponent<MeshFilter>().sharedMesh = look; ((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = lookMaterial; } else { val = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)val).name = "FalseGods_CarriedCrate"; Collider component = val.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } val.transform.SetParent(((Component)Goblin).transform, false); val.transform.localScale = Vector3.one * 0.5f; val.transform.localPosition = new Vector3(0f, 1.9f + (float)_drawn.Count * 0.55f, 0f); _drawn.Add(val); } } public void Clear() { for (int i = 0; i < _drawn.Count; i++) { if ((Object)(object)_drawn[i] != (Object)null) { Object.Destroy((Object)(object)_drawn[i]); } } _drawn.Clear(); } } private const float MatchRadius = 8f; private const float StackSpacing = 0.55f; private const float StackBase = 1.9f; private const int MaxDrawnStack = 5; private readonly SulfurThrownCratePort _crates; private readonly ILogger _logger; private readonly List<Load> _loads = new List<Load>(); public SulfurCarriedLoadMirror(SulfurThrownCratePort crates, ILogger logger = null) { _crates = crates ?? throw new ArgumentNullException("crates"); _logger = logger; } public void PickedUp(ArenaWorldPoint at, int count) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) Forget(); if (count <= 0) { return; } Unit val = NearestCivilianTo(new Vector3(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y, ((ArenaWorldPoint)(ref at)).Z)); if (!((Object)(object)val == (Object)null)) { Load load = Find(val); if (load == null) { load = new Load(val); _loads.Add(load); } _crates.TryGetLook(out var mesh, out var material); load.Show(Math.Min(count + load.Shown, 5), mesh, material); } } public void PutDown(ArenaWorldPoint from) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) Forget(); Unit val = NearestCivilianTo(new Vector3(((ArenaWorldPoint)(ref from)).X, ((ArenaWorldPoint)(ref from)).Y, ((ArenaWorldPoint)(ref from)).Z)); if (!((Object)(object)val == (Object)null)) { Find(val)?.Clear(); } } public void Clear() { for (int i = 0; i < _loads.Count; i++) { _loads[i].Clear(); } _loads.Clear(); } private Load Find(Unit goblin) { for (int i = 0; i < _loads.Count; i++) { if (_loads[i].Goblin == goblin) { return _loads[i]; } } return null; } private void Forget() { for (int num = _loads.Count - 1; num >= 0; num--) { if ((Object)(object)_loads[num].Goblin == (Object)null || !_loads[num].Goblin.IsAlive) { _loads[num].Clear(); _loads.RemoveAt(num); } } } private static Unit NearestCivilianTo(Vector3 point) { //IL_0058: 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_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) GameManager instance = StaticInstance<GameManager>.Instance; List<Npc> list = (((Object)(object)instance != (Object)null) ? instance.aliveNpcs : null); if (list == null) { return null; } Unit result = null; float num = 64f; for (int i = 0; i < list.Count; i++) { Npc val = list[i]; if (!((Object)(object)val == (Object)null) && ((Unit)val).IsAlive && ((Unit)val).IsCivilian) { Vector3 val2 = ((Component)val).transform.position - point; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = (Unit)(object)val; } } } return result; } } public sealed class SulfurCarrierPort : ICarrierPort { private enum Leg { ToSource, ToPile } private sealed class Carrier { private readonly List<GameObject> _drawn = new List<GameObject>(); private readonly List<SulfurThrownCratePort.CrateLook> _carried = new List<SulfurThrownCratePort.CrateLook>(); public int ExplosivesHeld { get { int num = 0; for (int i = 0; i < _carried.Count; i++) { if (_carried[i].Explosive) { num++; } } return num; } } public Unit Unit { get; } public Npc Npc { get; } public Leg Leg { get; set; } public int SourceIndex { get; set; } public int Load { get; set; } public ArenaWorldPoint Fetch { get; set; } public CratePileId FetchPile { get; set; } public bool Aimed { get; set; } public float OnLeg { get; set; } public float Handling { get; set; } public float Waited { get; set; } public Vector3 Destination { get; set; } public Vector3 LastPosition { get; set; } public Vector3 StillSince { get; set; } public float Still { get; set; } public Carrier(Unit unit, int sourceIndex) { //IL_0054: 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) Unit = unit; Npc = (Npc)(object)((unit is Npc) ? unit : null); SourceIndex = sourceIndex; Leg = Leg.ToSource; LastPosition = (((Object)(object)unit != (Object)null) ? ((Component)unit).transform.position : Vector3.zero); } public void Shoulder(List<SulfurThrownCratePort.CrateLook> picked, int took) { for (int i = 0; i < picked.Count && i < took; i++) { _carried.Add(picked[i]); } while (_carried.Count < Load) { _carried.Add((_carried.Count > 0) ? _carried[_carried.Count - 1] : default(SulfurThrownCratePort.CrateLook)); } Redraw(); } public void DrawLoad() { if (!((Object)(object)Unit == (Object)null)) { Redraw(); } } private void Redraw() { int num = Math.Min(Load, 5); while (_drawn.Count > num) { GameObject val = _drawn[_drawn.Count - 1]; _drawn.RemoveAt(_drawn.Count - 1); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } while (_drawn.Count < num) { _drawn.Add(MakeOne(((Component)Unit).transform, _drawn.Count, LookAt(_drawn.Count, num))); } } private SulfurThrownCratePort.CrateLook LookAt(int place, int drawn) { if (place >= _carried.Count) { return default(SulfurThrownCratePort.CrateLook); } if (place == drawn - 1 && _carried.Count > drawn && ExplosivesHeld > 0 && !AnyExplosiveWithin(drawn - 1)) { return FirstExplosive(); } return _carried[place]; } private bool AnyExplosiveWithin(int places) { for (int i = 0; i < places && i < _carried.Count; i++) { if (_carried[i].Explosive) { return true; } } return false; } private SulfurThrownCratePort.CrateLook FirstExplosive() { for (int i = 0; i < _carried.Count; i++) { if (_carried[i].Explosive) { return _carried[i]; } } return default(SulfurThrownCratePort.CrateLook); } private static GameObject MakeOne(Transform on, int place, SulfurThrownCratePort.CrateLook look) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0075: 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_00a7: Unknown result type (might be due to invalid IL or missing references) GameObject val; if (look.Known) { val = new GameObject("FalseGods_CarriedCrate"); val.AddComponent<MeshFilter>().sharedMesh = look.Mesh; ((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = look.Material; } else { val = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)val).name = "FalseGods_CarriedCrate"; Collider component = val.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } val.transform.SetParent(on, false); val.transform.localScale = Vector3.one * 0.5f; val.transform.localPosition = new Vector3(0f, 1.9f + (float)place * 0.55f, 0f); return val; } public void ClearDrawnLoad() { _carried.Clear(); for (int i = 0; i < _drawn.Count; i++) { if ((Object)(object)_drawn[i] != (Object)null) { Object.Destroy((Object)(object)_drawn[i]); } } _drawn.Clear(); } } private static readonly UnitId CarrierUnit = UnitIds.GoblinCivilian; private const float ArrivalRadius = 2.5f; private const float LegTimeoutSeconds = 45f; private const float HandlingSeconds = 0.75f; private const float StackSpacing = 0.55f; private const float StackBase = 1.9f; private const float SetDownMinRadius = 1.2f; private const float SetDownMaxRadius = 4f; private const float SetDownHeight = 1.2f; private const float SetDownFlightSeconds = 0.55f; private const float SetDownApexHeight = 1.6f; private const float PickUpReach = 9f; private const float StillTooLongSeconds = 5f; private const float StillEnough = 0.05f; private const int MaxDrawnStack = 5; private readonly MonoBehaviour _host; private readonly IThrownCratePort _crates; private readonly ILogger _logger; private readonly Action<ArenaWorldPoint, CratePileId, int, float> _announceTaken; private readonly Action<ArenaWorldPoint, ArenaWorldPoint, CratePileId, int, int, int> _announceSetDown; private readonly List<Carrier> _carriers = new List<Carrier>(); private bool _reportedDeactivationTrap; private bool _pending; private readonly List<SulfurThrownCratePort.CrateLook> _justPickedUp = new List<SulfurThrownCratePort.CrateLook>(); private readonly List<ArenaWorldPoint> _claimedHeaps = new List<ArenaWorldPoint>(); private float _routeClock; private float _replaceAfterSeconds; private readonly List<float> _mourning = new List<float>(); private int _nextSetDownSeed = 1; private float _observedWalkSpeed; public int Working { get { Forget(); return _carriers.Count; } } public float ObservedWalkSpeed => _observedWalkSpeed; public int Carried { get { Forget(); int num = 0; for (int i = 0; i < _carriers.Count; i++) { num += _carriers[i].Load; } return num; } } public SulfurCarrierPort(MonoBehaviour host, IThrownCratePort crates, ILogger logger = null, Action<ArenaWorldPoint, CratePileId, int, float> announceTaken = null, Action<ArenaWorldPoint, ArenaWorldPoint, CratePileId, int, int, int> announceSetDown = null) { _host = host ?? throw new ArgumentNullException("host"); _crates = crates ?? throw new ArgumentNullException("crates"); _logger = logger; _announceTaken = announceTaken; _announceSetDown = announceSetDown; } public void Warm(ArenaWorldPoint at) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) MakeOneAndThrowItAway(at); } private async void MakeOneAndThrowItAway(ArenaWorldPoint at) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) try { UnitSO asset = AssetAccess.GetAsset(CarrierUnit); if ((Object)(object)asset == (Object)null) { return; } Unit val = await asset.SpawnUnitAsync(_host, new Vector3(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y, ((ArenaWorldPoint)(ref at)).Z), default(Quaternion)); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); ILogger logger = _logger; if (logger != null) { logger.Log("[carrier] one villager was made and dismissed while the level was still loading, so the first of the route is not the first ever built."); } } } catch (Exception ex) { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[carrier] the village could not be warmed ahead of time (" + ex.Message + "); the first carrier will pay for it instead."); } } } public void Advance(float deltaSeconds, int wanted, int loadPerCarrier, float replaceAfterSeconds, IReadOnlyList<ArenaWorldPoint> sources, ArenaWorldPoint deliverTo, CratePileId deliverPile) { //IL_004f: 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) _routeClock += deltaSeconds; _replaceAfterSeconds = replaceAfterSeconds; Forget(); if (sources != null && sources.Count != 0) { PutOnTheRoute(wanted, sources); TakeOffTheRoute(wanted); for (int i = 0; i < _carriers.Count; i++) { Advance(_carriers[i], deltaSeconds, loadPerCarrier, sources, deliverTo, deliverPile); } } } public void DismissAll() { int num = 0; for (int i = 0; i < _carriers.Count; i++) { if (Remove(_carriers[i], spillLoad: false)) { num++; } } _carriers.Clear(); _mourning.Clear(); if (num > 0) { ILogger logger = _logger; if (logger != null) { logger.Log($"[carrier] {num} carrier(s) taken off the route with the encounter."); } } } public void Disband() { int num = 0; int num2 = 0; for (int i = 0; i < _carriers.Count; i++) { Carrier carrier = _carriers[i]; num2 += DropWhatItIsHolding(carrier); carrier.ClearDrawnLoad(); if (SendBackToItsOwnLife(carrier)) { num++; } } _carriers.Clear(); _mourning.Clear(); if (num > 0 || num2 > 0) { ILogger logger = _logger; if (logger != null) { logger.Log($"[carrier] the errand is over: {num} villager(s) went back to their own lives, " + $"{num2} crate(s) put down where they stood."); } } } private bool SendBackToItsOwnLife(Carrier carrier) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) Npc npc = carrier.Npc; if ((Object)(object)npc == (Object)null || (Object)(object)carrier.Unit == (Object)null) { return false; } try { npc.SetForcedDestination(Vector3.zero); npc.ActivateBehaviourTree(); return true; } catch (Exception ex) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[carrier] a villager could not be given its own behaviour back (" + ex.Message + "); it will stand where it is."); } return false; } } private int DropWhatItIsHolding(Carrier carrier) { //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_0020: 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_0036: 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_0048: Unknown result type (might be due to invalid IL or missing references) if (carrier.Load <= 0 || carrier.LastPosition == Vector3.zero) { return 0; } ArenaWorldPoint at = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref at))..ctor(carrier.LastPosition.x, carrier.LastPosition.y, carrier.LastPosition.z); int result = TossLoadAround(carrier, at, CratePileId.Loose); carrier.Load = 0; return result; } private void Advance(Carrier carrier, float deltaSeconds, int loadPerCarrier, IReadOnlyList<ArenaWorldPoint> sources, ArenaWorldPoint deliverTo, CratePileId deliverPile) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: 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_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: 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_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Invalid comparison between Unknown and I4 //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) carrier.OnLeg += deltaSeconds; carrier.DrawLoad(); if (HasSeizedUp(carrier, deltaSeconds)) { PutBackOnTheRoute(carrier, sources); return; } switch (carrier.Leg) { case Leg.ToSource: { if (!carrier.Aimed) { AimAtSomethingToFetch(carrier, sources); Begin(carrier, Leg.ToSource, carrier.Fetch); carrier.Aimed = true; break; } if (!HasArrived(carrier, carrier.Fetch)) { RepeatIfStuck(carrier, carrier.Fetch); break; } carrier.Handling += deltaSeconds; if (carrier.Handling < 0.75f) { break; } int num = loadPerCarrier - carrier.Load; if (num > 0) { Vector3 val = (((Object)(object)carrier.Unit != (Object)null) ? ((Component)carrier.Unit).transform.position : carrier.LastPosition); ArenaWorldPoint val2 = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref val2))..ctor(val.x, val.y, val.z); _justPickedUp.Clear(); int num2 = ((_crates is SulfurThrownCratePort sulfurThrownCratePort) ? sulfurThrownCratePort.TakeFrom(carrier.FetchPile, num, val2, 9f, _justPickedUp) : _crates.TakeFrom(carrier.FetchPile, num, val2, 9f)); if (num2 > 0) { carrier.Load += num2; carrier.Shoulder(_justPickedUp, num2); _announceTaken?.Invoke(val2, carrier.FetchPile, num2, 9f); } } if (carrier.Load <= 0) { AimAtSomethingToFetch(carrier, sources); Begin(carrier, Leg.ToSource, carrier.Fetch); break; } if (carrier.Load < loadPerCarrier) { CratePileId fetchPile = carrier.FetchPile; if ((int)((CratePileId)(ref fetchPile)).Kind == 1 && carrier.Waited < 3f) { carrier.Waited += deltaSeconds; break; } } Begin(carrier, Leg.ToPile, deliverTo); break; } case Leg.ToPile: if (!HasArrived(carrier, deliverTo)) { Retarget(carrier, deliverTo); RepeatIfStuck(carrier, deliverTo); break; } carrier.Handling += deltaSeconds; if (!(carrier.Handling < 0.75f)) { SetDown(carrier, deliverTo, deliverPile); carrier.SourceIndex++; AimAtSomethingToFetch(carrier, sources); Begin(carrier, Leg.ToSource, carrier.Fetch); } break; } } private void AimAtSomethingToFetch(Carrier carrier, IReadOnlyList<ArenaWorldPoint> sources) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_0053: 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_0058: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) ArenaWorldPoint fetch = sources[carrier.SourceIndex % sources.Count]; carrier.Fetch = fetch; carrier.FetchPile = CratePileId.Source(carrier.SourceIndex % sources.Count); Vector3 val = (((Object)(object)carrier.Unit != (Object)null) ? ((Component)carrier.Unit).transform.position : Vector3.zero); ArenaWorldPoint val2 = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref val2))..ctor(val.x, val.y, val.z); ArenaWorldPoint fetch2 = default(ArenaWorldPoint); if (_crates.TryFindNearestResting(CratePileId.Loose, val2, ref fetch2, HeapsBeingCollected(carrier), 9f)) { carrier.Fetch = fetch2; carrier.FetchPile = CratePileId.Loose; } } private IReadOnlyList<ArenaWorldPoint> HeapsBeingCollected(Carrier except) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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) _claimedHeaps.Clear(); for (int i = 0; i < _carriers.Count; i++) { Carrier carrier = _carriers[i]; if (carrier != except && carrier.Aimed && carrier.Leg == Leg.ToSource) { CratePileId fetchPile = carrier.FetchPile; if ((int)((CratePileId)(ref fetchPile)).Kind == 0) { _claimedHeaps.Add(carrier.Fetch); } } } return _claimedHeaps; } private int TossLoadAround(Carrier carrier, ArenaWorldPoint at, CratePileId pile) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0076: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) int load = carrier.Load; if (load <= 0) { return 0; } Vector3 val = (((Object)(object)carrier.Unit != (Object)null) ? ((Component)carrier.Unit).transform.position : carrier.LastPosition); ArenaWorldPoint val2 = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref val2))..ctor(val.x, val.y + 1.9f, val.z); int num = _nextSetDownSeed++; int explosivesHeld = carrier.ExplosivesHeld; int result = _crates.TossRing(val2, at, pile, load, num, explosivesHeld); Action<ArenaWorldPoint, ArenaWorldPoint, CratePileId, int, int, int> announceSetDown = _announceSetDown; if (announceSetDown != null) { announceSetDown(val2, at, pile, load, num, explosivesHeld); return result; } return result; } private static bool HasSeizedUp(Carrier carrier, float deltaSeconds) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might
FalseGods.Integration.SulfurTogether.dll
Decompiled 9 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using FalseGods.Integration.SulfurTogether.Diagnostics; using FalseGods.RuntimeContracts.Diagnostics; using FalseGods.RuntimeContracts.Integration; using FalseGods.RuntimeContracts.Multiplayer; using FalseGods.RuntimeContracts.Transport; using Microsoft.CodeAnalysis; using SULFURTogether.Api; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FalseGods.Integration.SulfurTogether")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6e5740a80f810ab422551028733810b527fb614d")] [assembly: AssemblyProduct("FalseGods.Integration.SulfurTogether")] [assembly: AssemblyTitle("FalseGods.Integration.SulfurTogether")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FalseGods.Integration.SulfurTogether { internal sealed class StDestructibleOwnership : IDestructibleOwnership { private readonly ILogger? _logger; private bool _unavailable; public StDestructibleOwnership(ILogger? logger = null) { _logger = logger; } public void ClaimAsOurs(object destructible) { if (_unavailable) { return; } object obj = ((destructible is GameObject) ? destructible : null); if (obj == null) { object obj2 = ((destructible is Component) ? destructible : null); obj = ((obj2 != null) ? ((Component)obj2).gameObject : null); } GameObject val = (GameObject)obj; if ((Object)(object)val == (Object)null) { return; } try { NetExternalDestructibles.Exclude(val); } catch (Exception ex) { _unavailable = true; ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[st-destructibles] the session layer would not take the claim (" + ex.Message + "); it will keep mirroring our crates, which can break the wrong one."); } } } } internal sealed class StEncounterChannel : IEncounterChannel, IDisposable { public const string ChannelId = "false_gods.encounter"; private readonly StPeerDirectory _peers; private readonly ILogger _logger; private IDisposable? _registration; public event Action<SessionPeerId, EncodedPayload>? Received; public StEncounterChannel(StPeerDirectory peers, ILogger logger) { _peers = peers ?? throw new ArgumentNullException("peers"); _logger = logger ?? throw new ArgumentNullException("logger"); } public bool TryRegister() { if (_registration != null) { return true; } try { _registration = (IDisposable?)NetExternalChannel.Register("false_gods.encounter", (Action<string, byte[]>)OnBridgePayload); _logger.Log(string.Format("Encounter channel '{0}' registered on the ST bridge (API v{1}).", "false_gods.encounter", 1)); return true; } catch (InvalidOperationException ex) { _logger.LogWarning("Encounter channel 'false_gods.encounter' is already registered with the ST bridge: " + ex.Message); return false; } } public void Send(EncodedPayload payload, MessageDelivery delivery, MessageTarget target) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0052: 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_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_001c: 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_007d: 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) byte[] array = ((EncodedPayload)(ref payload)).ToArray(); string bridgePeerId = null; if ((int)((MessageTarget)(ref target)).Kind == 2 && !_peers.TryGetBridgeId(((MessageTarget)(ref target)).Peer, out bridgePeerId)) { _logger.LogWarning($"Dropping a send to unknown {((MessageTarget)(ref target)).Peer}: no bridge id is mapped for it."); } else if (!NetExternalChannel.Send("false_gods.encounter", array, MapDelivery(delivery), MapTarget(((MessageTarget)(ref target)).Kind), bridgePeerId)) { _logger.LogWarning($"Bridge refused a {delivery} send to {target} ({array.Length} bytes)."); } } public void Dispose() { try { _registration?.Dispose(); } catch (Exception ex) { _logger.LogWarning("Encounter channel unregister failed: " + ex.Message); } _registration = null; } private void OnBridgePayload(string senderBridgeId, byte[] payload) { //IL_002e: 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) if (string.IsNullOrEmpty(senderBridgeId) || payload == null) { _logger.LogWarning("Dropping a bridge payload with no sender id or no body."); } else { this.Received?.Invoke(_peers.Map(senderBridgeId), new EncodedPayload(payload)); } } private static ExternalDelivery MapDelivery(MessageDelivery delivery) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)delivery == 1) { return (ExternalDelivery)1; } return (ExternalDelivery)0; } private static ExternalTarget MapTarget(MessageTargetKind kind) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected I4, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) return (ExternalTarget)((int)kind switch { 0 => 0, 1 => 1, 2 => 2, _ => throw new ArgumentOutOfRangeException("kind", kind, "Unknown message target kind."), }); } } internal sealed class StMultiplayerSession : IMultiplayerSession { private readonly StPeerDirectory _peers; public SessionRole Role => ReadRole(); public bool IsActive => ReadIsActive(); public SessionPeerId LocalPeer => ReadLocalPeer(); public SessionPeerId HostPeer => ReadHostPeer(); public StMultiplayerSession(StPeerDirectory peers) { _peers = peers ?? throw new ArgumentNullException("peers"); } private static SessionRole ReadRole() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)NetSessionInfo.Role == 1) { return (SessionRole)0; } return (SessionRole)1; } private static bool ReadIsActive() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if (NetSessionInfo.IsSessionActive) { return (int)NetSessionInfo.Role > 0; } return false; } private SessionPeerId ReadLocalPeer() { //IL_001d: 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_0015: Unknown result type (might be due to invalid IL or missing references) string localPeerId = NetSessionInfo.LocalPeerId; if (!string.IsNullOrEmpty(localPeerId)) { return _peers.Map(localPeerId); } return default(SessionPeerId); } private SessionPeerId ReadHostPeer() { //IL_000c: 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_005b: 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_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_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_0046: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<ExternalPeer> peers = NetSessionInfo.Peers; for (int i = 0; i < peers.Count; i++) { ExternalPeer val = peers[i]; if (((ExternalPeer)(ref val)).IsHost) { val = peers[i]; if (!string.IsNullOrEmpty(((ExternalPeer)(ref val)).PeerId)) { StPeerDirectory peers2 = _peers; val = peers[i]; return peers2.Map(((ExternalPeer)(ref val)).PeerId); } } } return default(SessionPeerId); } } internal sealed class StParticipantPeerMap : IParticipantPeerMap { private readonly StPeerDirectory _peers; public StParticipantPeerMap(StPeerDirectory peers) { _peers = peers ?? throw new ArgumentNullException("peers"); } public bool TryGetRemotePeer(int participantIndex, out SessionPeerId peer) { //IL_000c: 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_0067: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<ExternalPeer> peers = NetSessionInfo.Peers; for (int i = 0; i < peers.Count; i++) { ExternalPeer val = peers[i]; if (((ExternalPeer)(ref val)).IsLocal) { continue; } val = peers[i]; if (((ExternalPeer)(ref val)).PlayerIndex == participantIndex) { val = peers[i]; string peerId = ((ExternalPeer)(ref val)).PeerId; if (!string.IsNullOrEmpty(peerId)) { peer = _peers.Map(peerId); return true; } } } peer = default(SessionPeerId); return false; } } internal sealed class StPeerDirectory { private readonly Dictionary<string, SessionPeerId> _byBridgeId = new Dictionary<string, SessionPeerId>(StringComparer.Ordinal); private readonly Dictionary<SessionPeerId, string> _byPeer = new Dictionary<SessionPeerId, string>(); private int _next = 1; public SessionPeerId Map(string bridgePeerId) { //IL_005a: 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_0053: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(bridgePeerId)) { throw new ArgumentException("A bridge peer id must be non-empty.", "bridgePeerId"); } if (!_byBridgeId.TryGetValue(bridgePeerId, out var value)) { ((SessionPeerId)(ref value))..ctor(_next++); _byBridgeId.Add(bridgePeerId, value); _byPeer.Add(value, bridgePeerId); } return value; } public bool TryGetBridgeId(SessionPeerId peer, out string bridgePeerId) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return _byPeer.TryGetValue(peer, out bridgePeerId); } } internal sealed class StPlayerLifeQuery : IPlayerLifeQuery { private readonly ILogger? _logger; private bool _unavailable; public StPlayerLifeQuery(ILogger? logger = null) { _logger = logger; } public bool IsOutOfTheFight(object playerUnit) { if (playerUnit == null || _unavailable) { return false; } try { return NetPlayerLife.IsOutOfTheFight(playerUnit); } catch (Exception ex) { _unavailable = true; ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[st-life] the session layer cannot say who is down (" + ex.Message + "); the boss will treat every player as still fighting."); } return false; } } } internal sealed class StPlayerRoster : IPlayerRoster { private readonly StPeerDirectory _peers; public IReadOnlyList<SessionPeerId> Members => ReadMembers(); public StPlayerRoster(StPeerDirectory peers) { _peers = peers ?? throw new ArgumentNullException("peers"); } private IReadOnlyList<SessionPeerId> ReadMembers() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) List<SessionPeerId> list = new List<SessionPeerId>(); IReadOnlyList<ExternalPeer> peers = NetSessionInfo.Peers; for (int i = 0; i < peers.Count; i++) { ExternalPeer val = peers[i]; string peerId = ((ExternalPeer)(ref val)).PeerId; if (!string.IsNullOrEmpty(peerId)) { list.Add(_peers.Map(peerId)); } } return list; } } internal sealed class StSpawnOwnership : ISpawnOwnership { private readonly ILogger? _logger; public StSpawnOwnership(ILogger? logger = null) { _logger = logger; } public IDisposable? DeclareHostAuthoritative(object spawnOwner) { MonoBehaviour val = (MonoBehaviour)((spawnOwner is MonoBehaviour) ? spawnOwner : null); if (val == null) { ILogger? logger = _logger; if (logger != null) { logger.LogWarning("[st-spawns] a spawn owner that is not a game component cannot be declared; runtime spawns will stay host-only."); } return null; } try { IExternalSpawnOwnerRegistration result = NetExternalSpawns.RegisterHostAuthoritativeOwner(val); ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log("[st-spawns] '" + ((object)val).GetType().Name + "' declared host-authoritative; its runtime spawns are mirrored to clients as host-driven puppets."); } return (IDisposable?)result; } catch (Exception ex) { ILogger? logger3 = _logger; if (logger3 != null) { logger3.LogWarning("[st-spawns] the session layer would not take the declaration (" + ex.Message + "); runtime spawns will stay host-only."); } return null; } } } internal sealed class SulfurTogetherIntegration : IFalseGodsIntegration { public IMultiplayerSession Session { get; } public IEncounterChannel Channel { get; } public IPlayerRoster Roster { get; } public IParticipantPeerMap Players { get; } public ISpawnOwnership Spawns { get; } public IPlayerLifeQuery Lives { get; } public IDestructibleOwnership Destructibles { get; } public SulfurTogetherIntegration(IMultiplayerSession session, IEncounterChannel channel, IPlayerRoster roster, IParticipantPeerMap players, ISpawnOwnership spawns, IPlayerLifeQuery lives, IDestructibleOwnership destructibles) { Session = session ?? throw new ArgumentNullException("session"); Channel = channel ?? throw new ArgumentNullException("channel"); Roster = roster ?? throw new ArgumentNullException("roster"); Players = players ?? throw new ArgumentNullException("players"); Spawns = spawns ?? throw new ArgumentNullException("spawns"); Lives = lives ?? throw new ArgumentNullException("lives"); Destructibles = destructibles ?? throw new ArgumentNullException("destructibles"); } } [BepInPlugin("ryuka.sulfur.false_gods_sulfur_together", "False Gods - SULFUR Together Adapter", "0.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class SulfurTogetherPlugin : BaseUnityPlugin { public const string PluginGuid = "ryuka.sulfur.false_gods_sulfur_together"; public const string PluginName = "False Gods - SULFUR Together Adapter"; public const string PluginVersion = "0.4.0"; private const string BasePluginGuid = "ryuka.sulfur.false_gods"; private const string SulfurTogetherGuid = "com.ryuka.sulfur.together"; private ILogger _log; private StEncounterChannel? _channel; private SulfurTogetherIntegration? _integration; private IIntegrationRegistration? _token; private void Awake() { _log = (ILogger)(object)new BepInExLogger(((BaseUnityPlugin)this).Logger); ((BaseUnityPlugin)this).Logger.LogMessage((object)"False Gods - SULFUR Together Adapter 0.4.0 loaded."); TryCompose("plugin load"); } private void OnDestroy() { Revoke(); _channel?.Dispose(); _channel = null; } private void TryCompose(string trigger) { if (EnsureComposed()) { IIntegrationRegistration val = FalseGodsIntegrations.Register((IFalseGodsIntegration)(object)_integration); if (val != null) { _token = val; _log.Log("Multiplayer integration registered with the base plugin (" + trigger + ")."); } else if (_token != null) { _log.Log("Broker rejected the duplicate registration (" + trigger + "); the first registration stays authoritative."); } else { _log.LogWarning("Multiplayer integration already provided by someone else (" + trigger + "); staying inert."); } } } private void Revoke() { if (_token != null) { ((IDisposable)_token).Dispose(); _token = null; _log.Log("Registration token disposed; the base plugin falls back to the single-player composition."); } } private bool EnsureComposed() { if (_integration != null) { return true; } try { string text = DescribeBridge(); StPeerDirectory peers = new StPeerDirectory(); StEncounterChannel stEncounterChannel = new StEncounterChannel(peers, _log); if (!stEncounterChannel.TryRegister()) { _log.LogWarning("Encounter channel registration refused; multiplayer unavailable."); return false; } _channel = stEncounterChannel; _integration = new SulfurTogetherIntegration((IMultiplayerSession)(object)new StMultiplayerSession(peers), (IEncounterChannel)(object)stEncounterChannel, (IPlayerRoster)(object)new StPlayerRoster(peers), (IParticipantPeerMap)(object)new StParticipantPeerMap(peers), (ISpawnOwnership)(object)new StSpawnOwnership(_log), (IPlayerLifeQuery)(object)new StPlayerLifeQuery(_log), (IDestructibleOwnership)(object)new StDestructibleOwnership(_log)); _log.Log("ST adapter composed over " + text + "."); return true; } catch (Exception ex) when (ex is TypeLoadException || ex is MissingMethodException || ex is MissingFieldException || ex is TypeInitializationException || ex is BadImageFormatException) { _log.LogWarning("The installed SULFUR Together does not carry the expected public bridge (SULFURTogether.Api). Multiplayer unavailable; single-player is unaffected. (" + ex.GetType().Name + ": " + ex.Message + ")"); return false; } } [MethodImpl(MethodImplOptions.NoInlining)] private static string DescribeBridge() { return $"ST bridge API v{1}"; } } } namespace FalseGods.Integration.SulfurTogether.Diagnostics { internal sealed class BepInExLogger : ILogger { private readonly ManualLogSource _log; public BepInExLogger(ManualLogSource log) { _log = log ?? throw new ArgumentNullException("log"); } public void Log(string message) { _log.LogMessage((object)message); } public void LogWarning(string message) { _log.LogWarning((object)message); } } }
FalseGods.Plugin.dll
Decompiled 9 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FalseGods.Application.Arena; using FalseGods.Application.Combat; using FalseGods.Application.Presentation; using FalseGods.Application.ReadyGate; using FalseGods.Application.Replication; using FalseGods.Core.Arena; using FalseGods.Core.Arena.Events; using FalseGods.Core.Bosses; using FalseGods.Core.Bosses.Combat; using FalseGods.Core.Bosses.Events; using FalseGods.Core.Encounters; using FalseGods.Core.Simulation; using FalseGods.Integration.Sulfur.Arena; using FalseGods.Integration.Sulfur.Combat; using FalseGods.Integration.Sulfur.Navigation; using FalseGods.Integration.Sulfur.Presentation; using FalseGods.Integration.Sulfur.Simulation; using FalseGods.Plugin.Diagnostics; using FalseGods.Protocol.Arena; using FalseGods.Protocol.Wire; using FalseGods.RuntimeContracts.Arena; using FalseGods.RuntimeContracts.Diagnostics; using FalseGods.RuntimeContracts.Integration; using FalseGods.RuntimeContracts.Multiplayer; using FalseGods.RuntimeContracts.Presentation; using FalseGods.RuntimeContracts.Transport; using FalseGods.UnityRuntime.Arena; using FalseGods.UnityRuntime.Presentation; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FalseGods.Plugin")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6e5740a80f810ab422551028733810b527fb614d")] [assembly: AssemblyProduct("FalseGods.Plugin")] [assembly: AssemblyTitle("FalseGods.Plugin")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FalseGods.Plugin { internal sealed class ClientBossController : IDisposable { private sealed class HitReportSink : IBossDamageSink { private readonly ClientHitReporter _reporter; private readonly EncounterId _encounter; public HitReportSink(ClientHitReporter reporter, EncounterId encounter) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) _reporter = reporter; _encounter = encounter; } public void ApplyWeaponDamage(float amount) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) _reporter.ReportHit(_encounter, amount, (WorldPosition?)null); } } private const float OriginEpsilon = 0.05f; private readonly ILogger? _logger; private readonly IFalseGodsIntegration _integration; private readonly string _contentDirectory; private readonly ClientEncounterFlow _controlFlow; private readonly ClientHitReporter _hitReporter; private readonly IDamagePort _damagePort; private readonly SulfurLocalPlayer _localPlayer; private readonly IBattlefieldCleanupPort _battlefield; private readonly IBossArmPort _rageArms; private readonly IBossVoicePort _voice; private readonly IArenaAtmospherePort _atmosphere; private readonly IBossRewardPort _reward; private readonly Func<bool> _levelWillBringTheArena; private readonly IBossPresencePort _presence; private ReplicationReceiver _receiver; private IDisposable? _hitBinding; private BossPresentation? _presentation; private EncounterId? _encounter; private int _presentedEvents; private int _presentedArenaEvents; private bool _waitingForCameraLogged; private BundleArenaRealization? _realization; private ArenaLoadFlow? _arenaFlow; private LoadedArena? _loadedArena; private ArenaPresentation? _arenaPresentation; private EncounterId? _arenaEncounter; private bool _lateJoinArenaFailed; private bool _arenaSnapshotReplayed; private bool _openingPlayed; private bool _waitingForOwnArenaLogged; private bool _ownsArena; public HijackedArenaContent? LevelArena { get; set; } public bool IsUp => _presentation != null; public ClientBossController(ILogger logger, MonoBehaviour host, IFalseGodsIntegration integration, IArenaAtmospherePort atmosphere, Func<bool> levelWillBringTheArena) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown _logger = logger; _integration = integration ?? throw new ArgumentNullException("integration"); _atmosphere = atmosphere ?? throw new ArgumentNullException("atmosphere"); _levelWillBringTheArena = levelWillBringTheArena ?? throw new ArgumentNullException("levelWillBringTheArena"); _contentDirectory = Path.GetDirectoryName(typeof(ClientBossController).Assembly.Location) ?? "."; _receiver = new ReplicationReceiver(integration.Channel, integration.Session); _hitReporter = new ClientHitReporter(integration.Channel, integration.Session, logger); _damagePort = (IDamagePort)new SulfurDamagePort(logger); _localPlayer = new SulfurLocalPlayer(); _battlefield = (IBattlefieldCleanupPort)new SulfurBattlefieldCleanup(logger); _rageArms = (IBossArmPort)new SulfurBossArmPort(host, logger); _reward = (IBossRewardPort)new SulfurBossReward(logger); _presence = (IBossPresencePort)new SulfurBossPresence((Func<Collider>)delegate { BossPresentation? presentation = _presentation; return (presentation == null) ? null : presentation.CollisionCollider; }, logger); _voice = (IBossVoicePort)new SulfurBossVoice(((Component)host).transform, logger); _voice.Warm(); _atmosphere.Warm(); _controlFlow = new ClientEncounterFlow(integration.Channel, integration.Session) { OnEnterArena = HandleEnterArena, OnAborted = delegate(EncounterAborted aborted) { //IL_0012: 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) ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log($"Host aborted {aborted.Encounter} at the gate ({aborted.Reason}); tearing the local arena down."); } TeardownArena(); }, OnEnded = delegate(EncounterEnded ended) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log($"Host ended {ended.Encounter}; discarding the encounter."); } DiscardEncounter(); }, OnBossHitPlayer = HandleBossHitPlayer }; ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log("Client encounter composition ready: listening for the host's announcements and streams."); } } public void Tick(float deltaSeconds) { //IL_0030: 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_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_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) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_00fd: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: 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_01b4: Unknown result type (might be due to invalid IL or missing references) _controlFlow.Tick(deltaSeconds); TryRealizeFromBaseline(); BossSnapshot latestBossSnapshot = _receiver.LatestBossSnapshot; if (latestBossSnapshot == null) { return; } if (_encounter.HasValue && latestBossSnapshot.Encounter != _encounter.Value) { ResetForNewEncounter(latestBossSnapshot.Encounter); return; } SimVector2 position; if (_presentation == null) { position = latestBossSnapshot.Position; float x = ((SimVector2)(ref position)).X; float positionHeight = latestBossSnapshot.PositionHeight; position = latestBossSnapshot.Position; if (!TryRaisePresentation(x, positionHeight, ((SimVector2)(ref position)).Z, latestBossSnapshot.Encounter)) { return; } } ReplayArenaSnapshotOnce(); IReadOnlyList<IBossWireEvent> appliedBossEvents = _receiver.AppliedBossEvents; while (_presentedEvents < appliedBossEvents.Count) { IBossWireEvent val = appliedBossEvents[_presentedEvents]; _presentation.Handle(WirePresentationMapping.ToEvent(latestBossSnapshot.Boss, val)); if (val is BossRelocatedEvent) { ClearOurOwnFloor(); } else { BossEnragedEvent val2 = (BossEnragedEvent)(object)((val is BossEnragedEvent) ? val : null); if (val2 != null && val2.Enraged) { IBossVoicePort voice = _voice; position = latestBossSnapshot.Position; float x2 = ((SimVector2)(ref position)).X; float positionHeight2 = latestBossSnapshot.PositionHeight; position = latestBossSnapshot.Position; voice.Roar(new ArenaWorldPoint(x2, positionHeight2, ((SimVector2)(ref position)).Z)); } else if (val is BossBeganEvent) { PlayTheOpening(latestBossSnapshot, withCeremony: true); } else if (val is BossDefeatedEvent) { _atmosphere.StopBattleMusic(); _presence.HideHealthBar(); IBossRewardPort reward = _reward; LoadedArena? loadedArena = _loadedArena; ArenaWorldPoint? val3 = ((loadedArena != null) ? loadedArena.RewardDrop : ((ArenaWorldPoint?)null)); ? val4; if (!val3.HasValue) { position = latestBossSnapshot.Position; float x3 = ((SimVector2)(ref position)).X; float positionHeight3 = latestBossSnapshot.PositionHeight; position = latestBossSnapshot.Position; val4 = new ArenaWorldPoint(x3, positionHeight3, ((SimVector2)(ref position)).Z); } else { val4 = val3.GetValueOrDefault(); } reward.DropReward((ArenaWorldPoint)val4); } } _presentedEvents++; } CatchUpOnTheOpening(latestBossSnapshot); IReadOnlyList<IArenaWireEvent> appliedArenaEvents = _receiver.AppliedArenaEvents; while (_presentedArenaEvents < appliedArenaEvents.Count) { ArenaPresentation? arenaPresentation = _arenaPresentation; if (arenaPresentation != null) { arenaPresentation.Handle(WirePresentationMapping.ToEvent(appliedArenaEvents[_presentedArenaEvents])); } _presentedArenaEvents++; } PresentationState val5 = WirePresentationMapping.ToState(latestBossSnapshot); _presentation.Apply(val5); _presence.ReportHealth(val5.HealthFraction); CarryTheHostsArms(latestBossSnapshot); _presentation.Render(deltaSeconds); } private void CarryTheHostsArms(BossSnapshot snapshot) { //IL_0027: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (!snapshot.Enraged) { _rageArms.Release(); return; } _rageArms.Adopt(2); IBossArmPort rageArms = _rageArms; SimVector2 position = snapshot.Position; float x = ((SimVector2)(ref position)).X; float positionHeight = snapshot.PositionHeight; position = snapshot.Position; rageArms.Follow(new ArmPlacement(new ArenaWorldPoint(x, positionHeight, ((SimVector2)(ref position)).Z), snapshot.Facing, 3.1f, 1f, 1.5f, 1.5f)); } private void PlayTheOpening(BossSnapshot snapshot, bool withCeremony) { //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_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_0032: Unknown result type (might be due to invalid IL or missing references) _openingPlayed = true; if (withCeremony) { IBossVoicePort voice = _voice; SimVector2 position = snapshot.Position; float x = ((SimVector2)(ref position)).X; float positionHeight = snapshot.PositionHeight; position = snapshot.Position; voice.Roar(new ArenaWorldPoint(x, positionHeight, ((SimVector2)(ref position)).Z)); _atmosphere.SetRoomDepth(10f, 72f, 1f, 3f); ILogger? logger = _logger; if (logger != null) { logger.Log("[opening] the host's boss began; roaring and opening the room here."); } } else { _atmosphere.SetRoomDepth(10f, 72f, 0f, 0f); ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log("[opening] the fight was already under way; opening the room without the ceremony."); } } _atmosphere.StartBattleMusic(); _presence.ShowHealthBar(); } private void CatchUpOnTheOpening(BossSnapshot snapshot) { if (!_openingPlayed && snapshot.Begun) { PlayTheOpening(snapshot, withCeremony: false); } } private void ClearOurOwnFloor() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) LoadedArena loadedArena = _loadedArena; if (loadedArena != null) { int num = _battlefield.SweepCorpses(loadedArena.Origin, 120f); ILogger? logger = _logger; if (logger != null) { logger.Log($"[cleanup] the host's boss moved on; {num} body/bodies going into the floor here."); } } } public void Dispose() { _controlFlow.Dispose(); _receiver.Dispose(); _hitBinding?.Dispose(); _hitBinding = null; _presence.Withdraw(); BossPresentation? presentation = _presentation; if (presentation != null) { presentation.Dispose(); } _presentation = null; _openingPlayed = false; _atmosphere.StopBattleMusic(); TeardownArena(); ILogger? logger = _logger; if (logger != null) { logger.Log("Client encounter composition torn down; nothing remains."); } } private ClientLoadOutcome HandleEnterArena(EnterArena enter) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: 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_0049: Unknown result type (might be due to invalid IL or missing references) TeardownArena(); _lateJoinArenaFailed = false; ClientLoadOutcome val = RealizeArenaAt(enter.Origin, enter.Encounter); if (val.NotYet) { if (!_waitingForOwnArenaLogged) { _waitingForOwnArenaLogged = true; ILogger? logger = _logger; if (logger != null) { logger.Log($"The host announced {enter.Encounter}, but this peer's own arena is still being " + "built by the level (" + val.FailureReason + "); waiting for it rather than loading a second copy."); } } return val; } _waitingForOwnArenaLogged = false; if (val.Manifest == null) { ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning($"Arena load for {enter.Encounter} failed: {val.FailureReason}. Reporting ArenaLoadFailed."); } return val; } ILogger? logger3 = _logger; if (logger3 != null) { object arg = enter.Encounter; WorldPosition origin = enter.Origin; object arg2 = ((WorldPosition)(ref origin)).X; origin = enter.Origin; string text = $"Arena for {arg} ready at ({arg2:0.0}, {((WorldPosition)(ref origin)).Y:0.0}, "; origin = enter.Origin; logger3.Log(text + $"{((WorldPosition)(ref origin)).Z:0.0}); reporting ArenaReady."); } _openingPlayed = false; _atmosphere.SetRoomDepth(4f, 10f, 0f, 0f); return val; } private ClientLoadOutcome RealizeArenaAt(WorldPosition origin, EncounterId encounter) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00af: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_001a: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) HijackedArenaContent levelArena = LevelArena; if (levelArena != null && levelArena.IsLive) { return AdoptLevelArena(levelArena, origin, encounter); } if (_levelWillBringTheArena()) { return ClientLoadOutcome.Deferred("this peer's level is still building the arena it declared"); } BundleArenaRealization realization = new BundleArenaRealization(Path.Combine(_contentDirectory, "falsegods-poc-room.bundle"), Path.Combine(_contentDirectory, "arena-content-PocRoom.artifact"), "PocRoom", _logger); ArenaLoadFlow val = new ArenaLoadFlow((IArenaAssetProvider)(object)realization, (IArenaRealization)(object)realization, (INavigationPort)new AstarNavigationPort((Func<GameObject>)(() => realization.CurrentRoot), _logger), (IVanillaAssetProvider)new SulfurVanillaAssetProvider((Func<GameObject>)(() => realization.CurrentRoot), _logger)); ArenaPrepareResult val2 = val.Prepare(); if (!val2.Success) { val.Teardown(); return ClientLoadOutcome.Failed(val2.FailureReason ?? "prepare failed"); } ArenaRealizeResult val3 = val.Realize(new ArenaWorldPoint(((WorldPosition)(ref origin)).X, ((WorldPosition)(ref origin)).Y, ((WorldPosition)(ref origin)).Z)); if (!val3.Success || val3.Manifest == null || val3.Arena == null) { return ClientLoadOutcome.Failed(val3.FailureReason ?? "realize failed"); } _ownsArena = true; _realization = realization; _arenaFlow = val; _loadedArena = val3.Arena; _arenaPresentation = new ArenaPresentation(realization, _logger); _arenaEncounter = encounter; _arenaSnapshotReplayed = false; return ClientLoadOutcome.Ready(val3.Manifest); } private ClientLoadOutcome AdoptLevelArena(HijackedArenaContent levelArena, WorldPosition origin, EncounterId encounter) { //IL_0038: 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_003e: 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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown //IL_00ec: 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) ArenaRealizeResult realized = levelArena.Realized; BundleArenaRealization realization = levelArena.Realization; if (((realized != null) ? realized.Manifest : null) == null || realized.Arena == null || realization == null) { return ClientLoadOutcome.Failed("the level's arena is standing but reported no load result"); } ArenaWorldPoint origin2 = realized.Arena.Origin; if (!SameOrigin(origin2, origin)) { return ClientLoadOutcome.Failed($"the level's arena stands at ({((ArenaWorldPoint)(ref origin2)).X:0.0}, {((ArenaWorldPoint)(ref origin2)).Y:0.0}, " + $"{((ArenaWorldPoint)(ref origin2)).Z:0.0}) but the host announced ({((WorldPosition)(ref origin)).X:0.0}, {((WorldPosition)(ref origin)).Y:0.0}, " + $"{((WorldPosition)(ref origin)).Z:0.0})"); } _ownsArena = false; _realization = realization; _arenaFlow = null; _loadedArena = realized.Arena; _arenaPresentation = new ArenaPresentation(realization, _logger); _arenaEncounter = encounter; _arenaSnapshotReplayed = false; ILogger? logger = _logger; if (logger != null) { logger.Log($"Adopting the arena the hijacked level left standing for {encounter}; " + "no second copy loaded, and the level keeps it when the encounter ends."); } return ClientLoadOutcome.Ready(realized.Manifest); } private static bool SameOrigin(ArenaWorldPoint standing, WorldPosition announced) { if (Math.Abs(((ArenaWorldPoint)(ref standing)).X - ((WorldPosition)(ref announced)).X) <= 0.05f && Math.Abs(((ArenaWorldPoint)(ref standing)).Y - ((WorldPosition)(ref announced)).Y) <= 0.05f) { return Math.Abs(((ArenaWorldPoint)(ref standing)).Z - ((WorldPosition)(ref announced)).Z) <= 0.05f; } return false; } private void TryRealizeFromBaseline() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0033: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) EncounterBaseline baseline = _receiver.Baseline; if (baseline == null || _lateJoinArenaFailed) { return; } if (_loadedArena != (LoadedArena)null) { EncounterId? arenaEncounter = _arenaEncounter; EncounterId encounter = baseline.Encounter; if (arenaEncounter.HasValue && arenaEncounter.GetValueOrDefault() == encounter) { return; } } ClientLoadOutcome val = RealizeArenaAt(baseline.ArenaOrigin, baseline.Encounter); if (val.NotYet) { return; } if (val.Manifest == null) { _lateJoinArenaFailed = true; ILogger? logger = _logger; if (logger != null) { logger.LogWarning("Late-join arena load failed: " + val.FailureReason + ". The boss puppet will not be shown for this encounter."); } } else if (!string.Equals(val.Manifest.ArenaId, baseline.ArenaId, StringComparison.Ordinal) || val.Manifest.ArenaVersion != baseline.ArenaVersion || val.Manifest.ContentHash != baseline.ContentHash) { _lateJoinArenaFailed = true; ILogger? logger2 = _logger; if (logger2 != null) { logger2.LogWarning("Late-join arena content does not match the host's baseline " + $"({val.Manifest.ArenaId} v{val.Manifest.ArenaVersion} vs {baseline.ArenaId} " + $"v{baseline.ArenaVersion}); tearing it down and showing nothing."); } TeardownArena(); } else { ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log($"Late join: arena for {baseline.Encounter} realized from the baseline's origin and " + "content-verified against it."); } } } private void ReplayArenaSnapshotOnce() { if (_arenaSnapshotReplayed || _arenaPresentation == null) { return; } ArenaSnapshot latestArenaSnapshot = _receiver.LatestArenaSnapshot; if (latestArenaSnapshot != null) { _arenaSnapshotReplayed = true; IReadOnlyList<IPresentationEvent> readOnlyList = WirePresentationMapping.ToEvents(latestArenaSnapshot); for (int i = 0; i < readOnlyList.Count; i++) { _arenaPresentation.Handle(readOnlyList[i]); } } } private bool TryRaisePresentation(float x, float height, float z, EncounterId encounter) { //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_0020: 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_004d: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00c0: 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_0128: Unknown result type (might be due to invalid IL or missing references) if (_loadedArena != null) { EncounterId? arenaEncounter = _arenaEncounter; if (arenaEncounter.HasValue && !(arenaEncounter.GetValueOrDefault() != encounter)) { ILogger? logger = _logger; Vector3 val = new Vector3(x, height, z); ArenaWorldPoint bossSpawn = _loadedArena.BossSpawn; _presentation = new BossPresentation(logger, val, ((ArenaWorldPoint)(ref bossSpawn)).Y); if (_loadedArena.BossSize > 0f) { _presentation.SpriteScale = _loadedArena.BossSize; } _presence.Declare(); _encounter = encounter; _presentedEvents = 0; _presentedArenaEvents = 0; _waitingForCameraLogged = false; _hitBinding = BossWeaponDamage.Bind(((Component)_presentation.HitCollider).gameObject, (IBossDamageSink)(object)new HitReportSink(_hitReporter, encounter), _logger); ILogger? logger2 = _logger; if (logger2 != null) { logger2.Log($"Client boss puppet raised for {encounter} at ({x:0.0}, {height:0.0}, {z:0.0}), " + "where the host says it stands; host-driven. Your weapons report hits to the host."); } return true; } } if (!_waitingForCameraLogged) { _waitingForCameraLogged = true; ILogger? logger3 = _logger; if (logger3 != null) { logger3.Log($"Host boss state for {encounter} arrived before a matching local arena; waiting."); } } return false; } private void ResetForNewEncounter(EncounterId next) { //IL_0011: 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_004d: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) ILogger? logger = _logger; if (logger != null) { logger.Log($"Host started {next}; discarding the previous encounter's stream and visuals."); } _receiver.Dispose(); _receiver = new ReplicationReceiver(_integration.Channel, _integration.Session); _hitBinding?.Dispose(); _hitBinding = null; _presence.Withdraw(); BossPresentation? presentation = _presentation; if (presentation != null) { presentation.Dispose(); } _presentation = null; _encounter = null; _presentedEvents = 0; _presentedArenaEvents = 0; _openingPlayed = false; _atmosphere.StopBattleMusic(); if (_arenaEncounter.HasValue) { EncounterId? arenaEncounter = _arenaEncounter; if (!arenaEncounter.HasValue || arenaEncounter.GetValueOrDefault() != next) { TeardownArena(); } } } private void DiscardEncounter() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown _receiver.Dispose(); _receiver = new ReplicationReceiver(_integration.Channel, _integration.Session); _hitBinding?.Dispose(); _hitBinding = null; _presence.Withdraw(); BossPresentation? presentation = _presentation; if (presentation != null) { presentation.Dispose(); } _presentation = null; _encounter = null; _presentedEvents = 0; _presentedArenaEvents = 0; _openingPlayed = false; _atmosphere.StopBattleMusic(); TeardownArena(); } private void HandleBossHitPlayer(BossHitPlayer hit) { //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) //IL_0045: Unknown result type (might be due to invalid IL or missing references) int num = default(int); if (hit.Amount > 0 && _encounter.HasValue && !(hit.Encounter != _encounter.Value) && _localPlayer.TryGetLocalParticipantIndex(ref num)) { _damagePort.ApplyDamage(new ParticipantId(num), hit.Amount); ILogger? logger = _logger; if (logger != null) { logger.Log($"Boss hit you for {hit.Amount} (host-authoritative); applied to your local player."); } } } private void TeardownArena() { _arenaPresentation = null; if (_ownsArena) { ArenaLoadFlow? arenaFlow = _arenaFlow; if (arenaFlow != null) { arenaFlow.Teardown(); } } _ownsArena = false; _arenaFlow = null; _realization = null; _loadedArena = null; _arenaEncounter = null; _arenaSnapshotReplayed = false; } } [BepInPlugin("ryuka.sulfur.false_gods", "False Gods", "0.4.0")] public sealed class FalseGodsPlugin : BaseUnityPlugin { private sealed class TrackedPlayer { private readonly TargetMotionTracker _tracker; private SimVector2 _lastPosition; private bool _hasLastPosition; public SimVector2 SmoothedVelocity => _tracker.SmoothedVelocity; public TrackedPlayer(float smoothingSeconds) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown _tracker = new TargetMotionTracker(smoothingSeconds); } public void Observe(PlayerAim player, float deltaSeconds) { //IL_000b: 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_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_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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_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_007e: Unknown result type (might be due to invalid IL or missing references) SimVector2 val = default(SimVector2); if (((PlayerAim)(ref player)).VelocityKnown) { val = ((PlayerAim)(ref player)).Velocity; } else if (_hasLastPosition) { SimVector2 position = ((PlayerAim)(ref player)).Position; float num = (((SimVector2)(ref position)).X - ((SimVector2)(ref _lastPosition)).X) / deltaSeconds; position = ((PlayerAim)(ref player)).Position; ((SimVector2)(ref val))..ctor(num, (((SimVector2)(ref position)).Z - ((SimVector2)(ref _lastPosition)).Z) / deltaSeconds); } else { val = SimVector2.Zero; } _lastPosition = ((PlayerAim)(ref player)).Position; _hasLastPosition = true; _tracker.Observe(val, deltaSeconds); } } private enum CompositionRole { SinglePlayer, Host, Client } public const string PluginGuid = "ryuka.sulfur.false_gods"; public const string PluginName = "False Gods"; public const string PluginVersion = "0.4.0"; private const int TestBossDefinition = 1; private const float VolleySpreadMin = 1.4f; private const float VolleySpreadMax = 4.2f; private const float VolleyLiftHeight = 5f; private const float VolleyLiftSeconds = 0.5f; private const float VolleyHoldMin = 0.5f; private const float VolleyHoldMax = 1.5f; private const int VolleyHoldSalt = 9973; private const float VolleyFlightSeconds = 1.2f; private const float VolleyApex = 4f; private const float VolleyCratesPerSecond = 10f; private const float VolleyFireInterval = 0.1f; private const float VolleyLeadFraction = 1f; private const float VolleyLeadShare = 0.5f; private const float VolleyLeadSmoothingSeconds = 0.4f; private const int CrateHitDamage = 10; private const float CrateContactRadius = 1.2f; private const float CrateSplashRadius = 2.5f; private const float CrateKnockbackSpeed = 12f; private const float CrateKnockbackLift = 4f; private ConfigEntry<float> _maxClientHitDamage; private int _nextVolleySeed = 1; private IThrownCratePort _crates; private SulfurCarriedLoadMirror? _carriedLoads; private readonly List<PlayerAim> _playersToThrowAt = new List<PlayerAim>(); private readonly List<CrateVolleyAim> _volleyAims = new List<CrateVolleyAim>(); private readonly Dictionary<int, TrackedPlayer> _playerSpeeds = new Dictionary<int, TrackedPlayer>(); private readonly HashSet<int> _playersSeen = new HashSet<int>(); private readonly List<int> _forgottenPlayers = new List<int>(); private IPlayerMotionPort _playerMotion; private BepInExLogger _log; private IArenaHijackPort _hijack; private ArenaLevelFlow? _levelFlow; private IFalseGodsIntegration? _levelFlowIntegration; private IDisposable? _spawnOwnership; private IFalseGodsIntegration? _spawnOwnershipIntegration; private CrateCommandFlow? _crateFlow; private IFalseGodsIntegration? _crateFlowIntegration; private HijackedArenaContent _levelArena; private SulfurArenaHazard _hazard; private LocalEncounterController _boss; private IBossVoicePort _voice; private IArenaAtmospherePort _atmosphere; private SulfurCaveBossPortal _caveDoor; private SulfurDevMenuEntry _devMenuRow; private int _raisedForRun; private bool _warmedThisArena; private const int WarmCrateCount = 2; private const float WarmDropHeight = 3f; private ClientBossController? _client; private IFalseGodsIntegration? _clientIntegration; private int _nextEncounter = 1; private EncounterId _currentEncounter; private void Awake() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Expected O, but got Unknown //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: 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_0242: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Expected O, but got Unknown //IL_026f: Expected O, but got Unknown //IL_026f: Expected O, but got Unknown //IL_026f: Expected O, but got Unknown //IL_026f: Expected O, but got Unknown //IL_026f: Expected O, but got Unknown _maxClientHitDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Multiplayer", "MaxClientHitDamage", 1000f, "Host only: the largest single hit a multiplayer client may report against the boss. A sanity ceiling on a forged message, not a substitute for rate limiting - set it above any legitimate single weapon hit. The host clamps to this; the simulation still decides weak-point, phase, and death. Read once at load."); _log = new BepInExLogger(((BaseUnityPlugin)this).Logger); SulfurCrateImpact val = new SulfurCrateImpact(10, 1.2f, 2.5f, 12f, 4f, (ILogger)(object)_log); val.Hit = delegate { _boss?.CratesHitSomebody(); }; SulfurThrownCratePort val2 = (SulfurThrownCratePort)(object)(_crates = (IThrownCratePort)new SulfurThrownCratePort((ILogger)(object)_log, (IThrownCrateImpact)(object)val)); val2.Died = delegate(int crateId, CrateDeath death) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.ReportDestroyed(crateId, death); } }; val2.Exploded = delegate(ArenaWorldPoint at, bool airburst) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) _boss?.ExplosionAt(at, airburst); }; _carriedLoads = new SulfurCarriedLoadMirror(val2, (ILogger)(object)_log); _playerMotion = (IPlayerMotionPort)new SulfurPlayerMotionPort(); LevelGenerationHijackPatches.Install((ILogger)(object)_log); _levelArena = new HijackedArenaContent(Path.GetDirectoryName(typeof(FalseGodsPlugin).Assembly.Location) ?? ".", (ILogger)(object)_log); _hazard = new SulfurArenaHazard((Func<GameObject>)delegate { BundleArenaRealization? realization = _levelArena.Realization; return (realization == null) ? null : realization.CurrentRoot; }, "VisualRoot/VanillaProps", "PoolBlocker", 5, 0.25f, (ILogger)(object)_log); LevelGenerationHijack.ArenaRooms = _levelArena.CreateRoomSource(); LevelGenerationHijack.Fog = new ArenaFogRange(4f, 10f); _hijack = (IArenaHijackPort)new SulfurArenaHijackPort((ILogger)(object)_log); _voice = (IBossVoicePort)new SulfurBossVoice(((Component)this).transform, (ILogger)(object)_log); _atmosphere = (IArenaAtmospherePort)new SulfurArenaAtmosphere((MonoBehaviour)(object)this, (ILogger)(object)_log); _caveDoor = new SulfurCaveBossPortal((Action)GoToArenaLevel, (ILogger)(object)_log); _devMenuRow = new SulfurDevMenuEntry((Action)GoToArenaLevel, (ILogger)(object)_log); _boss = new LocalEncounterController((ILogger)(object)_log, (IMinionSpawnPort)new SulfurMinionSpawnPort((MonoBehaviour)(object)this, (ILogger)(object)_log, false), (IMinionSpawnPort)new SulfurMinionSpawnPort((MonoBehaviour)(object)this, (ILogger)(object)_log, true), (IBossArmPort)new SulfurBossArmPort((MonoBehaviour)(object)this, (ILogger)(object)_log), (IBattlefieldCleanupPort)new SulfurBattlefieldCleanup((ILogger)(object)_log), _voice, _atmosphere, (IBossRewardPort)new SulfurBossReward((ILogger)(object)_log), _playerMotion, _crates, (ICarrierPort)new SulfurCarrierPort((MonoBehaviour)(object)this, _crates, (ILogger)(object)_log, (Action<ArenaWorldPoint, CratePileId, int, float>)delegate(ArenaWorldPoint at, CratePileId pile, int count, float radius) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.BroadcastTaken(at, pile, count, radius); } }, (Action<ArenaWorldPoint, ArenaWorldPoint, CratePileId, int, int, int>)delegate(ArenaWorldPoint from, ArenaWorldPoint at, CratePileId pile, int count, int seed, int explosives) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.BroadcastSetDown(from, at, pile, count, seed, explosives); } }), delegate(ArenaWorldPoint at, CratePileId pile, bool explosive) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.BroadcastDropped(at, pile, explosive); } }, LaunchCrateVolley, _maxClientHitDamage.Value) { LevelArena = _levelArena }; FalseGodsIntegrations.Changed += OnIntegrationChanged; ((BaseUnityPlugin)this).Logger.LogMessage((object)("False Gods 0.4.0 loaded. Beat the cave boss and walk into the way through that opens in its room; the arena's own boss is started by walking into it. Multiplayer integration: " + ((FalseGodsIntegrations.Current != null) ? "registered" : "none (single-player)") + ".")); } private void Update() { WarmContentWhileTheScreenIsBlack(); _caveDoor.Watch(); _devMenuRow.Maintain(); MaintainArenaLevelFlow(FalseGodsIntegrations.Current); MaintainSpawnOwnership(FalseGodsIntegrations.Current); MaintainCrateFlow(FalseGodsIntegrations.Current); TrackPlayerMotion(Time.deltaTime); _crates.Advance(Time.deltaTime); IFalseGodsIntegration current = FalseGodsIntegrations.Current; CompositionRole compositionRole = EvaluateRole(current); if (compositionRole != CompositionRole.Client) { _hazard.Advance(Time.deltaTime); } if (compositionRole == CompositionRole.Client) { RunClientComposition(current); return; } TearDownClientComposition(); RunLocalComposition(current, compositionRole); } private void MaintainCrateFlow(IFalseGodsIntegration? integration) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_010c: Expected O, but got Unknown if (integration == null || !integration.Session.IsActive) { if (_crateFlow != null) { _crateFlow.Dispose(); _crateFlow = null; _crateFlowIntegration = null; SulfurCarriedLoadMirror? carriedLoads = _carriedLoads; if (carriedLoads != null) { carriedLoads.Clear(); } } return; } if (_crateFlow != null && _crateFlowIntegration != integration) { _crateFlow.Dispose(); _crateFlow = null; _crateFlowIntegration = null; } if (_crateFlow != null) { return; } _crateFlow = new CrateCommandFlow(integration.Channel, integration.Session) { OnDropped = delegate(ArenaWorldPoint at, CratePileId pile, bool explosive) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_0066: Unknown result type (might be due to invalid IL or missing references) _crates.Drop(at, pile, explosive); _log.Log($"[crate] host dropped one on {pile} at ({((ArenaWorldPoint)(ref at)).X:0.0}, {((ArenaWorldPoint)(ref at)).Y:0.0}, {((ArenaWorldPoint)(ref at)).Z:0.0}); " + $"{_crates.RestingOn(pile)} resting on that pile here."); }, OnThrown = delegate(ArenaWorldPoint from, ArenaWorldPoint to, float seconds, float apex) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) _crates.Throw(from, to, seconds, apex); _log.Log($"[crate] host threw one from ({((ArenaWorldPoint)(ref from)).X:0.0}, {((ArenaWorldPoint)(ref from)).Y:0.0}, {((ArenaWorldPoint)(ref from)).Z:0.0}) to " + $"({((ArenaWorldPoint)(ref to)).X:0.0}, {((ArenaWorldPoint)(ref to)).Y:0.0}, {((ArenaWorldPoint)(ref to)).Z:0.0}); {_crates.InFlight} in the air here."); }, OnTaken = delegate(ArenaWorldPoint at, CratePileId pile, int count, float radius) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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) int num = _crates.TakeFrom(pile, count, at, radius); SulfurCarriedLoadMirror? carriedLoads2 = _carriedLoads; if (carriedLoads2 != null) { carriedLoads2.PickedUp(at, count); } _log.Log($"[carrier] host collected {count} off {pile}; {num} taken here, " + $"{_crates.RestingOn(pile)} left on it."); }, OnSetDown = delegate(ArenaWorldPoint from, ArenaWorldPoint at, CratePileId pile, int count, int seed, int explosives) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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) int num = _crates.TossRing(from, at, pile, count, seed, explosives); SulfurCarriedLoadMirror? carriedLoads2 = _carriedLoads; if (carriedLoads2 != null) { carriedLoads2.PutDown(from); } _log.Log($"[carrier] host put {count} down on {pile} (seed {seed}, {explosives} that go " + $"off); {num} laid out here, {_crates.RestingOn(pile)} on that pile."); }, OnVolleyFired = delegate(CratePileId pile, IReadOnlyList<CrateVolleyAim> aims, CrateVolleyShape shape) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) int num = _crates.LaunchVolley(pile, aims, shape); _log.Log($"[crate] host fired a volley of {((CrateVolleyShape)(ref shape)).Count} off {pile} (seed {((CrateVolleyShape)(ref shape)).Seed}) " + $"spread over {aims.Count} player(s); {num} lifted here."); }, OnDestroyed = delegate(int crateId, CrateDeath death) { //IL_0007: 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) bool flag = _crates.Destroy(crateId, death); _log.Log($"[crate] host settled that crate {crateId} was {Describe(death)}; " + (flag ? "destroyed here too." : "this peer no longer had it.")); }, OnDestroyRequested = delegate(int crateId, CrateDeath death) { //IL_0007: 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_002c: Unknown result type (might be due to invalid IL or missing references) bool flag = _crates.Destroy(crateId, death); CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.BroadcastDestroyed(crateId, death); } _log.Log($"[crate] a client's player {Describe(death)} crate {crateId}; " + (flag ? "destroyed here and settled for everyone." : "the host no longer had it.")); } }; _crateFlowIntegration = integration; } private static string Describe(CrateDeath death) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if ((int)death != 0) { return "burst on a player"; } return "shot"; } private void MaintainSpawnOwnership(IFalseGodsIntegration? integration) { if (integration != _spawnOwnershipIntegration) { _spawnOwnership?.Dispose(); _spawnOwnership = ((integration != null) ? integration.Spawns.DeclareHostAuthoritative((object)this) : null); _spawnOwnershipIntegration = integration; FightingPlayers.AskedOf((integration != null) ? integration.Lives : null); OurDestructibles.ClaimedWith((integration != null) ? integration.Destructibles : null); if (integration != null && _spawnOwnership == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"The session layer would not carry our runtime spawns; the boss's minions will appear on the host only."); } } } private void MaintainArenaLevelFlow(IFalseGodsIntegration? integration) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00bd: 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) if (integration == null || !integration.Session.IsActive) { if (_levelFlow != null) { TearDownArenaLevelFlow(); } return; } if (_levelFlow != null && _levelFlowIntegration != integration) { TearDownArenaLevelFlow(); } if (_levelFlow == null) { _levelFlow = new ArenaLevelFlow(integration.Channel, integration.Session, integration.Roster) { OnDeclared = ApplyArenaLevelDeclaration, OnRequested = HandleArenaLevelRequest }; _levelFlowIntegration = integration; ReconcileArenaLevelOnJoiningSession(integration); } ArenaLevelDeclared declaration = _levelFlow.Declaration; if (declaration != (ArenaLevelDeclared)null && declaration.IsBossArena && !_hijack.IsArenaModeOn && (int)integration.Session.Role == 0) { _levelFlow.Declare(declaration.Level, false); } _levelFlow.Tick(); } private void ReconcileArenaLevelOnJoiningSession(IFalseGodsIntegration integration) { //IL_0006: 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) if ((int)integration.Session.Role == 0) { if (_hijack.IsArenaModeOn) { ArenaLevelFlow? levelFlow = _levelFlow; if (levelFlow != null) { levelFlow.Declare(_hijack.ArenaLevel, true); } } } else if (_hijack.IsArenaModeOn) { ((BaseUnityPlugin)this).Logger.LogMessage((object)"Joined a session: the host decides which level is the boss arena, so the local declaration is dropped until it says so."); _hijack.LeaveArenaMode(); } } private void TearDownArenaLevelFlow() { ArenaLevelFlow? levelFlow = _levelFlow; if (levelFlow != null) { levelFlow.Dispose(); } _levelFlow = null; _levelFlowIntegration = null; } private void GoToArenaLevel() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_0056: 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) ArenaLevelFlow levelFlow = _levelFlow; if (levelFlow == null) { _hijack.LoadHijackedArena(); return; } IFalseGodsIntegration current = FalseGodsIntegrations.Current; if (current != null && (int)current.Session.Role == 0) { levelFlow.Declare(_hijack.ArenaLevel, true); _hijack.LoadHijackedArena(); } else { levelFlow.Request(_hijack.ArenaLevel); ((BaseUnityPlugin)this).Logger.LogMessage((object)"Asked the host to take the session to the boss arena; the host leads the transition."); } } private void ApplyArenaLevelDeclaration(ArenaLevelDeclared declaration) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!declaration.IsBossArena) { _hijack.LeaveArenaMode(); } else if (!_hijack.DeclareArenaLevel(declaration.Level)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)($"The host declared {declaration.Level} a boss arena, but this build does not " + "recognise that level; it will generate normally here.")); } } private void HandleArenaLevelRequest(ArenaLevelRequested request) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_003a: 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) ArenaLevelId arenaLevel = _hijack.ArenaLevel; if (request.Level != arenaLevel) { ((BaseUnityPlugin)this).Logger.LogWarning((object)($"A session peer asked for a boss arena at {request.Level}, but this build's " + $"arena is {arenaLevel}; ignoring the request.")); return; } ((BaseUnityPlugin)this).Logger.LogMessage((object)"A session peer asked for the boss arena; declaring it and leading the transition."); ArenaLevelFlow? levelFlow = _levelFlow; if (levelFlow != null) { levelFlow.Declare(arenaLevel, true); } _hijack.LoadHijackedArena(); } private void LaunchCrateVolley(CratePileId pile, int count) { //IL_00a6: 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_0155: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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) if ((Object)(object)Camera.main == (Object)null) { return; } int num = _nextVolleySeed++; float num2 = SeededRandom.Range(num, 9973, 0.5f, 1.5f); float num3 = (0.5f + num2 + 1.2f) * 1f; List<CrateVolleyAim> list = BuildVolleyAims(num3); if (list.Count == 0) { _log.Log("[crate] nobody to throw at — every player is down or out of the level."); return; } CrateVolleyShape val = default(CrateVolleyShape); ((CrateVolleyShape)(ref val))..ctor(num, count, 1.4f, 4.2f, 5f, 0.5f, num2, 1.2f, 4f, 0.5f, 0.1f); int num4 = _crates.LaunchVolley(pile, (IReadOnlyList<CrateVolleyAim>)list, val); if (num4 > 0) { CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.BroadcastVolley(pile, (IReadOnlyList<CrateVolleyAim>)list, val); } _log.Log($"[crate] volley of {num4} lifted off {pile}; {_crates.RestingOn(pile)} left there. " + $"Hold {num2:0.00}s, then {10f:0.#}/s for {(float)num4 * 0.1f:0.00}s; " + $"spread over {list.Count} player(s), led {num3:0.00}s. Shoot them for loot."); } else { _log.Log($"[crate] {pile} is empty - the boss has no ammunition. Nothing has been carried to it " + "yet."); } } private List<CrateVolleyAim> BuildVolleyAims(float airtime) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_004e: 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) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) _playerMotion.ReadPlayersToThrowAt((IList<PlayerAim>)_playersToThrowAt); _volleyAims.Clear(); for (int i = 0; i < _playersToThrowAt.Count; i++) { PlayerAim val = _playersToThrowAt[i]; if (_playerSpeeds.TryGetValue(((PlayerAim)(ref val)).Index, out TrackedPlayer value)) { SimVector2 val2 = LeadAim.Predict(((PlayerAim)(ref val)).Position, value.SmoothedVelocity, airtime); List<CrateVolleyAim> volleyAims = _volleyAims; SimVector2 position = ((PlayerAim)(ref val)).Position; float x = ((SimVector2)(ref position)).X; float height = ((PlayerAim)(ref val)).Height; position = ((PlayerAim)(ref val)).Position; volleyAims.Add(new CrateVolleyAim(new ArenaWorldPoint(x, height, ((SimVector2)(ref position)).Z), new ArenaWorldPoint(((SimVector2)(ref val2)).X, ((PlayerAim)(ref val)).Height, ((SimVector2)(ref val2)).Z))); } } return _volleyAims; } private void TrackPlayerMotion(float deltaSeconds) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (deltaSeconds <= 0f) { return; } _playerMotion.ReadPlayersToThrowAt((IList<PlayerAim>)_playersToThrowAt); _playersSeen.Clear(); for (int i = 0; i < _playersToThrowAt.Count; i++) { PlayerAim player = _playersToThrowAt[i]; _playersSeen.Add(((PlayerAim)(ref player)).Index); if (!_playerSpeeds.TryGetValue(((PlayerAim)(ref player)).Index, out TrackedPlayer value)) { value = new TrackedPlayer(0.4f); _playerSpeeds[((PlayerAim)(ref player)).Index] = value; } value.Observe(player, deltaSeconds); } if (_playerSpeeds.Count == _playersSeen.Count) { return; } _forgottenPlayers.Clear(); foreach (int key in _playerSpeeds.Keys) { if (!_playersSeen.Contains(key)) { _forgottenPlayers.Add(key); } } for (int j = 0; j < _forgottenPlayers.Count; j++) { _playerSpeeds.Remove(_forgottenPlayers[j]); } } private void OnDestroy() { FalseGodsIntegrations.Changed -= OnIntegrationChanged; IArenaHijackPort hijack = _hijack; if (hijack != null) { hijack.LeaveArenaMode(); } if (_boss != null && _boss.IsActiveEncounter) { _boss.Drop(); } TearDownClientComposition(); TearDownArenaLevelFlow(); _spawnOwnership?.Dispose(); _spawnOwnership = null; _spawnOwnershipIntegration = null; CrateCommandFlow? crateFlow = _crateFlow; if (crateFlow != null) { crateFlow.Dispose(); } _crateFlow = null; _crateFlowIntegration = null; SulfurCaveBossPortal caveDoor = _caveDoor; if (caveDoor != null) { caveDoor.Forget(); } ((IDisposable)_atmosphere)?.Dispose(); } private CompositionRole EvaluateRole(IFalseGodsIntegration? integration) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (integration == null || !integration.Session.IsActive) { return CompositionRole.SinglePlayer; } if ((int)integration.Session.Role != 0) { return CompositionRole.Client; } return CompositionRole.Host; } private void RunLocalComposition(IFalseGodsIntegration? integration, CompositionRole role) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) DropWithTheArena(); RaiseWithTheArena(integration, role); bool flag = role == CompositionRole.Host && _boss.IsUp; if (flag && !_boss.HasReplication && _boss.CurrentManifest != (ArenaManifest)null) { _boss.SetHosting(BuildHostReplication(integration, _boss.CurrentManifest, _boss.CurrentOrigin), integration); } else if (!flag && _boss.HasReplication) { _boss.SetHosting(null, null); } _boss.Tick(Time.deltaTime); } private void DropWithTheArena() { if (_boss.IsUp && !_levelArena.IsLive) { ((BaseUnityPlugin)this).Logger.LogMessage((object)"The level took the arena with it; the fight there is over."); _boss.Drop(); } } private void RaiseWithTheArena(IFalseGodsIntegration? integration, CompositionRole role) { int arenaRunsFinished = LevelGenerationHijack.ArenaRunsFinished; if (arenaRunsFinished != 0 && arenaRunsFinished != _raisedForRun && _levelArena.IsLive) { _raisedForRun = arenaRunsFinished; if (_boss.IsActiveEncounter) { _boss.Drop(); } _crates.Clear(); ((BaseUnityPlugin)this).Logger.LogMessage((object)"The boss arena is standing; raising the boss in it. It waits, untouchable, until a player walks into the room."); Raise(integration, role); } } private void WarmContentWhileTheScreenIsBlack() { if (!_levelArena.IsLive) { _warmedThisArena = false; } else if (!_warmedThisArena) { _warmedThisArena = true; _crates.Prepare(); MakeTheFirstOnesNow(); } } private void MakeTheFirstOnesNow() { //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_0067: 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_00b0: Unknown result type (might be due to invalid IL or missing references) ArenaRealizeResult? realized = _levelArena.Realized; object obj; if (realized == null) { obj = null; } else { LoadedArena arena = realized.Arena; obj = ((arena != null) ? arena.CrateSources : null); } IReadOnlyList<ArenaWorldPoint> readOnlyList = (IReadOnlyList<ArenaWorldPoint>)obj; if (readOnlyList == null || readOnlyList.Count == 0) { return; } ArenaWorldPoint at = readOnlyList[0]; ArenaWorldPoint val = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref val))..ctor(((ArenaWorldPoint)(ref at)).X, ((ArenaWorldPoint)(ref at)).Y + 3f, ((ArenaWorldPoint)(ref at)).Z); int num = 0; for (int i = 0; i < 2; i++) { if (_crates.Drop(val, CratePileId.Source(0), false)) { num++; } } _log.Log($"[crate] {num} made at the first production point while the level was still loading, so the " + "first one of the fight is not the first one ever built."); _boss.WarmTheVillage(at); } private void Raise(IFalseGodsIntegration? integration, CompositionRole role) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) _currentEncounter = new EncounterId(_nextEncounter++); _boss.Raise(_currentEncounter, (role == CompositionRole.Host) ? integration : null); } private void RunClientComposition(IFalseGodsIntegration integration) { if (_boss.IsActiveEncounter) { _boss.Drop(); } if (_client != null && _clientIntegration != integration) { TearDownClientComposition(); } if (_client == null) { _client = new ClientBossController((ILogger)(object)_log, (MonoBehaviour)(object)this, integration, _atmosphere, () => _hijack.IsArenaModeOn && !_levelArena.IsLive) { LevelArena = _levelArena }; _clientIntegration = integration; } _client.Tick(Time.deltaTime); } private void TearDownClientComposition() { _client?.Dispose(); _client = null; _clientIntegration = null; } private EncounterHostReplication BuildHostReplication(IFalseGodsIntegration integration, ArenaManifest manifest, WorldPosition arenaOrigin) { //IL_000c: 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_0024: 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_0030: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown return new EncounterHostReplication(new ReplicationSender(integration.Channel, integration.Session), integration.Session, integration.Roster, _currentEncounter, new DefinitionId(1), manifest, arenaOrigin); } private void OnIntegrationChanged() { ((BaseUnityPlugin)this).Logger.LogMessage((object)((FalseGodsIntegrations.Current != null) ? "Multiplayer integration registered; the host/client composition activates with the session." : "Multiplayer integration revoked; returning to the single-player composition.")); } } internal sealed class HijackedArenaContent { private static readonly ArenaWorldPoint LevelOrigin = new ArenaWorldPoint(0f, 0f, 0f); private readonly string _contentDirectory; private readonly ILogger _logger; private BundleArenaRealization? _realization; private ArenaLoadFlow? _flow; private ArenaRealizeResult? _realized; public bool IsLive { get { if (_realization != null) { return (Object)(object)_realization.CurrentRoot != (Object)null; } return false; } } public ArenaRealizeResult? Realized { get { if (!IsLive) { return null; } return _realized; } } public BundleArenaRealization? Realization { get { if (!IsLive) { return null; } return _realization; } } public static ArenaWorldPoint Origin => LevelOrigin; public HijackedArenaContent(string contentDirectory, ILogger logger) { _contentDirectory = contentDirectory ?? throw new ArgumentNullException("contentDirectory"); _logger = logger; } public HijackedArenaRoomSource CreateRoomSource() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown return new HijackedArenaRoomSource((Func<HijackedArenaLoad>)Load, (Func<GameObject>)delegate { BundleArenaRealization? realization = _realization; return (realization == null) ? null : realization.CurrentRoot; }, (Action)Release, _logger); } private HijackedArenaLoad Load() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0061: 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) //IL_0082: Expected O, but got Unknown //IL_0082: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00b7: 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) Release(); BundleArenaRealization realization = new BundleArenaRealization(Path.Combine(_contentDirectory, "falsegods-poc-room.bundle"), Path.Combine(_contentDirectory, "arena-content-PocRoom.artifact"), "PocRoom", _logger); _realization = realization; _flow = new ArenaLoadFlow((IArenaAssetProvider)(object)realization, (IArenaRealization)(object)realization, (INavigationPort)new NativeLevelNavigationPort(_logger), (IVanillaAssetProvider)new SulfurVanillaAssetProvider((Func<GameObject>)(() => realization.CurrentRoot), _logger)); ArenaPrepareResult val = _flow.Prepare(); if (!val.Success) { return HijackedArenaLoad.Failed("arena content did not prepare: " + val.FailureReason); } ArenaRealizeResult val2 = _flow.Realize(LevelOrigin); if (!val2.Success || val2.Arena == null) { return HijackedArenaLoad.Failed("arena load failed: " + val2.FailureReason); } _realized = val2; return HijackedArenaLoad.Loaded(val2.Arena.PlayerSpawn); } private void Release() { ArenaLoadFlow? flow = _flow; if (flow != null) { flow.Teardown(); } _flow = null; _realization = null; _realized = null; } } internal sealed class LocalEncounterController { private sealed class LocalRoster : IPlayerRoster { public static readonly LocalRoster Instance = new LocalRoster(); public static readonly SessionPeerId LocalPeer = new SessionPeerId(0); private readonly IReadOnlyList<SessionPeerId> _members = (IReadOnlyList<SessionPeerId>)(object)new SessionPeerId[1] { LocalPeer }; public IReadOnlyList<SessionPeerId> Members => _members; } private sealed class WeaponSink : IBossDamageSink { private readonly LocalEncounterController _owner; public WeaponSink(LocalEncounterController owner) { _owner = owner; } public void ApplyWeaponDamage(float amount) { _owner.OnWeaponDamage(amount); } } internal const float EyeToFootDrop = 1.6f; internal const string BundleFileName = "falsegods-poc-room.bundle"; internal const string ArtifactFileName = "arena-content-PocRoom.artifact"; internal const string ArenaPrefabName = "PocRoom"; internal const float DefaultMaxClientHitDamage = 1000f; private const string PhaseTwoGroup = "phase_2"; private const float GateTimeoutSeconds = 30f; private static readonly SupplyLineShape Supply = new SupplyLineShape(0.35f, 14, 40); private static readonly SupplyEscalation Escalation = new SupplyEscalation((SupplyStep[])(object)new SupplyStep[5] { new SupplyStep(0.8f, 6, 7, 0.01f), new SupplyStep(0.6f, 6, 8, 0.02f), new SupplyStep(0.4f, 7, 9, 0.03f), new SupplyStep(0.2f, 7, 10, 0.04f), new SupplyStep(0f, 8, 10, 0.05f) }); private const float ProductionDropHeight = 3f; private const float ExitBarrelDelaySeconds = 0.5f; private const float ExitBarrelFlightSeconds = 1.6f; private const float ExitBarrelApexHeight = 9f; private const float CarrierReplacementRoundTrips = 1f; private const float StarvationRoundTrips = 1.5f; private const float FutilitySeconds = 30f; private const float RageDamageMultiplier = 2.5f; private const float RageCostsHealthFraction = 0.2f; private const int ExplosiveRollSeed = 20873; private const float AirburstOnTheBoss = 20f; private const float OpeningSeconds = 1.9f; private const float CarrierHandlingSeconds = 0.75f; private const float VolleyEverySeconds = 2f; private const int MaxCratesPerVolley = 16; private const float AssumedCarrierWalkSpeed = 5.13f; private static readonly IReadOnlyList<BossStation> Itinerary = (IReadOnlyList<BossStation>)(object)new BossStation[5] { new BossStation(0, 1f, default(MinionBandId)), new BossStation(1, 0.8f, MinionBands.Vanguard), new BossStation(0, 0.6f, default(MinionBandId)), new BossStation(1, 0.4f, MinionBands.Warband), new BossStation(0, 0.2f, MinionBands.Coven) }; private readonly ILogger _logger; private readonly ISimulationClock _clock; private readonly IEncounterParticipantQuery _participants; private readonly IDamagePort _damagePort; private readonly SulfurLocalPlayer _localPlayer; private readonly string _contentDirectory; private readonly float _maxClientHitDamage; private readonly IMinionSpawnPort _minionSpawns; private readonly IMinionSpawnPort _emergencyMinions; private readonly IBossArmPort _rageArms; private readonly IBattlefieldCleanupPort _battlefield; private readonly IBossVoicePort _voice; private readonly IArenaAtmospherePort _atmosphere; private readonly IBossRewardPort _reward; private readonly IPlayerMotionPort _players; private readonly List<PlayerAim> _atTheDoor = new List<PlayerAim>(); private readonly IBossPresencePort _presence; private readonly StarvationWatch _starvation = new StarvationWatch(); private int _pileLastSeen; private readonly IThrownCratePort _crates; private readonly ICarrierPort _carriers; private readonly Action<ArenaWorldPoint, CratePileId, bool>? _announceProduced; private readonly Action<CratePileId, int>? _throwVolley; private SupplyLine? _supply; private int[]? _restingAtSource; private float _sinceVolley; private float _measuredRoundTripSeconds = 1f; private float _walkSpeedInUse = 5.13f; private int _lastReportedThroughput = -1; private float _blastDamage; private float _blastRadius; private int _produced; private int _barrelsMade; private bool _cratesHitSomebody; private float _untilTheExitBarrel = -1f; private BossSimulation? _boss; private BossPresenter? _presenter; private BossPresentation? _presentation; private ArenaSimulation? _arena; private EncounterCoordinator? _coordinator; private ArenaPresentation? _arenaPresentation; private BundleArenaRealization? _realization; private ArenaLoadFlow? _flow; private EncounterHostReplication? _replication; private IDisposable? _damageBinding; private HostHitIntake? _hitIntake; private IFalseGodsIntegration? _hostIntegration; private ReplicationSender? _hostSender; private HostEncounterGate? _hostGate; private ArenaRealizeResult? _pendingStart; private bool _ownsArena; private ArenaManifest? _manifest; private LoadedArena? _arenaContent; private EncounterId _encounter; private WorldPosition _originWire; private BossActivity _lastReportedActivity = (BossActivity)4; private int _lastReportedPending = -1; public HijackedArenaContent? LevelArena { get; set; } public bool IsUp => _presentation != null; public bool IsActiveEncounter { get { if (!IsUp) { return _hostGate != null; } return true; } } public bool HasReplication => _replication != null; public ArenaManifest? CurrentManifest => _manifest; public WorldPosition CurrentOrigin => _originWire; public LocalEncounterController(ILogger logger, IMinionSpawnPort minions, IMinionSpawnPort emergencyMinions, IBossArmPort rageArms, IBattlefieldCleanupPort battlefield, IBossVoicePort voice, IArenaAtmospherePort atmosphere, IBossRewardPort reward, IPlayerMotionPort players, IThrownCratePort crates, ICarrierPort carriers, Action<ArenaWorldPoint, CratePileId, bool>? announceProduced = null, Action<CratePileId, int>? throwVolley = null, float maxClientHitDamage = 1000f) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0040: 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) //IL_0160: Expected O, but got Unknown //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown _throwVolley = throwVolley; _logger = logger; _minionSpawns = minions ?? throw new ArgumentNullException("minions"); _emergencyMinions = emergencyMinions ?? throw new ArgumentNullException("emergencyMinions"); _rageArms = rageArms ?? throw new ArgumentNullException("rageArms"); _battlefield = battlefield ?? throw new ArgumentNullException("battlefield"); _voice = voice ?? throw new ArgumentNullException("voice"); _atmosphere = atmosphere ?? throw new ArgumentNullException("atmosphere"); _reward = reward ?? throw new ArgumentNullException("reward"); _players = players ?? throw new ArgumentNullException("players"); _crates = crates ?? throw new ArgumentNullException("crates"); _carriers = carriers ?? throw new ArgumentNullException("carriers"); _announceProduced = announceProduced; _maxClientHitDamage = maxClientHitDamage; _clock = (ISimulationClock)new SulfurSimulationClock(); _participants = (IEncounterParticipantQuery)new SulfurParticipantQuery(); _damagePort = (IDamagePort)new SulfurDamagePort(logger); _localPlayer = new SulfurLocalPlayer(); _presence = (IBossPresencePort)new SulfurBossPresence((Func<Collider>)delegate { BossPresentation? presentation = _presentation; return (presentation == null) ? null : presentation.CollisionCollider; }, logger); _contentDirectory = Path.GetDirectoryName(typeof(LocalEncounterController).Assembly.Location) ?? "."; } public void CratesHitSomebody() { _cratesHitSomebody = true; } public void WarmTheVillage(ArenaWorldPoint at) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _carriers.Warm(at); } public void ExplosionAt(ArenaWorldPoint at, bool pickedOutOfTheAir) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) BossTakesItsShareOfTheBlast(at, pickedOutOfTheAir); } public void SetHosting(EncounterHostReplication? replication, IFalseGodsIntegration? integration) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) if (_replication != replication) { _replication = replication; ILogger logger = _logger; if (logger != null) { logger.Log((replication != null) ? "Host replication attached: encounter state and events now broadcast to the session." : "Host replication detached: encounter continues locally only."); } } if (replication == null || integration == null) { if (_hitIntake != null) { _hitIntake.Dispose(); _hitIntake = null; ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("Client hits are no longer accepted: this encounter is not hosted."); } } } else { if (_hitIntake != null) { return; } _hitIntake = new HostHitIntake(integration.Channel, integration.Roster, _encounter, _maxClientHitDamage, (Action<float>)OnWeaponDamage, (Action<string>)delegate(string message) { ILogger logger4 = _logger; if (logger4 != null) { logger4.Log(message); } }); ILogger logger3 = _logger; if (logger3 != null) { logger3.Log($"Client hits accepted for {_encounter}; the simulation still decides what they cost."); } } } public bool Raise(EncounterId encounter, IFalseGodsIntegration? hostIntegration) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0166: Expected O, but got Unknown //IL_0191: 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_01b2: Expected O, but got Unknown //IL_01b2: Expected O, but got Unknown //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown //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_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) if (IsActiveEncounter) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("An encounter is already up or gating; drop it first."); } return false; } _encounter = encounter; _hostIntegration = hostIntegration; _voice.Warm(); _atmosphere.Warm(); IThrownCratePort crates = _crates; IThrownCratePort obj = ((crates is SulfurThrownCratePort) ? crates : null); if (obj != null) { ((SulfurThrownCratePort)obj).ReadBlast(ref _blastDamage, ref _blastRadius); } if (_crates.Prepare()) { ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("[crate] destructible content loaded ahead of the fight."); } } HijackedArenaContent levelArena = LevelArena; if (levelArena != null && levelArena.IsLive) { ArenaRealizeResult realized = levelArena.Realized; if (((realized != null) ? realized.Manifest : null) == null || realized.Arena == null) { ILogger logger3 = _logger; if (logger3 != null) { logger3.LogWarning("The level's arena is standing but reported no load result; cannot raise in it."); } return false; } _ownsArena = false; _realization = levelArena.Realization; _flow = null; return RaiseInArena(realized, HijackedArenaContent.Origin); } Camera main = Camera.main; if ((Object)(object)main == (Object)null) { ILogger logger4 = _logger; if (logger4 != null) { logger4.LogWarning("Cannot start the encounter: no main camera. Load a level and stand in it first."); } return false; } _ownsArena = true; _realization = new BundleArenaRealization(Path.Combine(_contentDirectory, "falsegods-poc-room.bundle"), Path.Combine(_contentDirectory, "arena-content-PocRoom.artifact"), "PocRoom", _logger); BundleArenaRealization realizationForNav = _realization; _flow = new ArenaLoadFlow((IArenaAssetProvider)(object)_realization, (IArenaRealization)(object)_realization, (INavigationPort)new AstarNavigationPort((Func<GameObject>)(() => realizationForNav.CurrentRoot), _logger), (IVanillaAssetProvider)new SulfurVanillaAssetProvider((Func<GameObject>)(() => realizationForNav.CurrentRoot), _logger)); ArenaPrepareResult val = _flow.Prepare(); if (!val.Success || val.Artifact == null) { Abort("arena content did not prepare: " + val.FailureReason); return false; } Vector3 position = ((Component)main).transform.position; ArenaWorldPoint val2 = default(ArenaWorldPoint); ((ArenaWorldPoint)(ref val2))..ctor(position.x, position.y - 1.6f, position.z); ArenaWorldPoint val3; try { val3 = ArenaPlacement.OriginForPlayerFoot(val.Artifact, val2); } catch (InvalidOperationException ex) { Abort("arena placement refused: " + ex.Message); return false; } ArenaRealizeResult val4 = _flow.Realize(val3); if (!val4.Success || val4.Manifest == null || val4.Arena == null) { Abort("arena load failed: " + val4.FailureReason); return false; } return RaiseInArena(val4, val3); } private bool RaiseInArena(ArenaRealizeResult realized, ArenaWorldPoint origin) { //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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0111: 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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Invalid comparison between Unknown and I4 //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) _manifest = realized.Manifest; _originWire = new WorldPosition(((ArenaWorldPoint)(ref origin)).X, ((ArenaWorldPoint)(ref origin)).Y, ((ArenaWorldPoint)(ref origin)).Z); if (_hostIntegration != null) { _hostSender = new ReplicationSender(_hostIntegration.Channel, _hostIntegration.Session); _hostGate = new HostEncounterGate(_hostIntegration.Channel, _hostIntegration.Session, _hostIntegration.Roster, _hostSender, _encounter, realized.Manifest, _originWire, 30f); _pendingStart = realized; _hostGate.Open(); ILogger logger = _logger; if (logger != null) { logger.Log($"Encounter {_encounter}: arena realized and EnterArena broadcast; waiting for every " + $"session peer's ArenaReady (timeout {30f:0}s)."); } return true; } EncounterReadyGate val = new EncounterReadyGate(realized.Manifest, (IPlayerRoster)(object)LocalRoster.Instance); GateStatus val2 = val.SubmitReady(LocalRoster.LocalPeer, realized.Manifest); if ((int)val2 != 1) { Abort($"ready gate did not resolve locally: {val2}/{val.AbortReason}"); return false; } StartBoss(realized); return true; } public void Tick(float deltaSeconds) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0036: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_008d: 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) if (_hostGate != null && _pendingStart != (ArenaRealizeResult)null) { _hostGate.Tick(deltaSeconds); GateStatus status = _hostGate.Status; if ((int)status != 1) { if ((int)status == 2) { ILogger logger = _logger; if (logger != null) { logger.LogWarning($"Encounter {_encounter} aborted at the gate: {_hostGate.AbortReason} " + "(outstanding: [" + _hostGate.DescribeOutstanding() + "]). Clients were told; releasing the local arena."); } CleanupGate(); ReleaseArena(); } return; } ArenaRealizeResult pendingStart = _pendingStart; _pendingStart = null; _hostGate.Dispose(); _hostGate = null; ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("Ready gate resolved for every session peer; starting the encounter."); } StartBoss(pendingStart); } else if (_boss != null && _presenter != null && _presentation != null) { WatchTheDoor(); _boss.Advance(); ReportActivityChange(); if (!_boss.IsOutsideTheFight && !_boss.IsDead) { AdvanceSupplyLine(deltaSeconds); AdvanceStarvation(deltaSeconds); CarryTheArmsWithTheBoss(); FireWhateverWasBrought(deltaSeconds); } AdvanceTheLastBarrel(deltaSeconds); _presence.ReportHealth(_boss.HealthFraction); Present(); _presentation.Render(deltaSeconds); } } private void AdvanceTheLastBarrel(float deltaSeconds) { //IL_0076: 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) if (_untilTheExitBarrel < 0f) { return; } _untilTheExitBarrel -= deltaSeconds; if (_untilTheExitBarrel > 0f) { return; } _untilTheExitBarrel = -1f; LoadedArena? arenaContent = _arenaContent; ArenaWorldPoint? val = ((arenaContent != null) ? arenaContent.ExitBlast : ((ArenaWorldPoint?)null)); if (!val.HasValue) { ILogger logger = _logger; if (logger != null) { logger.LogWarning("[exit] the room authored no place for the boss's last barrel to land, so the way out stays shut."); } return; } bool flag = _crates.ThrowExplosive(BossStandsAt(), val.Value, 1.6f, 9f, (Action)OpenTheWayOut); ILogger logger2 = _logger; if (logger2 != null) { logger2.Log(flag ? "[exit] the boss throws one last barrel at the rock over the doorway." : "[exit] the boss's last barrel could not be thrown; opening the way out directly instead."); } if (!flag) { OpenTheWayOut(); } } private void OpenTheWayOut() { if (_arena != null && !_arena.IsExitUnlocked) { _arena.UnlockExit(); ILogger logger = _logger; if (logger != null) { logger.Log("[exit] the rock is blown out of the doorway; the way out is open."); } } } private void WatchTheDoor() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) LoadedArena? arenaContent = _arenaContent; ArenaWorldPoint? val = ((arenaContent != null) ? arenaContent.StartTrigger : ((ArenaWorldPoint?)null)); if (_boss == null || _boss.HasBegun || !val.HasValue) { return; } ArenaWorldPoint value = val.Value; float startTriggerRadius = _arenaContent.StartTriggerRadius; _players.ReadPlayersToThrowAt((IList<PlayerAim>)_atTheDoor); for (int i = 0; i < _atTheDoor.Count; i++) { PlayerAim val2 = _atTheDoor[i]; SimVector2 position = ((PlayerAim)(ref val2)).Position; float num = ((SimVector2)(ref position)).X - ((ArenaWorldPoint)(ref value)).X; float num2 = ((PlayerAim)(ref val2)).Height - ((ArenaWorldPoint)(ref value)).Y; position = ((PlayerAim)(ref val2)).Position; float num3 = ((SimVector2)(ref position)).Z - ((ArenaWorldPoint)(ref value)).Z; if (!(num * num + num2 * num2 + num3 * num3 > startTriggerRadius * startTriggerRadius)) { ILogger logger = _logger; if (logger != null) { logger.Log($"[opening] player {((PlayerAim)(ref val2)).Index} reached the room; the fight starts."); } _boss.Begin(); break; } } } private void AdvanceSupplyLine(float deltaSeconds) { //IL_0039: 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_008d: 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_00c5: 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_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_01ca: Unknown result type (might be due to invalid IL or missing references) LoadedArena? arenaContent = _arenaContent; IReadOnlyList<ArenaWorldPoint> readOnlyList = ((arenaContent != null) ? arenaContent.CrateSources : null); if (_supply == null || readOnlyList == null || readOnlyList.Count == 0) { return; } for (int i = 0; i < _restingAtSource.Length; i++) { _restingAtSource[i] = _crates.RestingOn(CratePileId.Source(i)); } AdvanceCarriers(deltaSeconds, readOnlyList); _supply.Advance(deltaSeconds, (IReadOnlyList<int>)_restingAtSource); SupplyEscalation escalation = Escalation; BossSimulation? boss = _boss; SupplyStep val = escalation.At((boss != null) ? boss.HealthFraction : 1f); IReadOnlyList<int> readOnlyList2 = _supply.DrainProductionRequests(); ArenaWorldPoint val4 = default(ArenaWorldPoint); for (int j = 0; j < readOnlyList2.Count; j++) { int num = readOnlyList2[j]; if (num >= readOnlyList.Count) { continue; } CratePileId val2 = CratePileId.Source(num); ArenaWorldPoint val3 = readOnlyList[num]; ((ArenaWorldPoint)(ref val4))..ctor(((ArenaWorldPoint)(ref val3)).X, ((ArenaWorldPoint)(ref val3)).Y + 3f, ((ArenaWorldPoint)(ref val3)).Z); bool flag = SeededRandom.Unit01(20873, _produced++) < (double)((SupplyStep)(ref val)).ExplosiveChance; if (!_crates.Drop(val4, val2, flag)) { continue; } _announceProduced?.Invoke(val4, val2, flag); if (flag) { _barrelsMade++; ILogger logger = _logger; if (logger != null) { logger.Log($"[supply] source {num} produced a BARREL ({_barrelsMade} of {_produced} " + $"produced so far, at {((SupplyStep)(ref val)).ExplosiveChance:P1} this step)."); } } else { ILogger logger2 = _logger; if (logger2 != null) { logger2.Log($"[supply] source {num} produced one; {_crates.RestingOn(val2)} resting there."); } } } } private void FireWhateverWasBrought(float deltaSeconds) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid
FalseGods.Protocol.dll
Decompiled 9 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using FalseGods.Core.Arena; using FalseGods.Core.Bosses; using FalseGods.Core.Simulation; using FalseGods.Protocol.Arena; using FalseGods.Protocol.Arena.Internal; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FalseGods.Protocol")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6e5740a80f810ab422551028733810b527fb614d")] [assembly: AssemblyProduct("FalseGods.Protocol")] [assembly: AssemblyTitle("FalseGods.Protocol")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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; } } internal static class IsExternalInit { } } namespace FalseGods.Protocol.Wire { public readonly struct ArenaLevelId : IEquatable<ArenaLevelId> { public int Environment { get; } public int LevelIndex { get; } public ArenaLevelId(int environment, int levelIndex) { Environment = environment; LevelIndex = levelIndex; } public bool Equals(ArenaLevelId other) { if (Environment == other.Environment) { return LevelIndex == other.LevelIndex; } return false; } public override bool Equals(object? obj) { if (obj is ArenaLevelId other) { return Equals(other); } return false; } public override int GetHashCode() { return (Environment * 397) ^ LevelIndex; } public override string ToString() { return $"env {Environment} level {LevelIndex}"; } public static bool operator ==(ArenaLevelId left, ArenaLevelId right) { return left.Equals(right); } public static bool operator !=(ArenaLevelId left, ArenaLevelId right) { return !left.Equals(right); } } public sealed record ArenaLevelDeclared(ArenaLevelId Level, bool IsBossArena); public sealed record ArenaLevelRequested(ArenaLevelId Level); public sealed record ArenaSnapshot(EncounterId Encounter, string ArenaId, int ArenaVersion, ProtocolVersion ProtocolVersion, SimulationTick Tick, IReadOnlyList<MechanismGroupId> ActiveMechanismGroups, bool ExitUnlocked, Sequence LastProcessedArenaEventSequence); public sealed record ArenaMechanismGroupActivatedEvent(Sequence Sequence, SimulationTick Tick, MechanismGroupId Group) : IArenaWireEvent; public sealed record ArenaExitUnlockedEvent(Sequence Sequence, SimulationTick Tick) : IArenaWireEvent; public sealed record BossHitPlayer(EncounterId Encounter, int Amount); public sealed record BossSnapshot(EncounterId Encounter, BossInstanceId Boss, DefinitionId Definition, ProtocolVersion ProtocolVersion, SimulationTick Tick, int PhaseId, int StateId, SimulationTick StateStartTick, AttackInstanceId? ActiveAttack, int? ActiveAttackDefinitionId, ParticipantId? Target, SimVector2 Position, float PositionHeight, SimVector2 Facing, int Health, int MaxHealth, bool WeakPointExposed, bool Enraged, bool Begun, Sequence LastProcessedBossEventSequence); public sealed record BossAppearedEvent(Sequence Sequence, SimulationTick Tick, int PhaseId) : IBossWireEvent; public sealed record BossBeganEvent(Sequence Sequence, SimulationTick Tick) : IBossWireEvent; public sealed record BossAttackTelegraphedEvent(Sequence Sequence, SimulationTick Tick, AttackInstanceId Attack, int AttackDefinitionId, SimVector2 AimPoint, float TelegraphSeconds) : IBossWireEvent; public sealed record BossAttackCommittedEvent(Sequence Sequence, SimulationTick Tick, AttackInstanceId Attack, int AttackDefinitionId, SimVector2 AimPoint) : IBossWireEvent; public sealed record BossPhaseChangedEvent(Sequence Sequence, SimulationTick Tick, int PhaseId) : IBossWireEvent; public sealed record BossWeakPointChangedEvent(Sequence Sequence, SimulationTick Tick, bool Exposed) : IBossWireEvent; public sealed record BossDamagedEvent(Sequence Sequence, SimulationTick Tick, int Amount, int RemainingHealth, bool WeakPointHit) : IBossWireEvent; public sealed record BossRelocatedEvent(Sequence Sequence, SimulationTick Tick, int StationIndex, int AnchorIndex, SimVector2 Position, float Height) : IBossWireEvent; public sealed record BossEnragedEvent(Sequence Sequence, SimulationTick Tick, bool Enraged) : IBossWireEvent; public sealed record BossDefeatedEvent(Sequence Sequence, SimulationTick Tick) : IBossWireEvent; public sealed record ClientHitRequest(EncounterId Encounter, int RequestSequence, float DamageCandidate, WorldPosition? AttackerPosition); public sealed record CrateDropped(WorldPosition At, int PileKind, int PileIndex, bool Explosive); public sealed record CratesTaken(WorldPosition At, int PileKind, int PileIndex, int Count, float Radius); public sealed record CratesSetDown(WorldPosition From, WorldPosition At, int PileKind, int PileIndex, int Count, int Seed, int Explosives); public sealed record CrateThrown(WorldPosition From, WorldPosition To, float FlightSeconds, float ApexHeight); public sealed record CrateVolleyTarget(WorldPosition Current, WorldPosition Lead); public sealed record CrateDestroyed(int CrateId, int Death); public sealed record CrateDestroyRequested(int CrateId, int Death); public sealed record CrateVolleyFired(IReadOnlyList<CrateVolleyTarget> Targets, int PileKind, int PileIndex, int Seed, int Count, float SpreadMinRadius, float SpreadMaxRadius, float LiftHeight, float LiftSeconds, float HoldSeconds, float FlightSeconds, float ApexHeight, float LeadShare, float FireIntervalSeconds); public sealed record EncounterBaseline(EncounterId Encounter, ProtocolVersion ProtocolVersion, string ArenaId, int ArenaVersion, ContentHash ContentHash, WorldPosition ArenaOrigin, SimulationTick Tick, int EncounterPhaseId, BossSnapshot Boss, ArenaSnapshot Arena, Sequence LastProcessedBossEventSequence, Sequence LastProcessedArenaEventSequence); public enum EncounterAbortReason { Unspecified, ContentHashSchemaMismatch, VersionMismatch, ContentMismatch, LoadFailed, Timeout } public sealed record EnterArena(EncounterId Encounter, ArenaManifest Manifest, WorldPosition Origin); public sealed record ArenaReady(EncounterId Encounter, ArenaManifest Manifest); public sealed record ArenaLoadFailed(EncounterId Encounter, string Reason); public sealed record EncounterAborted(EncounterId Encounter, EncounterAbortReason Reason); public sealed record EncounterEnded(EncounterId Encounter, SimulationTick Tick); public interface IArenaWireEvent { Sequence Sequence { get; } SimulationTick Tick { get; } } public interface IBossWireEvent { Sequence Sequence { get; } SimulationTick Tick { get; } } public readonly struct ProtocolVersion : IEquatable<ProtocolVersion> { public static readonly ProtocolVersion Current = new ProtocolVersion(17); public int Value { get; } public ProtocolVersion(int value) { Value = value; } public bool Equals(ProtocolVersion other) { return Value == other.Value; } public override bool Equals(object? obj) { if (obj is ProtocolVersion other) { return Equals(other); } return false; } public override int GetHashCode() { return Value; } public override string ToString() { return Value.ToString(); } public static bool operator ==(ProtocolVersion left, ProtocolVersion right) { return left.Equals(right); } public static bool operator !=(ProtocolVersion left, ProtocolVersion right) { return !left.Equals(right); } } public readonly struct Sequence : IEquatable<Sequence>, IComparable<Sequence> { private readonly long _value; public long Value => _value; public Sequence(long value) { _value = value; } public Sequence Next() { return new Sequence(_value + 1); } public int CompareTo(Sequence other) { long value = _value; return value.CompareTo(other._value); } public bool Equals(Sequence other) { return _value == other._value; } public override bool Equals(object? obj) { if (obj is Sequence other) { return Equals(other); } return false; } public override int GetHashCode() { long value = _value; return value.GetHashCode(); } public override string ToString() { return $"seq:{_value}"; } public static bool operator ==(Sequence left, Sequence right) { return left.Equals(right); } public static bool operator !=(Sequence left, Sequence right) { return !left.Equals(right); } public static bool operator <(Sequence left, Sequence right) { return left.CompareTo(right) < 0; } public static bool operator >(Sequence left, Sequence right) { return left.CompareTo(right) > 0; } public static bool operator <=(Sequence left, Sequence right) { return left.CompareTo(right) <= 0; } public static bool operator >=(Sequence left, Sequence right) { return left.CompareTo(right) >= 0; } } public readonly struct SimulationTick : IEquatable<SimulationTick>, IComparable<SimulationTick> { private readonly long _value; public long Value => _value; public SimulationTick(long value) { _value = value; } public int CompareTo(SimulationTick other) { long value = _value; return value.CompareTo(other._value); } public bool Equals(SimulationTick other) { return _value == other._value; } public override bool Equals(object? obj) { if (obj is SimulationTick other) { return Equals(other); } return false; } public override int GetHashCode() { long value = _value; return value.GetHashCode(); } public override string ToString() { return $"tick:{_value}"; } public static bool operator ==(SimulationTick left, SimulationTick right) { return left.Equals(right); } public static bool operator !=(SimulationTick left, SimulationTick right) { return !left.Equals(right); } } public static class WireCodec { private const int MaxVolleyTargets = 32; private const byte BossAppearedTag = 1; private const byte BossTelegraphedTag = 2; private const byte BossCommittedTag = 3; private const byte BossPhaseChangedTag = 4; private const byte BossWeakPointTag = 5; private const byte BossDamagedTag = 6; private const byte BossDefeatedTag = 7; private const byte BossRelocatedTag = 8; private const byte BossEnragedTag = 9; private const byte BossBeganTag = 10; private const byte ArenaMechanismActivatedTag = 1; private const byte ArenaExitUnlockedTag = 2; public static byte[] Serialize(BossSnapshot snapshot) { WireWriter wireWriter = new WireWriter(); WriteBossSnapshot(wireWriter, snapshot); return wireWriter.ToArray(); } public static BossSnapshot DeserializeBossSnapshot(byte[] payload) { WireReader r = new WireReader(payload); BossSnapshot result = ReadBossSnapshot(r); RequireEnd(r); return result; } public static byte[] Serialize(ArenaSnapshot snapshot) { WireWriter wireWriter = new WireWriter(); WriteArenaSnapshot(wireWriter, snapshot); return wireWriter.ToArray(); } public static ArenaSnapshot DeserializeArenaSnapshot(byte[] payload) { WireReader r = new WireReader(payload); ArenaSnapshot result = ReadArenaSnapshot(r); RequireEnd(r); return result; } public static byte[] Serialize(EncounterBaseline baseline) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) WireWriter wireWriter = new WireWriter(); EncounterId encounter = baseline.Encounter; WriteInt(wireWriter, ((EncounterId)(ref encounter)).Value); WriteInt(wireWriter, baseline.ProtocolVersion.Value); wireWriter.WriteString(baseline.ArenaId); WriteInt(wireWriter, baseline.ArenaVersion); WriteContentHash(wireWriter, baseline.ContentHash); WriteWorldPosition(wireWriter, baseline.ArenaOrigin); wireWriter.WriteInt64(baseline.Tick.Value); WriteInt(wireWriter, baseline.EncounterPhaseId); WriteBossSnapshot(wireWriter, baseline.Boss); WriteArenaSnapshot(wireWriter, baseline.Arena); wireWriter.WriteInt64(baseline.LastProcessedBossEventSequence.Value); wireWriter.WriteInt64(baseline.LastProcessedArenaEventSequence.Value); return wireWriter.ToArray(); } public static EncounterBaseline DeserializeBaseline(byte[] payload) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) WireReader wireReader = new WireReader(payload); EncounterBaseline result = new EncounterBaseline(new EncounterId(wireReader.ReadInt32()), new ProtocolVersion(wireReader.ReadInt32()), wireReader.ReadString(), wireReader.ReadInt32(), ReadContentHash(wireReader), ReadWorldPosition(wireReader), new SimulationTick(wireReader.ReadInt64()), wireReader.ReadInt32(), ReadBossSnapshot(wireReader), ReadArenaSnapshot(wireReader), new Sequence(wireReader.ReadInt64()), new Sequence(wireReader.ReadInt64())); RequireEnd(wireReader); return result; } public static byte[] Serialize(EnterArena message) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) WireWriter wireWriter = new WireWriter(); EncounterId encounter = message.Encounter; WriteInt(wireWriter, ((EncounterId)(ref encounter)).Value); WriteManifest(wireWriter, message.Manifest); WriteWorldPosition(wireWriter, message.Origin); return wireWriter.ToArray(); } public static EnterArena DeserializeEnterArena(byte[] payload) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) WireReader wireReader = new WireReader(payload); EnterArena result = new EnterArena(new EncounterId(wireReader.ReadInt32()), ReadManifest(wireReader), ReadWorldPosition(wireReader)); RequireEnd(wireReader); return result; } public static byte[] Serialize(ArenaReady message) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) WireWriter wireWriter = new WireWriter(); EncounterId encounter = message.Encounter; WriteInt(wireWriter, ((EncounterId)(ref encounter)).Value); WriteManifest(wireWriter, message.Manifest); return wireWriter.ToArray(); } public static ArenaReady DeserializeArenaReady(byte[] payload) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) WireReader wireReader = new WireReader(payload); ArenaReady result = new ArenaReady(new EncounterId(wireReader.ReadInt32()), ReadManifest(wireReader)); RequireEnd(wireReader); return result; } public static byte[] Serialize(ArenaLoadFailed message) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) WireWriter wireWriter = new WireWriter(); EncounterId encounter = message.Encounter; WriteInt(wireWriter, ((EncounterId)(ref encounter)).Value); wireWriter.WriteString(message.Reason); return wireWriter.ToArray(); } public static ArenaLoadFailed DeserializeArenaLoadFailed(byte[] payload) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) WireReader wireReader = new WireReader(payload); ArenaLoadFailed result = new ArenaLoadFailed(new EncounterId(wireReader.ReadInt32()), wireReader.ReadString()); RequireEnd(wireReader); return result; } public static byte[] Serialize(EncounterAborted message) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) WireWriter wireWriter = new WireWriter(); EncounterId encounter = message.Encounter; WriteInt(wireWriter, ((EncounterId)(ref encounter)).Value); WriteInt(wireWriter, (int)message.Reason); return wireWriter.ToArray(); } public static EncounterAborted DeserializeEncounterAborted(byte[] payload) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) WireReader wireReader = new WireReader(payload); EncounterId encounter = new EncounterId(wireReader.ReadInt32()); int num = wireReader.ReadInt32(); if (num < 0 || num > 5) { throw new InvalidDataException($"Unknown encounter-abort reason {num}."); } EncounterAborted result = new EncounterAborted(encounter, (EncounterAbortReason)num); RequireEnd(wireReader); return result; } public static byte[] Serialize(EncounterEnded message) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) WireWriter wireWriter = new WireWriter(); EncounterId encounter = message.Encounter; WriteInt(wireWriter, ((EncounterId)(ref encounter)).Value); wireWriter.WriteInt64(message.Tick.Value); return wireWriter.ToArray(); } public static EncounterEnded DeserializeEncounterEnded(byte[] payload) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) WireReader wireReader = new WireReader(payload); EncounterEnded result = new EncounterEnded(new EncounterId(wireReader.ReadInt32()), new SimulationTick(wireReader.ReadInt64())); RequireEnd(wireReader); return result; } public static byte[] Serialize(ClientHitRequest message) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) WireWriter wireWriter = new WireWriter(); EncounterId encounter = message.Encounter; WriteInt(wireWriter, ((EncounterId)(ref encounter)).Value); WriteInt(wireWriter, message.RequestSequence); wireWriter.WriteSingle(message.DamageCandidate); wireWriter.WriteBool(message.AttackerPosition.HasValue); if (message.AttackerPosition.HasValue) { WriteWorldPosition(wireWriter, message.AttackerPosition.Value); } return wireWriter.ToArray(); } public static ClientHitRequest DeserializeClientHitRequest(byte[] payload) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) WireReader wireReader = new WireReader(payload); EncounterId encounter = new EncounterId(wireReader.ReadInt32()); int requestSequence = wireReader.ReadInt32(); float damageCandidate = wireReader.ReadSingle(); WorldPosition? attackerPosition = (wireReader.ReadBool() ? new WorldPosition?(ReadWorldPosition(wireReader)) : ((WorldPosition?)null)); ClientHitRequest result = new ClientHitRequest(encounter, requestSequence, damageCandidate, attackerPosition); RequireEnd(wireReader); return result; } public static byte[] Serialize(BossHitPlayer message) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) WireWriter wireWriter = new WireWriter(); EncounterId encounter = message.Encounter; WriteInt(wireWriter, ((EncounterId)(ref encounter)).Value); WriteInt(wireWriter, message.Amount); return wireWriter.ToArray(); } public static BossHitPlayer DeserializeBossHitPlayer(byte[] payload) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) WireReader wireReader = new WireReader(payload); BossHitPlayer result = new BossHitPlayer(new EncounterId(wireReader.ReadInt32()), wireReader.ReadInt32()); RequireEnd(wireReader); return result; } public static byte[] Serialize(CrateDropped message) { WireWriter wireWriter = new WireWriter(); WriteWorldPosition(wireWriter, message.At); WriteInt(wireWriter, message.PileKind); WriteInt(wireWriter, message.PileIndex); wireWriter.WriteBool(message.Explosive); return wireWriter.ToArray(); } public static CrateDropped DeserializeCrateDropped(byte[] payload) { WireReader wireReader = new WireReader(payload); CrateDropped result = new CrateDropped(ReadWorldPosition(wireReader), wireReader.ReadInt32(), wireReader.ReadInt32(), wireReader.ReadBool()); RequireEnd(wireReader); return result; } public static byte[] Serialize(CratesTaken message) { WireWriter wireWriter = new WireWriter(); WriteWorldPosition(wireWriter, message.At); WriteInt(wireWriter, message.PileKind); WriteInt(wireWriter, message.PileIndex); WriteInt(wireWriter, message.Count); wireWriter.WriteSingle(message.Radius); return wireWriter.ToArray(); } public static CratesTaken DeserializeCratesTaken(byte[] payload) { WireReader wireReader = new WireReader(payload); CratesTaken result = new CratesTaken(ReadWorldPosition(wireReader), wireReader.ReadInt32(), wireReader.ReadInt32(), wireReader.ReadInt32(), wireReader.ReadSingle()); RequireEnd(wireReader); return result; } public static byte[] Serialize(CrateDestroyed message) { WireWriter wireWriter = new WireWriter(); WriteInt(wireWriter, message.CrateId); WriteInt(wireWriter, message.Death); return wireWriter.ToArray(); } public static CrateDestroyed DeserializeCrateDestroyed(byte[] payload) { WireReader wireReader = new WireReader(payload); CrateDestroyed result = new CrateDestroyed(wireReader.ReadInt32(), wireReader.ReadInt32()); RequireEnd(wireReader); return result; } public static byte[] Serialize(CrateDestroyRequested message) { WireWriter wireWriter = new WireWriter(); WriteInt(wireWriter, message.CrateId); WriteInt(wireWriter, message.Death); return wireWriter.ToArray(); } public static CrateDestroyRequested DeserializeCrateDestroyRequested(byte[] payload) { WireReader wireReader = new WireReader(payload); CrateDestroyRequested result = new CrateDestroyRequested(wireReader.ReadInt32(), wireReader.ReadInt32()); RequireEnd(wireReader); return result; } public static byte[] Serialize(CratesSetDown message) { WireWriter wireWriter = new WireWriter(); WriteWorldPosition(wireWriter, message.From); WriteWorldPosition(wireWriter, message.At); WriteInt(wireWriter, message.PileKind); WriteInt(wireWriter, message.PileIndex); WriteInt(wireWriter, message.Count); WriteInt(wireWriter, message.Seed); WriteInt(wireWriter, message.Explosives); return wireWriter.ToArray(); } public static CratesSetDown DeserializeCratesSetDown(byte[] payload) { WireReader wireReader = new WireReader(payload); CratesSetDown result = new CratesSetDown(ReadWorldPosition(wireReader), ReadWorldPosition(wireReader), wireReader.ReadInt32(), wireReader.ReadInt32(), wireReader.ReadInt32(), wireReader.ReadInt32(), wireReader.ReadInt32()); RequireEnd(wireReader); return result; } public static byte[] Serialize(CrateThrown message) { WireWriter wireWriter = new WireWriter(); WriteWorldPosition(wireWriter, message.From); WriteWorldPosition(wireWriter, message.To); wireWriter.WriteSingle(message.FlightSeconds); wireWriter.WriteSingle(message.ApexHeight); return wireWriter.ToArray(); } public static CrateThrown DeserializeCrateThrown(byte[] payload) { WireReader wireReader = new WireReader(payload); CrateThrown result = new CrateThrown(ReadWorldPosition(wireReader), ReadWorldPosition(wireReader), wireReader.ReadSingle(), wireReader.ReadSingle()); RequireEnd(wireReader); return result; } public static byte[] Serialize(CrateVolleyFired message) { WireWriter wireWriter = new WireWriter(); WriteInt(wireWriter, message.Targets.Count); for (int i = 0; i < message.Targets.Count; i++) { WriteWorldPosition(wireWriter, message.Targets[i].Current); WriteWorldPosition(wireWriter, message.Targets[i].Lead); } WriteInt(wireWriter, message.PileKind); WriteInt(wireWriter, message.PileIndex); WriteInt(wireWriter, message.Seed); WriteInt(wireWriter, message.Count); wireWriter.WriteSingle(message.SpreadMinRadius); wireWriter.WriteSingle(message.SpreadMaxRadius); wireWriter.WriteSingle(message.LiftHeight); wireWriter.WriteSingle(message.LiftSeconds); wireWriter.WriteSingle(message.HoldSeconds); wireWriter.WriteSingle(message.FlightSeconds); wireWriter.WriteSingle(message.ApexHeight); wireWriter.WriteSingle(message.LeadShare); wireWriter.WriteSingle(message.FireIntervalSeconds); return wireWriter.ToArray(); } public static CrateVolleyFired DeserializeCrateVolleyFired(byte[] payload) { WireReader wireReader = new WireReader(payload); int num = wireReader.ReadInt32(); if (num < 0 || num > 32) { throw new InvalidDataException($"CrateVolleyFired target count {num} is outside 0..{32}."); } List<CrateVolleyTarget> list = new List<CrateVolleyTarget>(num); for (int i = 0; i < num; i++) { list.Add(new CrateVolleyTarget(ReadWorldPosition(wireReader), ReadWorldPosition(wireReader))); } CrateVolleyFired result = new CrateVolleyFired(list, wireReader.ReadInt32(), wireReader.ReadInt32(), wireReader.ReadInt32(), wireReader.ReadInt32(), wireReader.ReadSingle(), wireReader.ReadSingle(), wireReader.ReadSingle(), wireReader.ReadSingle(), wireReader.ReadSingle(), wireReader.ReadSingle(), wireReader.ReadSingle(), wireReader.ReadSingle(), wireReader.ReadSingle()); RequireEnd(wireReader); return result; } public static byte[] Serialize(ArenaLevelDeclared message) { WireWriter wireWriter = new WireWriter(); WriteArenaLevelId(wireWriter, message.Level); wireWriter.WriteBool(message.IsBossArena); return wireWriter.ToArray(); } public static ArenaLevelDeclared DeserializeArenaLevelDeclared(byte[] payload) { WireReader wireReader = new WireReader(payload); ArenaLevelDeclared result = new ArenaLevelDeclared(ReadArenaLevelId(wireReader), wireReader.ReadBool()); RequireEnd(wireReader); return result; } public static byte[] Serialize(ArenaLevelRequested message) { WireWriter wireWriter = new WireWriter(); WriteArenaLevelId(wireWriter, message.Level); return wireWriter.ToArray(); } public static ArenaLevelRequested DeserializeArenaLevelRequested(byte[] payload) { WireReader r = new WireReader(payload); ArenaLevelRequested result = new ArenaLevelRequested(ReadArenaLevelId(r)); RequireEnd(r); return result; } public static byte[] Serialize(IBossWireEvent bossEvent) { WireWriter wireWriter = new WireWriter(); WriteBossEvent(wireWriter, bossEvent); return wireWriter.ToArray(); } public static IBossWireEvent DeserializeBossEvent(byte[] payload) { WireReader r = new WireReader(payload); IBossWireEvent result = ReadBossEvent(r); RequireEnd(r); return result; } public static byte[] Serialize(IArenaWireEvent arenaEvent) { WireWriter wireWriter = new WireWriter(); WriteArenaEvent(wireWriter, arenaEvent); return wireWriter.ToArray(); } public static IArenaWireEvent DeserializeArenaEvent(byte[] payload) { WireReader r = new WireReader(payload); IArenaWireEvent result = ReadArenaEvent(r); RequireEnd(r); return result; } private static void WriteBossSnapshot(WireWriter w, BossSnapshot s) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_001b: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) EncounterId encounter = s.Encounter; WriteInt(w, ((EncounterId)(ref encounter)).Value); BossInstanceId boss = s.Boss; WriteInt(w, ((BossInstanceId)(ref boss)).Value); DefinitionId definition = s.Definition; WriteInt(w, ((DefinitionId)(ref definition)).Value); WriteInt(w, s.ProtocolVersion.Value); w.WriteInt64(s.Tick.Value); WriteInt(w, s.PhaseId); WriteInt(w, s.StateId); w.WriteInt64(s.StateStartTick.Value); WriteNullableAttack(w, s.ActiveAttack); WriteNullableInt(w, s.ActiveAttackDefinitionId); WriteNullableParticipant(w, s.Target); WriteVector(w, s.Position); w.WriteSingle(s.PositionHeight); WriteVector(w, s.Facing); WriteInt(w, s.Health); WriteInt(w, s.MaxHealth); w.WriteBool(s.WeakPointExposed); w.WriteBool(s.Enraged); w.WriteBool(s.Begun); w.WriteInt64(s.LastProcessedBossEventSequence.Value); } private static BossSnapshot ReadBossSnapshot(WireReader r) { //IL_0006: 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_001c: 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_006d: Unknown result type (might be due to invalid IL or missing references) return new BossSnapshot(new EncounterId(r.ReadInt32()), new BossInstanceId(r.ReadInt32()), new DefinitionId(r.ReadInt32()), new ProtocolVersion(r.ReadInt32()), new SimulationTick(r.ReadInt64()), r.ReadInt32(), r.ReadInt32(), new SimulationTick(r.ReadInt64()), ReadNullableAttack(r), ReadNullableInt(r), ReadNullableParticipant(r), ReadVector(r), r.ReadSingle(), ReadVector(r), r.ReadInt32(), r.ReadInt32(), r.ReadBool(), r.ReadBool(), r.ReadBool(), new Sequence(r.ReadInt64())); } private static void WriteArenaSnapshot(WireWriter w, ArenaSnapshot s) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) EncounterId encounter = s.Encounter; WriteInt(w, ((EncounterId)(ref encounter)).Value); w.WriteString(s.ArenaId); WriteInt(w, s.ArenaVersion); WriteInt(w, s.ProtocolVersion.Value); w.WriteInt64(s.Tick.Value); WriteInt(w, s.ActiveMechanismGroups.Count); for (int i = 0; i < s.ActiveMechanismGroups.Count; i++) { MechanismGroupId val = s.ActiveMechanismGroups[i]; w.WriteString(((MechanismGroupId)(ref val)).Value); } w.WriteBool(s.ExitUnlocked); w.WriteInt64(s.LastProcessedArenaEventSequence.Value); } private static ArenaSnapshot ReadArenaSnapshot(WireReader r) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) EncounterId encounter = default(EncounterId); ((EncounterId)(ref encounter))..ctor(r.ReadInt32()); string arenaId = r.ReadString(); int arenaVersion = r.ReadInt32(); ProtocolVersion protocolVersion = new ProtocolVersion(r.ReadInt32()); SimulationTick tick = new SimulationTick(r.ReadInt64()); int num = r.ReadInt32(); if (num < 0) { throw new InvalidDataException($"ArenaSnapshot mechanism-group count {num} is negative."); } List<MechanismGroupId> list = new List<MechanismGroupId>(num); for (int i = 0; i < num; i++) { list.Add(new MechanismGroupId(r.ReadString())); } bool exitUnlocked = r.ReadBool(); return new ArenaSnapshot(LastProcessedArenaEventSequence: new Sequence(r.ReadInt64()), Encounter: encounter, ArenaId: arenaId, ArenaVersion: arenaVersion, ProtocolVersion: protocolVersion, Tick: tick, ActiveMechanismGroups: list, ExitUnlocked: exitUnlocked); } private static void WriteBossEvent(WireWriter w, IBossWireEvent e) { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) if (!(e is BossAppearedEvent bossAppearedEvent)) { AttackInstanceId attack; if (!(e is BossAttackTelegraphedEvent bossAttackTelegraphedEvent)) { if (!(e is BossAttackCommittedEvent bossAttackCommittedEvent)) { if (!(e is BossPhaseChangedEvent bossPhaseChangedEvent)) { if (!(e is BossWeakPointChangedEvent bossWeakPointChangedEvent)) { if (!(e is BossDamagedEvent bossDamagedEvent)) { if (!(e is BossRelocatedEvent bossRelocatedEvent)) { if (!(e is BossBeganEvent bossBeganEvent)) { if (!(e is BossEnragedEvent bossEnragedEvent)) { if (!(e is BossDefeatedEvent bossDefeatedEvent)) { if (e == null) { throw new ArgumentNullException("e"); } throw new ArgumentOutOfRangeException("e", e.GetType().Name, "No wire encoding for this boss event."); } WriteBossHeader(w, 7, bossDefeatedEvent.Sequence, bossDefeatedEvent.Tick); } else { WriteBossHeader(w, 9, bossEnragedEvent.Sequence, bossEnragedEvent.Tick); w.WriteBool(bossEnragedEvent.Enraged); } } else { WriteBossHeader(w, 10, bossBeganEvent.Sequence, bossBeganEvent.Tick); } } else { WriteBossHeader(w, 8, bossRelocatedEvent.Sequence, bossRelocatedEvent.Tick); WriteInt(w, bossRelocatedEvent.StationIndex); WriteInt(w, bossRelocatedEvent.AnchorIndex); WriteVector(w, bossRelocatedEvent.Position); w.WriteSingle(bossRelocatedEvent.Height); } } else { WriteBossHeader(w, 6, bossDamagedEvent.Sequence, bossDamagedEvent.Tick); WriteInt(w, bossDamagedEvent.Amount); WriteInt(w, bossDamagedEvent.RemainingHealth); w.WriteBool(bossDamagedEvent.WeakPointHit); } } else { WriteBossHeader(w, 5, bossWeakPointChangedEvent.Sequence, bossWeakPointChangedEvent.Tick); w.WriteBool(bossWeakPointChangedEvent.Exposed); } } else { WriteBossHeader(w, 4, bossPhaseChangedEvent.Sequence, bossPhaseChangedEvent.Tick); WriteInt(w, bossPhaseChangedEvent.PhaseId); } } else { WriteBossHeader(w, 3, bossAttackCommittedEvent.Sequence, bossAttackCommittedEvent.Tick); attack = bossAttackCommittedEvent.Attack; w.WriteInt64(((AttackInstanceId)(ref attack)).Value); WriteInt(w, bossAttackCommittedEvent.AttackDefinitionId); WriteVector(w, bossAttackCommittedEvent.AimPoint); } } else { WriteBossHeader(w, 2, bossAttackTelegraphedEvent.Sequence, bossAttackTelegraphedEvent.Tick); attack = bossAttackTelegraphedEvent.Attack; w.WriteInt64(((AttackInstanceId)(ref attack)).Value); WriteInt(w, bossAttackTelegraphedEvent.AttackDefinitionId); WriteVector(w, bossAttackTelegraphedEvent.AimPoint); w.WriteSingle(bossAttackTelegraphedEvent.TelegraphSeconds); } } else { WriteBossHeader(w, 1, bossAppearedEvent.Sequence, bossAppearedEvent.Tick); WriteInt(w, bossAppearedEvent.PhaseId); } } private static IBossWireEvent ReadBossEvent(WireReader r) { //IL_006f: 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_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_00f0: Unknown result type (might be due to invalid IL or missing references) byte b = r.ReadBytes(1)[0]; Sequence sequence = new Sequence(r.ReadInt64()); SimulationTick tick = new SimulationTick(r.ReadInt64()); return b switch { 1 => new BossAppearedEvent(sequence, tick, r.ReadInt32()), 2 => new BossAttackTelegraphedEvent(sequence, tick, new AttackInstanceId(r.ReadInt64()), r.ReadInt32(), ReadVector(r), r.ReadSingle()), 3 => new BossAttackCommittedEvent(sequence, tick, new AttackInstanceId(r.ReadInt64()), r.ReadInt32(), ReadVector(r)), 4 => new BossPhaseChangedEvent(sequence, tick, r.ReadInt32()), 5 => new BossWeakPointChangedEvent(sequence, tick, r.ReadBool()), 6 => new BossDamagedEvent(sequence, tick, r.ReadInt32(), r.ReadInt32(), r.ReadBool()), 8 => new BossRelocatedEvent(sequence, tick, r.ReadInt32(), r.ReadInt32(), ReadVector(r), r.ReadSingle()), 10 => new BossBeganEvent(sequence, tick), 9 => new BossEnragedEvent(sequence, tick, r.ReadBool()), 7 => new BossDefeatedEvent(sequence, tick), _ => throw new InvalidDataException($"Unknown boss wire-event tag {b}."), }; } private static void WriteArenaEvent(WireWriter w, IArenaWireEvent e) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!(e is ArenaMechanismGroupActivatedEvent arenaMechanismGroupActivatedEvent)) { if (!(e is ArenaExitUnlockedEvent arenaExitUnlockedEvent)) { if (e == null) { throw new ArgumentNullException("e"); } throw new ArgumentOutOfRangeException("e", e.GetType().Name, "No wire encoding for this arena event."); } WriteArenaHeader(w, 2, arenaExitUnlockedEvent.Sequence, arenaExitUnlockedEvent.Tick); } else { WriteArenaHeader(w, 1, arenaMechanismGroupActivatedEvent.Sequence, arenaMechanismGroupActivatedEvent.Tick); MechanismGroupId val = arenaMechanismGroupActivatedEvent.Group; w.WriteString(((MechanismGroupId)(ref val)).Value); } } private static IArenaWireEvent ReadArenaEvent(WireReader r) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) byte b = r.ReadBytes(1)[0]; Sequence sequence = new Sequence(r.ReadInt64()); SimulationTick tick = new SimulationTick(r.ReadInt64()); return b switch { 1 => new ArenaMechanismGroupActivatedEvent(sequence, tick, new MechanismGroupId(r.ReadString())), 2 => new ArenaExitUnlockedEvent(sequence, tick), _ => throw new InvalidDataException($"Unknown arena wire-event tag {b}."), }; } private static void WriteBossHeader(WireWriter w, byte tag, Sequence sequence, SimulationTick tick) { w.WriteBytes(new byte[1] { tag }); w.WriteInt64(sequence.Value); w.WriteInt64(tick.Value); } private static void WriteArenaHeader(WireWriter w, byte tag, Sequence sequence, SimulationTick tick) { w.WriteBytes(new byte[1] { tag }); w.WriteInt64(sequence.Value); w.WriteInt64(tick.Value); } private static void WriteInt(WireWriter w, int value) { w.WriteInt32(value); } private static void WriteVector(WireWriter w, SimVector2 v) { w.WriteSingle(((SimVector2)(ref v)).X); w.WriteSingle(((SimVector2)(ref v)).Z); } private static SimVector2 ReadVector(WireReader r) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new SimVector2(r.ReadSingle(), r.ReadSingle()); } private static void WriteNullableAttack(WireWriter w, AttackInstanceId? value) { //IL_0019: 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) w.WriteBool(value.HasValue); if (value.HasValue) { AttackInstanceId value2 = value.Value; w.WriteInt64(((AttackInstanceId)(ref value2)).Value); } } private static AttackInstanceId? ReadNullableAttack(WireReader r) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (!r.ReadBool()) { return null; } return new AttackInstanceId(r.ReadInt64()); } private static void WriteNullableParticipant(WireWriter w, ParticipantId? value) { //IL_0019: 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) w.WriteBool(value.HasValue); if (value.HasValue) { ParticipantId value2 = value.Value; w.WriteInt32(((ParticipantId)(ref value2)).Value); } } private static ParticipantId? ReadNullableParticipant(WireReader r) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (!r.ReadBool()) { return null; } return new ParticipantId(r.ReadInt32()); } private static void WriteNullableInt(WireWriter w, int? value) { w.WriteBool(value.HasValue); if (value.HasValue) { w.WriteInt32(value.Value); } } private static int? ReadNullableInt(WireReader r) { if (!r.ReadBool()) { return null; } return r.ReadInt32(); } private static void WriteManifest(WireWriter w, ArenaManifest m) { w.WriteString(m.ArenaId); WriteInt(w, m.ArenaVersion); WriteInt(w, m.ContentHashSchemaVersion.Value); WriteContentHash(w, m.ContentHash); WriteInt(w, m.ProtocolVersion); w.WriteString(m.BundleVersion); } private static ArenaManifest ReadManifest(WireReader r) { return new ArenaManifest(r.ReadString(), r.ReadInt32(), new ContentHashSchemaVersion(r.ReadInt32()), ReadContentHash(r), r.ReadInt32(), r.ReadString()); } private static void WriteWorldPosition(WireWriter w, WorldPosition p) { w.WriteSingle(p.X); w.WriteSingle(p.Y); w.WriteSingle(p.Z); } private static WorldPosition ReadWorldPosition(WireReader r) { return new WorldPosition(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); } private static void WriteArenaLevelId(WireWriter w, ArenaLevelId level) { WriteInt(w, level.Environment); WriteInt(w, level.LevelIndex); } private static ArenaLevelId ReadArenaLevelId(WireReader r) { return new ArenaLevelId(r.ReadInt32(), r.ReadInt32()); } private static void WriteContentHash(WireWriter w, ContentHash hash) { bool flag = hash.Length == 32; w.WriteBool(flag); if (flag) { w.WriteBytes(hash.ToArray()); } } private static ContentHash ReadContentHash(WireReader r) { if (!r.ReadBool()) { return default(ContentHash); } return new ContentHash(r.ReadBytes(32)); } private static void RequireEnd(WireReader r) { if (!r.AtEnd) { throw new InvalidDataException("Wire payload has trailing bytes after the decoded value."); } } } public sealed class WireReader { private readonly byte[] _buffer; private int _position; public bool AtEnd => _position == _buffer.Length; public WireReader(byte[] buffer) { _buffer = buffer ?? throw new ArgumentNullException("buffer"); } public bool ReadBool() { return ReadRawByte() != 0; } public int ReadInt32() { byte num = ReadRawByte(); byte b = ReadRawByte(); byte b2 = ReadRawByte(); byte b3 = ReadRawByte(); return num | (b << 8) | (b2 << 16) | (b3 << 24); } public long ReadInt64() { long num = 0L; for (int i = 0; i < 8; i++) { num |= (long)((ulong)ReadRawByte() << 8 * i); } return num; } public float ReadSingle() { byte[] array = ReadBytes(4); if (!BitConverter.IsLittleEndian) { Array.Reverse((Array)array); } return BitConverter.ToSingle(array, 0); } public string ReadString() { int num = ReadInt32(); if (num < 0) { throw new EndOfStreamException($"Wire string length {num} is negative."); } byte[] bytes = ReadBytes(num); return Encoding.UTF8.GetString(bytes); } public byte[] ReadBytes(int count) { if (count < 0) { throw new EndOfStreamException($"Requested {count} bytes."); } if (_position + count > _buffer.Length) { throw new EndOfStreamException($"Wire payload is truncated: needed {count} bytes at offset {_position} of {_buffer.Length}."); } byte[] array = new byte[count]; Array.Copy(_buffer, _position, array, 0, count); _position += count; return array; } private byte ReadRawByte() { if (_position >= _buffer.Length) { throw new EndOfStreamException($"Wire payload is truncated: read past the end at offset {_position} of {_buffer.Length}."); } return _buffer[_position++]; } } public sealed class WireWriter { private readonly MemoryStream _stream = new MemoryStream(); public void WriteBool(bool value) { _stream.WriteByte(value ? ((byte)1) : ((byte)0)); } public void WriteInt32(int value) { _stream.WriteByte((byte)value); _stream.WriteByte((byte)(value >> 8)); _stream.WriteByte((byte)(value >> 16)); _stream.WriteByte((byte)(value >> 24)); } public void WriteInt64(long value) { for (int i = 0; i < 8; i++) { _stream.WriteByte((byte)(value >> 8 * i)); } } public void WriteSingle(float value) { byte[] bytes = BitConverter.GetBytes(value); if (!BitConverter.IsLittleEndian) { Array.Reverse((Array)bytes); } _stream.Write(bytes, 0, bytes.Length); } public void WriteString(string value) { if (value == null) { throw new ArgumentNullException("value", "A required wire string reached the writer as null."); } byte[] bytes = Encoding.UTF8.GetBytes(value); WriteInt32(bytes.Length); _stream.Write(bytes, 0, bytes.Length); } public void WriteBytes(byte[] value) { if (value == null) { throw new ArgumentNullException("value"); } _stream.Write(value, 0, value.Length); } public byte[] ToArray() { return _stream.ToArray(); } } public readonly struct WorldPosition : IEquatable<WorldPosition> { public float X { get; } public float Y { get; } public float Z { get; } public WorldPosition(float x, float y, float z) { X = x; Y = y; Z = z; } public bool Equals(WorldPosition other) { if (X.Equals(other.X) && Y.Equals(other.Y)) { return Z.Equals(other.Z); } return false; } public override bool Equals(object? obj) { if (obj is WorldPosition other) { return Equals(other); } return false; } public override int GetHashCode() { return (((X.GetHashCode() * 397) ^ Y.GetHashCode()) * 397) ^ Z.GetHashCode(); } public override string ToString() { return $"({X:0.##}, {Y:0.##}, {Z:0.##})"; } public static bool operator ==(WorldPosition left, WorldPosition right) { return left.Equals(right); } public static bool operator !=(WorldPosition left, WorldPosition right) { return !left.Equals(right); } } } namespace FalseGods.Protocol.Arena { public sealed record ArenaContentArtifact(ArenaContentDefinition Definition, ContentHashSchemaVersion SchemaVersion, int ProtocolVersion, string BundleVersion, IReadOnlyList<ArenaParityNode> Parity, IReadOnlyList<MaterialBorrowPlacement> MaterialBorrowPlacements) { public const int ArtifactFormatVersion = 2; private const string Magic = "FGARENA"; private const char Sep = '\t'; private const string Nil = "-"; public ContentHash ComputeContentHash() { return ContentHashComputer.Compute(Definition, SchemaVersion); } public ArenaManifest ToManifest() { return new ArenaManifest(Definition.ArenaId, Definition.ArenaVersion, SchemaVersion, ComputeContentHash(), ProtocolVersion, BundleVersion); } public string Serialize() { StringBuilder stringBuilder = new StringBuilder(); Row(stringBuilder, "FGARENA", 2.ToString(CultureInfo.InvariantCulture)); Row(stringBuilder, "arenaId", Definition.ArenaId); Row(stringBuilder, "arenaVersion", Int(Definition.ArenaVersion)); Row(stringBuilder, "arenaContentId", Definition.ArenaContentId); Row(stringBuilder, "schemaVersion", Int(SchemaVersion.Value)); Row(stringBuilder, "protocolVersion", Int(ProtocolVersion)); Row(stringBuilder, "bundleVersion", BundleVersion); foreach (AuthoredNode node in Definition.Nodes) { Row(stringBuilder, Fields("node", node.MarkerId.ToCanonicalString(), node.NodeKind, Marker(node.ParentMarkerId), Transform(node.LocalTransform))); } foreach (VanillaProxyDefinition vanillaProxy in Definition.VanillaProxies) { Row(stringBuilder, Fields("proxy", vanillaProxy.MarkerId.ToCanonicalString(), vanillaProxy.AddressableKeyOrGuid, Transform(vanillaProxy.LocalTransform))); } foreach (ColliderDefinition collider in Definition.Colliders) { Row(stringBuilder, Fields("collider", collider.MarkerId.ToCanonicalString(), collider.ColliderKind, collider.LayerName, Geometry(collider.GeometryParameters))); } foreach (NavDefinition navDefinition in Definition.NavDefinitions) { Row(stringBuilder, Fields("nav", navDefinition.MarkerId.ToCanonicalString(), navDefinition.NavKind, navDefinition.NavmeshPrefabContentId ?? "-", Bounds(navDefinition.Bounds))); } foreach (SpawnDefinition spawn in Definition.Spawns) { Row(stringBuilder, Fields("spawn", spawn.MarkerId.ToCanonicalString(), spawn.SpawnKind, spawn.DefinitionId, Transform(spawn.LocalTransform))); } foreach (MechanismDefinition mechanism in Definition.Mechanisms) { Row(stringBuilder, Fields("mechanism", mechanism.MarkerId.ToCanonicalString(), mechanism.MechanismDefinitionId, mechanism.MechanismGroupId, Transform(mechanism.LocalTransform))); } foreach (MaterialBorrowDefinition materialBorrow in Definition.MaterialBorrows) { Row(stringBuilder, Fields("matborrow", materialBorrow.MarkerId.ToCanonicalString(), materialBorrow.TargetMarkerId.ToCanonicalString(), Int(materialBorrow.TargetSubMaterialIndex), materialBorrow.CarrierGuid, materialBorrow.MaterialName, TargetPathFor(materialBorrow.MarkerId))); } foreach (ArenaParityNode item in Parity) { Row(stringBuilder, Fields("parity", item.Path, item.Kind, Transform(item.LocalTransform))); } return stringBuilder.ToString(); } private string TargetPathFor(StableMarkerId borrowMarkerId) { foreach (MaterialBorrowPlacement materialBorrowPlacement in MaterialBorrowPlacements) { if (materialBorrowPlacement.BorrowMarkerId == borrowMarkerId) { return materialBorrowPlacement.TargetPath; } } throw new ArenaContentExportException($"Material borrow {borrowMarkerId} has no target-path placement to serialize."); } private static string[] Fields(params object[] parts) { List<string> list = new List<string>(); foreach (object obj in parts) { if (obj is string[] collection) { list.AddRange(collection); } else { list.Add((string)obj); } } return list.ToArray(); } private static void Row(StringBuilder sb, params string[] fields) { for (int i = 0; i < fields.Length; i++) { if (i > 0) { sb.Append('\t'); } string text = fields[i]; if (text.IndexOf('\t') >= 0 || text.IndexOf('\n') >= 0) { throw new ArenaContentExportException("Artifact field contains a tab or newline: '" + text + "'."); } sb.Append(text); } sb.Append('\n'); } private static string Int(int value) { return value.ToString(CultureInfo.InvariantCulture); } private static string Flt(float value) { return value.ToString("R", CultureInfo.InvariantCulture); } private static string Dbl(double value) { return value.ToString("R", CultureInfo.InvariantCulture); } private static string Marker(StableMarkerId? m) { if (!m.HasValue) { return "-"; } return m.Value.ToCanonicalString(); } private static string[] Transform(AuthoredTransform t) { return new string[10] { Flt(t.Position.X), Flt(t.Position.Y), Flt(t.Position.Z), Flt(t.Rotation.X), Flt(t.Rotation.Y), Flt(t.Rotation.Z), Flt(t.Rotation.W), Flt(t.Scale.X), Flt(t.Scale.Y), Flt(t.Scale.Z) }; } private static string[] Bounds(AuthoredBounds b) { return new string[6] { Flt(b.Center.X), Flt(b.Center.Y), Flt(b.Center.Z), Flt(b.Size.X), Flt(b.Size.Y), Flt(b.Size.Z) }; } private static string[] Geometry(IReadOnlyList<double> parameters) { return new string[1] { Int(parameters.Count) }.Concat(parameters.Select(Dbl)).ToArray(); } public static ArenaContentArtifact Parse(string text) { if (text == null) { throw new ArgumentNullException("text"); } List<string[]> rows = (from line in text.Replace("\r\n", "\n").Replace('\r', '\n').Split(new char[1] { '\n' }) where line.Length > 0 select line.Split(new char[1] { '\t' })).ToList(); int cursor = 0; int num = ParseInt(Next("FGARENA", 2)[1], "artifact format version"); if (num != 2) { throw Malformed($"unsupported artifact format version {num} (this reader is {2})."); } string arenaId = Next("arenaId", 2)[1]; int arenaVersion = ParseInt(Next("arenaVersion", 2)[1], "arenaVersion"); string arenaContentId = Next("arenaContentId", 2)[1]; int value = ParseInt(Next("schemaVersion", 2)[1], "schemaVersion"); int protocolVersion = ParseInt(Next("protocolVersion", 2)[1], "protocolVersion"); string bundleVersion = Next("bundleVersion", 2)[1]; List<AuthoredNode> list = new List<AuthoredNode>(); List<VanillaProxyDefinition> list2 = new List<VanillaProxyDefinition>(); List<ColliderDefinition> list3 = new List<ColliderDefinition>(); List<NavDefinition> list4 = new List<NavDefinition>(); List<SpawnDefinition> list5 = new List<SpawnDefinition>(); List<MechanismDefinition> list6 = new List<MechanismDefinition>(); List<MaterialBorrowDefinition> list7 = new List<MaterialBorrowDefinition>(); List<MaterialBorrowPlacement> list8 = new List<MaterialBorrowPlacement>(); List<ArenaParityNode> list9 = new List<ArenaParityNode>(); for (; cursor < rows.Count; cursor++) { string[] array = rows[cursor]; switch (array[0]) { case "node": Require(array, 14, "node"); list.Add(new AuthoredNode(Marker(array[1], "node"), array[2], OptionalMarker(array[3], "node parent"), ReadTransform(array, 4, "node"))); break; case "proxy": Require(array, 13, "proxy"); list2.Add(new VanillaProxyDefinition(Marker(array[1], "proxy"), array[2], ReadTransform(array, 3, "proxy"))); break; case "collider": Require(array, 5, "collider"); list3.Add(new ColliderDefinition(Marker(array[1], "collider"), array[2], ReadGeometry(array, 4, "collider"), array[3])); break; case "nav": Require(array, 10, "nav"); list4.Add(new NavDefinition(Marker(array[1], "nav"), array[2], ReadBounds(array, 4, "nav"), (array[3] == "-") ? null : array[3])); break; case "spawn": Require(array, 14, "spawn"); list5.Add(new SpawnDefinition(Marker(array[1], "spawn"), array[2], array[3], ReadTransform(array, 4, "spawn"))); break; case "mechanism": Require(array, 14, "mechanism"); list6.Add(new MechanismDefinition(Marker(array[1], "mechanism"), array[2], array[3], ReadTransform(array, 4, "mechanism"))); break; case "matborrow": { Require(array, 7, "matborrow"); StableMarkerId stableMarkerId = Marker(array[1], "matborrow"); list7.Add(new MaterialBorrowDefinition(stableMarkerId, Marker(array[2], "matborrow target"), ParseInt(array[3], "matborrow subMaterialIndex"), array[4], array[5])); list8.Add(new MaterialBorrowPlacement(stableMarkerId, array[6])); break; } case "parity": Require(array, 13, "parity"); list9.Add(new ArenaParityNode(array[1], array[2], ReadTransform(array, 3, "parity"))); break; default: throw Malformed("unknown row tag '" + array[0] + "'."); } } return new ArenaContentArtifact(new ArenaContentDefinition(arenaId, arenaVersion, arenaContentId, list, list2, list3, list4, list5, list6, list7), new ContentHashSchemaVersion(value), protocolVersion, bundleVersion, list9, list8); string[] Next(string expectedTag, int minFields) { if (cursor >= rows.Count) { throw Malformed("expected a '" + expectedTag + "' row but the artifact ended."); } string[] array2 = rows[cursor++]; if (array2[0] != expectedTag) { throw Malformed("expected a '" + expectedTag + "' row, found '" + array2[0] + "'."); } if (array2.Length < minFields) { throw Malformed($"'{expectedTag}' row has {array2.Length} fields, needs at least {minFields}."); } return array2; } } private static void Require(string[] row, int minFields, string tag) { if (row.Length < minFields) { throw Malformed($"'{tag}' row has {row.Length} fields, needs at least {minFields}."); } } private static StableMarkerId Marker(string token, string where) { if (!Guid.TryParseExact(token, "D", out var result)) { throw Malformed(where + " marker '" + token + "' is not a canonical 'D'-form GUID."); } return new StableMarkerId(result); } private static StableMarkerId? OptionalMarker(string token, string where) { if (!(token == "-")) { return Marker(token, where); } return null; } private static AuthoredTransform ReadTransform(string[] row, int at, string where) { return new AuthoredTransform(new Vector3(ParseFloat(row[at], where), ParseFloat(row[at + 1], where), ParseFloat(row[at + 2], where)), new Quaternion(ParseFloat(row[at + 3], where), ParseFloat(row[at + 4], where), ParseFloat(row[at + 5], where), ParseFloat(row[at + 6], where)), new Vector3(ParseFloat(row[at + 7], where), ParseFloat(row[at + 8], where), ParseFloat(row[at + 9], where))); } private static AuthoredBounds ReadBounds(string[] row, int at, string where) { return new AuthoredBounds(new Vector3(ParseFloat(row[at], where), ParseFloat(row[at + 1], where), ParseFloat(row[at + 2], where)), new Vector3(ParseFloat(row[at + 3], where), ParseFloat(row[at + 4], where), ParseFloat(row[at + 5], where))); } private static IReadOnlyList<double> ReadGeometry(string[] row, int at, string where) { int num = ParseInt(row[at], where + " geometry count"); if (num < 0 || at + 1 + num > row.Length) { throw Malformed($"{where} geometry count {num} does not fit the row."); } double[] array = new double[num]; for (int i = 0; i < num; i++) { array[i] = ParseDouble(row[at + 1 + i], $"{where} geometry[{i}]"); } return array; } private static int ParseInt(string token, string where) { if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { throw Malformed(where + " '" + token + "' is not an integer."); } return result; } private static float ParseFloat(string token, string where) { if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { throw Malformed(where + " '" + token + "' is not a float."); } return result; } private static double ParseDouble(string token, string where) { if (!double.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { throw Malformed(where + " '" + token + "' is not a number."); } return result; } private static ArenaContentExportException Malformed(string detail) { return new ArenaContentExportException("Malformed arena content artifact: " + detail); } [CompilerGenerated] private ArenaContentArtifact(ArenaContentArtifact original) { Definition = original.Definition; SchemaVersion = original.SchemaVersion; ProtocolVersion = original.ProtocolVersion; BundleVersion = original.BundleVersion; Parity = original.Parity; MaterialBorrowPlacements = original.MaterialBorrowPlacements; } } public sealed record ArenaParityNode(string Path, string Kind, AuthoredTransform LocalTransform); public sealed record MaterialBorrowPlacement(StableMarkerId BorrowMarkerId, string TargetPath); public sealed record ArenaContentDefinition(string ArenaId, int ArenaVersion, string ArenaContentId, IReadOnlyList<AuthoredNode> Nodes, IReadOnlyList<VanillaProxyDefinition> VanillaProxies, IReadOnlyList<ColliderDefinition> Colliders, IReadOnlyList<NavDefinition> NavDefinitions, IReadOnlyList<SpawnDefinition> Spawns, IReadOnlyList<MechanismDefinition> Mechanisms, IReadOnlyList<MaterialBorrowDefinition> MaterialBorrows) { public static ArenaContentDefinition Create(string arenaId, int arenaVersion, string arenaContentId, IReadOnlyList<AuthoredNode>? nodes = null, IReadOnlyList<VanillaProxyDefinition>? vanillaProxies = null, IReadOnlyList<ColliderDefinition>? colliders = null, IReadOnlyList<NavDefinition>? navDefinitions = null, IReadOnlyList<SpawnDefinition>? spawns = null, IReadOnlyList<MechanismDefinition>? mechanisms = null, IReadOnlyList<MaterialBorrowDefinition>? materialBorrows = null) { return new ArenaContentDefinition(arenaId, arenaVersion, arenaContentId, nodes ?? Array.Empty<AuthoredNode>(), vanillaProxies ?? Array.Empty<VanillaProxyDefinition>(), colliders ?? Array.Empty<ColliderDefinition>(), navDefinitions ?? Array.Empty<NavDefinition>(), spawns ?? Array.Empty<SpawnDefinition>(), mechanisms ?? Array.Empty<MechanismDefinition>(), materialBorrows ?? Array.Empty<MaterialBorrowDefinition>()); } } public sealed class ArenaContentExportException : Exception { public ArenaContentExportException(string message) : base(message) { } } public sealed record ArenaManifest(string ArenaId, int ArenaVersion, ContentHashSchemaVersion ContentHashSchemaVersion, ContentHash ContentHash, int ProtocolVersion, string BundleVersion); public sealed record AuthoredBounds(Vector3 Center, Vector3 Size); public sealed record AuthoredNode(StableMarkerId MarkerId, string NodeKind, StableMarkerId? ParentMarkerId, AuthoredTransform LocalTransform); public sealed record VanillaProxyDefinition(StableMarkerId MarkerId, string AddressableKeyOrGuid, AuthoredTransform LocalTransform); public sealed record MaterialBorrowDefinition(StableMarkerId MarkerId, StableMarkerId TargetMarkerId, int TargetSubMaterialIndex, string CarrierGuid, string MaterialName); public sealed record ColliderDefinition(StableMarkerId MarkerId, string ColliderKind, IReadOnlyList<double> GeometryParameters, string LayerName); public sealed record NavDefinition(StableMarkerId MarkerId, string NavKind, AuthoredBounds Bounds, string? NavmeshPrefabContentId); public sealed record SpawnDefinition(StableMarkerId MarkerId, string SpawnKind, string DefinitionId, AuthoredTransform LocalTransform); public sealed record MechanismDefinition(StableMarkerId MarkerId, string MechanismDefinitionId, string MechanismGroupId, AuthoredTransform LocalTransform); public sealed record AuthoredTransform(Vector3 Position, Quaternion Rotation, Vector3 Scale); public readonly struct ContentHash : IEquatable<ContentHash> { public const int Sha256Length = 32; private readonly byte[]? _bytes; public int Length { get { byte[]? bytes = _bytes; if (bytes == null) { return 0; } return bytes.Length; } } public ContentHash(byte[] bytes) { if (bytes == null) { throw new ArgumentNullException("bytes"); } if (bytes.Length != 32) { throw new ArgumentException($"A ContentHash is a full SHA-256 digest of {32} bytes, but {bytes.Length} were " + "given. The hash is never truncated (MultiplayerLoadingContract §5.2.1).", "bytes"); } _bytes = (byte[])bytes.Clone(); } public byte[] ToArray() { return (byte[])(_bytes ?? Array.Empty<byte>()).Clone(); } public string ToHex() { byte[] array = _bytes ?? Array.Empty<byte>(); char[] array2 = new char[array.Length * 2]; for (int i = 0; i < array.Length; i++) { byte b = array[i]; array2[i * 2] = ToHexChar(b >> 4); array2[i * 2 + 1] = ToHexChar(b & 0xF); } return new string(array2); } public bool Equals(ContentHash other) { byte[] array = _bytes ?? Array.Empty<byte>(); byte[] array2 = other._bytes ?? Array.Empty<byte>(); if (array.Length != array2.Length) { return false; } for (int i = 0; i < array.Length; i++) { if (array[i] != array2[i]) { return false; } } return true; } public override bool Equals(object? obj) { if (obj is ContentHash other) { return Equals(other); } return false; } public override int GetHashCode() { byte[] bytes = _bytes; if (bytes == null || bytes.Length == 0) { return 0; } int num = 17; int num2 = Math.Min(bytes.Length, 4); for (int i = 0; i < num2; i++) { num = num * 31 + bytes[i]; } return num; } public override string ToString() { return ToHex(); } public static bool operator ==(ContentHash left, ContentHash right) { return left.Equals(right); } public static bool operator !=(ContentHash left, ContentHash right) { return !left.Equals(right); } private static char ToHexChar(int nibble) { return (char)((nibble < 10) ? (48 + nibble) : (97 + (nibble - 10))); } } public static class ContentHashComputer { public static ContentHash Compute(ArenaContentDefinition content) { return Compute(content, ContentHashSchemaVersion.Current); } public static ContentHash Compute(ArenaContentDefinition content, ContentHashSchemaVersion schemaVersion) { if ((object)content == null) { throw new ArgumentNullException("content"); } Validate(content); CanonicalEncoder canonicalEncoder = new CanonicalEncoder(); canonicalEncoder.WriteInt32(schemaVersion.Value); canonicalEncoder.WriteString(content.ArenaId); canonicalEncoder.WriteInt32(content.ArenaVersion); canonicalEncoder.WriteString(content.ArenaContentId); foreach (AuthoredNode item in OrderByMarker(content.Nodes, (AuthoredNode n) => n.MarkerId)) { string context = $"node {item.MarkerId}"; canonicalEncoder.WriteMarker(item.MarkerId); canonicalEncoder.WriteString(item.NodeKind); canonicalEncoder.WriteOptionalMarker(item.ParentMarkerId); canonicalEncoder.WriteTransform(item.LocalTransform, context); } foreach (VanillaProxyDefinition item2 in OrderByMarker(content.VanillaProxies, (VanillaProxyDefinition p) => p.MarkerId)) { string context2 = $"vanilla proxy {item2.MarkerId}"; canonicalEncoder.WriteMarker(item2.MarkerId); canonicalEncoder.WriteString(item2.AddressableKeyOrGuid); canonicalEncoder.WriteTransform(item2.LocalTransform, context2); } foreach (ColliderDefinition item3 in OrderByMarker(content.Colliders, (ColliderDefinition c) => c.MarkerId)) { string context3 = $"collider {item3.MarkerId}"; canonicalEncoder.WriteMarker(item3.MarkerId); canonicalEncoder.WriteString(item3.ColliderKind); WriteGeometry(canonicalEncoder, item3.GeometryParameters, context3); canonicalEncoder.WriteString(item3.LayerName); } foreach (NavDefinition item4 in OrderByMarker(content.NavDefinitions, (NavDefinition n) => n.MarkerId)) { string context4 = $"nav {item4.MarkerId}"; canonicalEncoder.WriteMarker(item4.MarkerId); canonicalEncoder.WriteString(item4.NavKind); canonicalEncoder.WriteBounds(item4.Bounds, context4); canonicalEncoder.WriteOptionalString(item4.NavmeshPrefabContentId); } foreach (SpawnDefinition item5 in OrderByMarker(content.Spawns, (SpawnDefinition s) => s.MarkerId)) { string context5 = $"spawn {item5.MarkerId}"; canonicalEncoder.WriteMarker(item5.MarkerId); canonicalEncoder.WriteString(item5.SpawnKind); canonicalEncoder.WriteString(item5.DefinitionId); canonicalEncoder.WriteTransform(item5.LocalTransform, context5); } foreach (MechanismDefinition item6 in OrderByMarker(content.Mechanisms, (MechanismDefinition m) => m.MarkerId)) { string context6 = $"mechanism {item6.MarkerId}"; canonicalEncoder.WriteMarker(item6.MarkerId); canonicalEncoder.WriteString(item6.MechanismDefinitionId); canonicalEncoder.WriteString(item6.MechanismGroupId); canonicalEncoder.WriteTransform(item6.LocalTransform, context6); } foreach (MaterialBorrowDefinition item7 in OrderByMarker(content.MaterialBorrows, (MaterialBorrowDefinition b) => b.MarkerId)) { canonicalEncoder.WriteMarker(item7.MarkerId); canonicalEncoder.WriteMarker(item7.TargetMarkerId); canonicalEncoder.WriteInt32(item7.TargetSubMaterialIndex); canonicalEncoder.WriteString(item7.CarrierGuid); canonicalEncoder.WriteString(item7.MaterialName); } using SHA256 sHA = SHA256.Create(); return new ContentHash(sHA.ComputeHash(canonicalEncoder.ToArray())); } private static void WriteGeometry(CanonicalEncoder encoder, IReadOnlyList<double> parameters, string context) { encoder.WriteInt32(parameters.Count); for (int i = 0; i < parameters.Count; i++) { encoder.WriteLength(parameters[i], $"{context} geometry[{i}]"); } } private static IEnumerable<T> OrderByMarker<T>(IReadOnlyList<T> items, Func<T, StableMarkerId> selector) { return items.OrderBy(selector, Comparer<StableMarkerId>.Default); } private static void Validate(ArenaContentDefinition content) { RequireToken(content.ArenaId, "arena", "ArenaId"); RequireToken(content.ArenaContentId, "arena", "ArenaContentId"); RequireNoNullLists(content); RequireNoNullElements(content.Nodes, "node"); RequireNoNullElements(content.VanillaProxies, "vanilla proxy"); RequireNoNullElements(content.Colliders, "collider"); RequireNoNullElements(content.NavDefinitions, "nav"); RequireNoNullElements(content.Spawns, "spawn"); RequireNoNullElements(content.Mechanisms, "mechanism"); RequireNoNullElements(content.MaterialBorrows, "material borrow"); RequireUniqueAssignedMarkers(content); ValidateElementFields(content); ValidateParentReferences(content.Nodes); ValidateMaterialBorrowTargets(content); } private static void ValidateElementFields(ArenaContentDefinition content) { foreach (AuthoredNode node in content.Nodes) { string text = $"node {node.MarkerId}"; RequireToken(node.NodeKind, text, "NodeKind"); RequireTransform(node.LocalTransform, text); } foreach (VanillaProxyDefinition vanillaProxy in content.VanillaProxies) { string text2 = $"vanilla proxy {vanillaProxy.MarkerId}"; RequireToken(vanillaProxy.AddressableKeyOrGuid, text2, "AddressableKeyOrGuid"); RequireTransform(vanillaProxy.LocalTransform, text2); } foreach (ColliderDefinition collider in content.Colliders) { string text3 = $"collider {collider.MarkerId}"; RequireToken(collider.ColliderKind, text3, "ColliderKind"); RequireToken(collider.LayerName, text3, "LayerName"); if (collider.GeometryParameters == null) { throw new ArenaContentExportException("Null GeometryParameters on " + text3 + ": pass an empty list, not null. (Individual parameters are validated for NaN/infinity when quantised.)"); } } foreach (NavDefinition navDefinition in content.NavDefinitions) { string text4 = $"nav {navDefinition.MarkerId}"; RequireToken(navDefinition.NavKind, text4, "NavKind"); RequireBounds(navDefinition.Bounds, text4); RequireOptionalToken(navDefinition.NavmeshPrefabContentId, text4, "NavmeshPrefabContentId"); } foreach (SpawnDefinition spawn in content.Spawns) { string text5 = $"spawn {spawn.MarkerId}"; RequireToken(spawn.SpawnKind, text5, "SpawnKind"); RequireToken(spawn.DefinitionId, text5, "DefinitionId"); RequireTransform(spawn.LocalTransform, text5); } foreach (MechanismDefinition mechanism in content.Mechanisms) { string text6 = $"mechanism {mechanism.MarkerId}"; RequireToken(mechanism.MechanismDefinitionId, text6, "MechanismDefinitionId"); RequireToken(mechanism.MechanismGroupId, text6, "MechanismGroupId"); RequireTransform(mechanism.LocalTransform, text6); } foreach (MaterialBorrowDefinition materialBorrow in content.MaterialBorrows) { string text7 = $"material borrow {materialBorrow.MarkerId}"; RequireToken(materialBorrow.CarrierGuid, text7, "CarrierGuid"); RequireToken(materialBorrow.MaterialName, text7, "MaterialName"); if (materialBorrow.TargetSubMaterialIndex < 0) { throw new ArenaContentExportException("Negative TargetSubMaterialIndex on " + text7 + ": a sub-material slot index is zero or positive."); } } } private static void ValidateMaterialBorrowTargets(ArenaContentDefinition content) { HashSet<StableMarkerId> hashSet = new HashSet<StableMarkerId>(); foreach (AuthoredNode node in content.Nodes) { hashSet.Add(node.MarkerId); } foreach (MaterialBorrowDefinition materialBorrow in content.MaterialBorrows) { string text = $"material borrow {materialBorrow.MarkerId}"; if (materialBorrow.TargetMarkerId.IsUnassigned) { throw new ArenaContentExportException("Unassigned TargetMarkerId on " + text + ": a material borrow must target an assigned node marker."); } if (!hashSet.Contains(materialBorrow.TargetMarkerId)) { throw new ArenaContentExportException($"Dangling TargetMarkerId {materialBorrow.TargetMarkerId} on {text}: it matches no authored node, " + "so there is no renderer to paint."); } } } private static void ValidateParentReferences(IReadOnlyList<AuthoredNode> nodes) { HashSet<StableMarkerId> hashSet = new HashSet<StableMarkerId>(); foreach (AuthoredNode node in nodes) { hashSet.Add(node.MarkerId); } foreach (AuthoredNode node2 in nodes) { StableMarkerId? parentMarkerId = node2.ParentMarkerId; if (parentMarkerId.HasValue) { string text = $"node {node2.MarkerId}"; if (parentMarkerId.Value.IsUnassigned) { throw new ArenaContentExportException("Unassigned ParentMarkerId on " + text + ": a present parent must be an assigned marker, or omitted entirely for a root node."); } if (parentMarkerId.Value == node2.MarkerId) { throw new ArenaContentExportException($"Node {node2.MarkerId} lists itself as its own parent."); } if (!hashSet.Contains(parentMarkerId.Value)) { throw new ArenaContentExportException($"Dangling ParentMarkerId {parentMarkerId.Value} on {text}: it matches no authored node, so the " + "hierarchy is broken."); } } } } private static void RequireToken(string? value, string where, string field) { if (string.IsNullOrWhiteSpace(value)) { throw new ArenaContentExportException("Missing required '" + field + "' on " + where + ": a required identifier/kind must be a non-empty, non-whitespace token authored in canonical form, never null or blank."); } } private static void RequireOptionalToken(string? value, string where, string field) { if (value != null && string.IsNullOrWhiteSpace(value)) { throw new ArenaContentExportException("Blank '" + field + "' on " + where + ": an optional token is either absent (null) or a real non-empty value. A present-but-blank value is ambiguous with absent in the hash."); } } private static void RequireTransform(AuthoredTransform? transform, string where) { if ((object)transform == null) { throw new ArenaContentExportException("Null local transform on " + where + "."); } } private static void RequireBounds(AuthoredBounds? bounds, string where) { if ((object)bounds == null) { throw new ArenaContentExportException("Null bounds on " + where + "."); } } private static void RequireNoNullElements<T>(IReadOnlyList<T> items, string kind) where T : class { for (int i = 0; i < items.Count; i++) { if (items[i] == null) { throw new ArenaContentExportException($"Null {kind} at index {i}: a content section must not contain null elements."); } } } private static void RequireNoNullLists(ArenaContentDefinition content) { RequireNotNull(content.Nodes, "Nodes"); RequireNotNull(content.VanillaProxies, "VanillaProxies"); RequireNotNull(content.Colliders, "Colliders"); RequireNotNull(content.NavDefinitions, "NavDefinitions"); RequireNotNull(content.Spawns, "Spawns"); RequireNotNull(content.Mechanisms, "Mechanisms"); RequireNotNull(content.MaterialBorrows, "MaterialBorrows"); static void RequireNotNull(object? list, string name) { if (list == null) { throw new ArenaContentExportException("Arena content section '" + name + "' is null. A dropped section must not silently hash the same as an empty one; pass an empty list (or use ArenaContentDefinition.Create)."); } } } private static void RequireUniqueAssignedMarkers(ArenaContentDefinition content) { HashSet<StableMarkerId> hashSet = new HashSet<StableMarkerId>(); foreach (var (stableMarkerId, text) in EnumerateMarkers(content)) { if (stableMarkerId.IsUnassigned) { throw new ArenaContentExportException("Unassigned StableMarkerId on " + text + ": every authored node that participates in content identity must carry an editor-assigned GUID, never a name or a default id."); } if (!hashSet.Add(stableMarkerId)) { throw new ArenaContentExportException($"Duplicate StableMarkerId {stableMarkerId} (seen again on {text}): marker ids must be " + "unique across the whole arena, or ordering and parent references become ambiguous."); } } } private static IEnumerable<(StableMarkerId Marker, string Description)> EnumerateMarkers(ArenaContentDefinition content) { foreach (AuthoredNode node in content.Nodes) { yield return (Marker: node.MarkerId, Description: "node (kind '" + node.NodeKind + "')"); } foreach (VanillaProxyDefinition vanillaProxy in content.VanillaProxies) { yield return (Marker: vanillaProxy.MarkerId, Description: "vanilla proxy ('" + vanillaProxy.AddressableKeyOrGuid + "')"); } foreach (ColliderDefinition collider in content.Colliders) { yield return (Marker: collider.MarkerId, Description: "collider (kind '" + collider.ColliderKind + "')"); } foreach (NavDefinition navDefinition in content.NavDefinitions) { yield return (Marker: navDefinition.MarkerId, Description: "nav (kind '" + navDefinition.NavKind + "')"); } foreach (SpawnDefinition spawn in content.Spawns) { yield return (Marker: spawn.MarkerId, Description: "spawn (kind '" + spawn.SpawnKind + "')"); } foreach (MechanismDefinition mechanism in content.Mechanisms) { yield return (Marker: mechanism.MarkerId, Description: "mechanism ('" + mechanism.MechanismDefinitionId + "')"); } foreach (MaterialBorrowDefinition materialBorrow in content.MaterialBorrows) { yield return (Marker: materialBorrow.MarkerId, Description: "material borrow ('" + materialBorrow.MaterialName + "')"); } } } public readonly struct ContentHashSchemaVersion : IEquatable<ContentHashSchemaVersion> { public static readonly ContentHashSchemaVersion Current = new ContentHashSchemaVersion(2); public int Value { get; } public ContentHashSchemaVersion(int value) { Value = value; } public bool Equals(ContentHashSchemaVersion other) { return Value == other.Value; } public override bool Equals(object? obj) { if (obj is ContentHashSchemaVersion other) { return Equals(other); } return false; } public override int GetHashCode() { return Value; } public override string ToString() { return Value.ToString(); } public static bool operator ==(ContentHashSchemaVersion left, ContentHashSchemaVersion right) { return left.Equals(right); } public static bool operator !=(ContentHashSchemaVersion left, ContentHashSchemaVersion right) { return !left.Equals(right); } } public readonly struct Quaternion : IEquatable<Quaternion> { public static Quaternion Identity => new Quaternion(0f, 0f, 0f, 1f); public float X { get; } public float Y { get; } public float Z { get; } public float W { get; } public Quaternion(float x, float y, float z, float w) { X = x; Y = y; Z = z; W = w; } public bool Equals(Quaternion other) { if (X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z)) { return W.Equals(other.W); } return false; } public override bool Equals(object? obj) { if (obj is Quaternion other) { return Equals(other); } return false; } public override int GetHashCode() { return (((((X.GetHashCode() * 397) ^ Y.GetHashCode()) * 397) ^ Z.GetHashCode()) * 397) ^ W.GetHashCode(); } public override string ToString() { return $"({X}, {Y}, {Z}, {W})"; } public static bool operator ==(Quaternion left, Quaternion right) { return left.Equals(right); } public static bool operator !=(Quaternion left, Quaternion right) { return !left.Equals(right); } } public readonly struct StableMarkerId : IEquatable<StableMarkerId>, IComparable<StableMarkerId> { private readonly Guid _value; public bool IsUnassigned => _value == Guid.Empty; public StableMarkerId(Guid value) { _value = value; } public string ToCanonicalString() { Guid value = _value; return value.ToString("D"); } public int CompareTo(StableMarkerId other) { return string.CompareOrdinal(ToCanonicalString(), other.ToCanonicalString()); } public bool Equals(StableMarkerId other) { Guid value = _value; return value.Equals(other._value); } public override bool Equals(object? obj) { if (obj is StableMarkerId other) { return Equals(other); } return false; } public override int GetHashCode() { return _value.GetHashCode(); } public override string ToString() { return ToCanonicalString(); } public static bool operator ==(StableMarkerId left, StableMarkerId right) { return left.Equals(right); } public static bool operator !=(StableMarkerId left, StableMarkerId right) { return !left.Equals(right); } public static bool operator <(StableMarkerId left, StableMarkerId right) { return left.CompareTo(right) < 0; } public static bool operator >(StableMarkerId left, StableMarkerId right) { return left.CompareTo(right) > 0; } public static bool operator <=(StableMarkerId left, StableMarkerId right) { return left.CompareTo(right) <= 0; } public static bool operator >=(StableMarkerId left, StableMarkerId right) { return left.CompareTo(right) >= 0; } } public readonly struct Vector3 : IEquatable<Vector3> { public float X { get; } public float Y { get; } public float Z { get; } public Vector3(float x, float y, float z) { X = x; Y = y; Z = z; } public bool Equals(Vector3 other) { if (X.Equals(other.X) && Y.Equals(other.Y)) { return Z.Equals(other.Z); } return false; } public override bool Equals(object? obj) { if (obj is Vector3 other) { return Equals(other); } return false; } public override int GetHashCode() { return (((X.GetHashCode() * 397) ^ Y.GetHashCode()) * 397) ^ Z.GetHashCode(); } public override string ToString() { return $"({X}, {Y}, {Z})"; } public static bool operator ==(Vector3 left, Vector3 right) { return left.Equals(right); } public static bool operator !=(Vector3 left, Vector3 right) { return !left.Equals(right); } } } namespace FalseGods.Protocol.Arena.Internal { internal sealed class CanonicalEncoder { private readonly MemoryStream _stream = new MemoryStream(); public void WriteInt32(int value) { _stream.WriteByte((byte)value); _stream.WriteByte((byte)(value >> 8)); _stream.WriteByte((byte)(value >> 16)); _stream.WriteByte((byte)(value >> 24)); } public void WriteInt64(long value) { for (int i = 0; i < 8; i++) { _stream.WriteByte((byte)(value >> 8 * i)); } } public void WriteString(string value) { if (value == null) { throw new ArgumentNullException("value", "A required string reached the encoder as null; validate it before encoding."); } byte[] bytes = Encoding.UTF8.GetBytes(value); WriteInt32(bytes.Length); _stream.Write(bytes, 0, bytes.Length); } public void WriteMarker(StableMarkerId marker) { WriteString(marker.ToCanonicalString()); } public void WriteOptionalMarker(StableMarkerId? marker) { WriteString(marker.HasValue ? marker.Value.ToCanonicalString() : string.Empty); } public void WriteOptionalString(string? value) { WriteString(value ?? string.Empty); } public void WriteLength(double value, string context) { WriteInt64(Quantizer.QuantizeLength(value, context)); } public void WriteVector(Vector3 vector, string context) { WriteLength(vector.X, context); WriteLength(vector.Y, context); WriteLength(vector.Z, context); } public void WriteTransform(AuthoredTransform transform, string context) { WriteVector(transform.Position, context); var (value, value2, value3, value4) = Quantizer.QuantizeRotation(transform.Rotation, context); WriteInt64(value); WriteInt64(value2); WriteInt64(value3); WriteInt64(value4); WriteVector(transform.Scale, context); } public void WriteBounds(AuthoredBounds bounds, string context) { WriteVector(bounds.Center, context); WriteVector(bounds.Size, context); } public byte[] ToArray() { return _stream.ToArray(); } } internal static class Quantizer { private const double LengthScale = 10000.0; private const double RotationScale = 1000000.0; public static long QuantizeLength(double value, string context) { return QuantizeAt(NormalizeZero(RequireFinite(value, context)), 10000.0); } public static (long W, long X, long Y, long Z) QuantizeRotation(Quaternion rotation, string context) { double num = RequireFinite(rotation.X, context); double num2 = RequireFinite(rotation.Y, context); double num3 = RequireFinite(rotation.Z, context); double num4 = RequireFinite(rotation.W, context); double num5 = Math.Sqrt(num * num + num2 * num2 + num3 * num3 + num4 * num4); if (num5 == 0.0) { throw new ArenaContentExportException("Zero-length quaternion at " + context + ": a rotation with no magnitude has no canonical representation. Fix the authored rotation (identity is (0,0,0,1))."); } num = NormalizeZero(num / num5); num2 = NormalizeZero(num2 / num5); num3 = NormalizeZero(num3 / num5); num4 = NormalizeZero(num4 / num5); if (((num4 != 0.0) ? num4 : ((num != 0.0) ? num : ((num2 != 0.0) ? num2 : num3))) < 0.0) { num = NormalizeZero(0.0 - num); num2 = NormalizeZero(0.0 - num2); num3 = NormalizeZero(0.0 - num3); num4 = NormalizeZero(0.0 - num4); } return (W: QuantizeAt(num4, 1000000.0), X: QuantizeAt(num, 1000000.0), Y: QuantizeAt(num2, 1000000.0), Z: QuantizeAt(num3, 1000000.0)); } private static long QuantizeAt(double value, double scale) { return (long)Math.Round(value * scale, MidpointRounding.ToEven); } private static double NormalizeZero(double value) { if (value != 0.0) { return value; } return 0.0; } private static double RequireFinite(double value, string context) { if (double.IsNaN(value) || double.IsInfinity(value)) { throw new ArenaContentExportException($"Non-finite authored value ({value}) at {context}: NaN and infinity cannot be quantised " + "into a reproducible hash and are a build-time export failure (MultiplayerLoadingContract §5.2.1)."); } return value; } } }
FalseGods.RuntimeContracts.dll
Decompiled 9 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using FalseGods.Core.Arena; using FalseGods.Core.Bosses; using FalseGods.Core.Simulation; using FalseGods.RuntimeContracts.Multiplayer; using FalseGods.RuntimeContracts.Transport; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FalseGods.RuntimeContracts")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6e5740a80f810ab422551028733810b527fb614d")] [assembly: AssemblyProduct("FalseGods.RuntimeContracts")] [assembly: AssemblyTitle("FalseGods.RuntimeContracts")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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; } } internal static class IsExternalInit { } } namespace FalseGods.RuntimeContracts.Transport { public readonly struct EncodedPayload { private readonly byte[]? _bytes; public int Length { get { byte[]? bytes = _bytes; if (bytes == null) { return 0; } return bytes.Length; } } public EncodedPayload(byte[] bytes) { if (bytes == null) { throw new ArgumentNullException("bytes"); } _bytes = (byte[])bytes.Clone(); } public byte[] ToArray() { return (byte[])(_bytes ?? Array.Empty<byte>()).Clone(); } } public enum MessageDelivery { ReliableOrdered, Unreliable } public enum MessageTargetKind { Host, AllClients, SpecificPeer } public readonly struct MessageTarget { public MessageTargetKind Kind { get; } public SessionPeerId Peer { get; } public static MessageTarget Host { get; } = new MessageTarget(MessageTargetKind.Host, default(SessionPeerId)); public static MessageTarget AllClients { get; } = new MessageTarget(MessageTargetKind.AllClients, default(SessionPeerId)); private MessageTarget(MessageTargetKind kind, SessionPeerId peer) { Kind = kind; Peer = peer; } public static MessageTarget ToPeer(SessionPeerId peer) { return new MessageTarget(MessageTargetKind.SpecificPeer, peer); } public override string ToString() { if (Kind != MessageTargetKind.SpecificPeer) { return Kind.ToString(); } return $"{Kind}({Peer})"; } } public readonly struct SessionPeerId : IEquatable<SessionPeerId> { private readonly int _value; public int Value => _value; public SessionPeerId(int value) { _value = value; } public bool Equals(SessionPeerId other) { return _value == other._value; } public override bool Equals(object? obj) { if (obj is SessionPeerId other) { return Equals(other); } return false; } public override int GetHashCode() { return _value; } public override string ToString() { return $"peer:{_value}"; } public static bool operator ==(SessionPeerId left, SessionPeerId right) { return left.Equals(right); } public static bool operator !=(SessionPeerId left, SessionPeerId right) { return !left.Equals(right); } } } namespace FalseGods.RuntimeContracts.Presentation { public enum AttackVisualKind { Projectile = 1, Area } public enum BossVisualActivity { Idle, Telegraphing, Committing, Recovering, Dead, Vanishing, Hidden, Appearing } public interface IEncounterPresentation { void Apply(PresentationState state); void Handle(IPresentationEvent presentationEvent); } public interface IPresentationEvent { } public sealed record BossAppeared(BossInstanceId Boss, int PhaseVisualId) : IPresentationEvent; public sealed record AttackTelegraphStarted(BossInstanceId Boss, AttackInstanceId Attack, AttackVisualKind Kind, SimVector2 AimPoint, float TelegraphSeconds) : IPresentationEvent; public sealed record AttackLanded(BossInstanceId Boss, AttackInstanceId Attack, AttackVisualKind Kind, SimVector2 AimPoint) : IPresentationEvent; public sealed record WeakPointVisibilityChanged(BossInstanceId Boss, bool Exposed) : IPresentationEvent; public sealed record PhaseTransition(BossInstanceId Boss, int PhaseVisualId) : IPresentationEvent; public sealed record BossHit(BossInstanceId Boss, int Amount, bool WeakPointHit) : IPresentationEvent; public sealed record RageChanged(BossInstanceId Boss, bool Enraged) : IPresentationEvent; public sealed record BossRoared(BossInstanceId Boss) : IPresentationEvent; public sealed record BossDefeated(BossInstanceId Boss) : IPresentationEvent; public sealed record BossMoved(BossInstanceId Boss, SimVector2 Position, float PositionHeight) : IPresentationEvent; public sealed record MechanismGroupEngaged(MechanismGroupId Group) : IPresentationEvent; public sealed record ExitOpened : IPresentationEvent; public sealed record PresentationState(BossInstanceId Boss, SimVector2 Position, float PositionHeight, SimVector2 Facing, int PhaseVisualId, BossVisualActivity Activity, bool WeakPointExposed, bool Enraged, float HealthFraction); } namespace FalseGods.RuntimeContracts.Multiplayer { public interface IDestructibleOwnership { void ClaimAsOurs(object destructible); } public interface IEncounterChannel { event Action<SessionPeerId, EncodedPayload> Received; void Send(EncodedPayload payload, MessageDelivery delivery, MessageTarget target); } public interface IMultiplayerSession { SessionRole Role { get; } bool IsActive { get; } SessionPeerId LocalPeer { get; } SessionPeerId HostPeer { get; } } public interface IParticipantPeerMap { bool TryGetRemotePeer(int participantIndex, out SessionPeerId peer); } public interface IPlayerLifeQuery { bool IsOutOfTheFight(object playerUnit); } public interface IPlayerRoster { IReadOnlyList<SessionPeerId> Members { get; } } public interface ISpawnOwnership { IDisposable? DeclareHostAuthoritative(object spawnOwner); } public enum SessionRole { Host, Client } } namespace FalseGods.RuntimeContracts.Integration { public static class FalseGodsIntegrations { private sealed class RegistrationToken : IIntegrationRegistration, IDisposable { public IFalseGodsIntegration Integration { get; } public RegistrationToken(IFalseGodsIntegration integration) { Integration = integration; } public void Dispose() { Revoke(this); } } private static readonly object Gate = new object(); private static RegistrationToken? _active; public static IFalseGodsIntegration? Current { get { lock (Gate) { return _active?.Integration; } } } public static event Action? Changed; public static IIntegrationRegistration? Register(IFalseGodsIntegration integration) { if (integration == null) { throw new ArgumentNullException("integration"); } RegistrationToken result; lock (Gate) { if (_active != null) { return null; } result = (_active = new RegistrationToken(integration)); } RaiseChanged(); return result; } private static void Revoke(RegistrationToken token) { lock (Gate) { if (_active != token) { return; } _active = null; } RaiseChanged(); } private static void RaiseChanged() { FalseGodsIntegrations.Changed?.Invoke(); } } public interface IFalseGodsIntegration { IMultiplayerSession Session { get; } IEncounterChannel Channel { get; } IPlayerRoster Roster { get; } IParticipantPeerMap Players { get; } ISpawnOwnership Spawns { get; } IPlayerLifeQuery Lives { get; } IDestructibleOwnership Destructibles { get; } } public interface IIntegrationRegistration : IDisposable { } } namespace FalseGods.RuntimeContracts.Diagnostics { public interface ILogger { void Log(string message); void LogWarning(string message); } } namespace FalseGods.RuntimeContracts.Arena { public readonly struct ArenaRotation : IEquatable<ArenaRotation> { public static ArenaRotation Identity => new ArenaRotation(0f, 0f, 0f, 1f); public float X { get; } public float Y { get; } public float Z { get; } public float W { get; } public ArenaRotation(float x, float y, float z, float w) { X = x; Y = y; Z = z; W = w; } public bool Equals(ArenaRotation other) { if (X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z)) { return W.Equals(other.W); } return false; } public override bool Equals(object? obj) { if (obj is ArenaRotation other) { return Equals(other); } return false; } public override int GetHashCode() { return (((((X.GetHashCode() * 397) ^ Y.GetHashCode()) * 397) ^ Z.GetHashCode()) * 397) ^ W.GetHashCode(); } public override string ToString() { return $"({X:0.###}, {Y:0.###}, {Z:0.###}, {W:0.###})"; } public static bool operator ==(ArenaRotation left, ArenaRotation right) { return left.Equals(right); } public static bool operator !=(ArenaRotation left, ArenaRotation right) { return !left.Equals(right); } } public readonly struct ArenaWorldPoint : IEquatable<ArenaWorldPoint> { public float X { get; } public float Y { get; } public float Z { get; } public ArenaWorldPoint(float x, float y, float z) { X = x; Y = y; Z = z; } public bool Equals(ArenaWorldPoint other) { if (X.Equals(other.X) && Y.Equals(other.Y)) { return Z.Equals(other.Z); } return false; } public override bool Equals(object? obj) { if (obj is ArenaWorldPoint other) { return Equals(other); } return false; } public override int GetHashCode() { return (((X.GetHashCode() * 397) ^ Y.GetHashCode()) * 397) ^ Z.GetHashCode(); } public override string ToString() { return $"({X:0.###}, {Y:0.###}, {Z:0.###})"; } public static bool operator ==(ArenaWorldPoint left, ArenaWorldPoint right) { return left.Equals(right); } public static bool operator !=(ArenaWorldPoint left, ArenaWorldPoint right) { return !left.Equals(right); } } public sealed record ArenaAssetLoadResult(bool Success, string? Error, string? ArtifactText) { public static ArenaAssetLoadResult Loaded(string artifactText) { return new ArenaAssetLoadResult(Success: true, null, artifactText); } public static ArenaAssetLoadResult Failed(string error) { return new ArenaAssetLoadResult(Success: false, error, null); } } public interface IArenaAssetProvider { ArenaAssetLoadResult Load(); void Release(); } public sealed record RealizedParityNode(string Path, ArenaWorldPoint LocalPosition, ArenaRotation LocalRotation, ArenaWorldPoint LocalScale); public sealed record RealizedMarker(string Path, ArenaWorldPoint WorldPosition, ArenaWorldPoint LocalScale); public sealed record ArenaRealizationResult(bool Success, string? Error, IReadOnlyList<RealizedParityNode> ParityNodes, IReadOnlyList<RealizedMarker> Markers) { public static ArenaRealizationResult Failed(string error) { return new ArenaRealizationResult(Success: false, error, Array.Empty<RealizedParityNode>(), Array.Empty<RealizedMarker>()); } } public interface IArenaRealization { ArenaRealizationResult Realize(ArenaWorldPoint origin, IReadOnlyList<string> parityPaths, IReadOnlyList<string> markerPaths, IReadOnlyList<string> markerGroupPaths); void Teardown(); } }
FalseGods.UnityRuntime.dll
Decompiled 9 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using FalseGods.Core.Arena; using FalseGods.Core.Bosses; using FalseGods.Core.Simulation; using FalseGods.RuntimeContracts.Arena; using FalseGods.RuntimeContracts.Diagnostics; using FalseGods.RuntimeContracts.Presentation; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("FalseGods.UnityRuntime")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6e5740a80f810ab422551028733810b527fb614d")] [assembly: AssemblyProduct("FalseGods.UnityRuntime")] [assembly: AssemblyTitle("FalseGods.UnityRuntime")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FalseGods.UnityRuntime.Presentation { public enum BossFacingMode { Fixed, LocalBillboard, NearestPlayer } public sealed class BossPresentation : IEncounterPresentation, IDisposable { private enum TransientKind { Fly, Fade } private sealed class Transient { public GameObject Object { get; } public Vector3 From { get; } public Vector3 To { get; } public float Seconds { get; } public TransientKind Kind { get; } public Material Material { get; } public float Elapsed { get; set; } public Transient(GameObject obj, Vector3 from, Vector3 to, float seconds, TransientKind kind, Material material = null) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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) Object = obj; From = from; To = to; Seconds = seconds; Kind = kind; Material = material; } } private const float BodyHeight = 2.4f; private const float BodyWidth = 1.6f; private const float MuzzleForward = 0.9f; private const float DefaultSpriteScale = 2f; private const float SinkDepth = 3.2f; private const float SinkSeconds = 0.42f; private const float RiseSeconds = 0.33f; private const float LurchDegrees = 23f; private const float SettleSeconds = 1.6f; private const float SettleFrequency = 3.2f; private const string BodyTextureResourceSuffix = "boss-body.png"; private static readonly Color PhaseOneColor = new Color(0.2f, 0.7f, 0.65f); private static readonly Color PhaseTwoColor = new Color(0.85f, 0.35f, 0.18f); private static readonly Color DeadColor = new Color(0.2f, 0.2f, 0.22f); private static readonly Color TelegraphProjectileColor = new Color(0.95f, 0.25f, 0.2f); private static readonly Color TelegraphAreaColor = new Color(0.95f, 0.55f, 0.1f); private static readonly Color RageTint = new Color(1f, 0.28f, 0.22f); private const float RoarSeconds = 1.9f; private const float RoarRiseFraction = 0.18f; private const float RoarHoldFraction = 0.34f; private const float RoarRearUp = 0.45f; private const float RoarSquashRatio = 0.55f; private const float RoarShakeDegrees = 7f; private const float RoarShakeFrequency = 9f; private const float HitFlashSeconds = 0.12f; private const float HitFlashBrightness = 2.6f; private const float HitFlinchSeconds = 0.16f; private const float HitFlinchSquash = 0.09f; private const float HitFlinchDegrees = 4f; private const float DeathSinkSeconds = 2.4f; private const float DeathRockDegrees = 14f; private const float DeathRockFrequency = 1.1f; private const float DeathSinkClearance = 1.5f; private readonly ILogger _logger; private readonly float _floorY; private readonly Shader _shader; private readonly string _shaderName; private readonly Vector3 _fixedForward; private readonly GameObject _root; private readonly GameObject _collisionBody; private readonly GameObject _hitBody; private readonly Transform _bodyBillboard; private readonly Transform _aimPivot; private readonly Transform _body; private readonly Material _bodyMat; private readonly Transform _muzzle; private readonly Texture2D _bodyTexture; private readonly bool _bodyTextured; private GameObject _telegraph; private Material _telegraphMat; private readonly List<Transient> _transients = new List<Transient>(); private float _time; private PresentationState _state; private bool _hasState; private float _flashTimer; private float _flinchTimer; private float _deathElapsed; private bool _flashWeakPoint; private float _phasePulseTimer; private float _appearPulseTimer; private float _roarTimer; private bool _reportedFog; private bool _dead; private bool _telegraphActive; private AttackVisualKind _telegraphKind; private Vector3 _telegraphAim; private float _telegraphStart; private float _telegraphSeconds; private BossVisualActivity _lastActivity; private float _activityStart; private float _relocationTilt; public BossFacingMode FacingMode { get; set; } = BossFacingMode.LocalBillboard; public bool LockPitch { get; set; } public float SpriteScale { get; set; } = 2f; public Collider BodyCollider { get; } public Collider CollisionCollider { get; } public Collider HitCollider { get; } public BossPresentation(ILogger logger, Vector3 origin, float arenaFloorY) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Expected O, but got Unknown //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Expected O, but got Unknown //IL_0372: Unknown result type (might be due to invalid IL or missing references) _logger = logger; _floorY = arenaFloorY; _shader = ResolveShader(logger, out _shaderName); _bodyTexture = LoadEmbeddedBodyTexture(logger); _bodyTextured = (Object)(object)_bodyTexture != (Object)null; _root = new GameObject("FalseGodsBoss"); _root.transform.position = origin; _fixedForward = ComputeSpawnFacing(_root.transform.position); _bodyBillboard = new GameObject("BodyBillboard").transform; _bodyBillboard.SetParent(_root.transform, false); _bodyBillboard.localPosition = new Vector3(0f, 1.2f, 0f); _aimPivot = new GameObject("AimPivot").transform; _aimPivot.SetParent(_root.transform, false); GameObject val = CreateQuad("Body", _bodyBillboard, _bodyTextured ? Color.white : PhaseOneColor, out _bodyMat); if (_bodyTextured) { _bodyMat.mainTexture = (Texture)(object)_bodyTexture; } _body = val.transform; _body.localPosition = Vector3.zero; float num = (_bodyTextured ? (2.4f * ((float)((Texture)_bodyTexture).width / (float)((Texture)_bodyTexture).height)) : 1.6f); _body.localScale = new Vector3(num, 2.4f, 1f); BodyCollider = AddBox(val); _muzzle = new GameObject("Muzzle").transform; _muzzle.SetParent(_aimPivot, false); _muzzle.localPosition = new Vector3(0f, 1.2f, 0.9f); _collisionBody = new GameObject("CollisionBody"); _collisionBody.transform.SetParent(_root.transform, false); int num2 = LayerMask.NameToLayer("Entities"); if (num2 >= 0) { _collisionBody.layer = num2; } else { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("'Entities' layer not found; boss collision left on the Default layer."); } } CapsuleCollider val2 = _collisionBody.AddComponent<CapsuleCollider>(); val2.direction = 1; val2.height = 2.4f; val2.radius = 0.71999997f; val2.center = new Vector3(0f, 1.2f, 0f); CollisionCollider = (Collider)(object)val2; Rigidbody obj = _collisionBody.AddComponent<Rigidbody>(); obj.isKinematic = true; obj.useGravity = false; _hitBody = new GameObject("WeaponHitBody"); _hitBody.transform.SetParent(_root.transform, false); int num3 = LayerMask.NameToLayer("Hitbox"); if (num3 >= 0) { _hitBody.layer = num3; } else { ILogger logger3 = _logger; if (logger3 != null) { logger3.LogWarning("'Hitbox' layer not found; weapon hits left on the Default layer."); } } CapsuleCollider val3 = _hitBody.AddComponent<CapsuleCollider>(); val3.direction = 1; val3.height = 2.4f; val3.radius = 0.71999997f; val3.center = new Vector3(0f, 1.2f, 0f); ((Collider)val3).isTrigger = true; HitCollider = (Collider)(object)val3; ILogger logger4 = _logger; if (logger4 != null) { logger4.Log($"boss renderer shader: {_shaderName} (supported={(Object)(object)_shader != (Object)null && _shader.isSupported})"); } ILogger logger5 = _logger; if (logger5 != null) { logger5.Log($"boss renderer floor y: {_floorY}"); } ILogger logger6 = _logger; if (logger6 != null) { logger6.Log($"boss collision: capsule h={2.4f} r={0.71999997f:0.00} on layer " + "'" + ((num2 >= 0) ? "Entities" : "Default") + "' (kinematic Rigidbody); weapon-hit capsule on '" + ((num3 >= 0) ? "Hitbox" : "Default") + "' (trigger)"); } } public void Apply(PresentationState state) { _state = state; _hasState = true; } public void Handle(IPresentationEvent presentationEvent) { //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_00b6: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012c: 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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_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_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) if (!(presentationEvent is BossAppeared)) { AttackTelegraphStarted val = (AttackTelegraphStarted)(object)((presentationEvent is AttackTelegraphStarted) ? presentationEvent : null); SimVector2 val8; AttackInstanceId attack; if (val == null) { AttackLanded val2 = (AttackLanded)(object)((presentationEvent is AttackLanded) ? presentationEvent : null); if (val2 == null) { WeakPointVisibilityChanged val3 = (WeakPointVisibilityChanged)(object)((presentationEvent is WeakPointVisibilityChanged) ? presentationEvent : null); if (val3 == null) { PhaseTransition val4 = (PhaseTransition)(object)((presentationEvent is PhaseTransition) ? presentationEvent : null); if (val4 == null) { BossHit val5 = (BossHit)(object)((presentationEvent is BossHit) ? presentationEvent : null); if (val5 == null) { BossMoved val6 = (BossMoved)(object)((presentationEvent is BossMoved) ? presentationEvent : null); if (val6 == null) { if (!(presentationEvent is BossRoared)) { RageChanged val7 = (RageChanged)(object)((presentationEvent is RageChanged) ? presentationEvent : null); if (val7 == null) { if (presentationEvent is BossDefeated) { _dead = true; _deathElapsed = 0f; _telegraphActive = false; HideTelegraph(); ILogger logger = _logger; if (logger != null) { logger.Log("[cue] BossDefeated"); } } } else { if (val7.Enraged) { _roarTimer = 1.9f; } ILogger logger2 = _logger; if (logger2 != null) { logger2.Log("[cue] RageChanged enraged=" + val7.Enraged); } } } else { _roarTimer = 1.9f; ILogger logger3 = _logger; if (logger3 != null) { logger3.Log("[cue] BossRoared"); } } } else { ILogger logger4 = _logger; if (logger4 != null) { val8 = val6.Position; object arg = ((SimVector2)(ref val8)).X; object arg2 = val6.PositionHeight; val8 = val6.Position; logger4.Log($"[cue] BossMoved to ({arg:0.0}, {arg2:0.0}, {((SimVector2)(ref val8)).Z:0.0})"); } } } else { _flashTimer = 0.12f; _flinchTimer = 0.16f; _flashWeakPoint = val5.WeakPointHit; } } else { _phasePulseTimer = 0.5f; ILogger logger5 = _logger; if (logger5 != null) { logger5.Log($"[cue] PhaseTransition -> phaseVisual={val4.PhaseVisualId}"); } } } else if (val3.Exposed) { _flashTimer = 0.15f; _flashWeakPoint = true; } } else { _telegraphActive = false; HideTelegraph(); AttackVisualKind kind = val2.Kind; val8 = val2.AimPoint; float x = ((SimVector2)(ref val8)).X; float floorY = _floorY; val8 = val2.AimPoint; SpawnImpact(kind, new Vector3(x, floorY, ((SimVector2)(ref val8)).Z)); ILogger logger6 = _logger; if (logger6 != null) { object arg3 = val2.Kind; attack = val2.Attack; logger6.Log($"[cue] AttackLanded {arg3} attack={((AttackInstanceId)(ref attack)).Value}"); } } } else { _telegraphActive = true; _telegraphKind = val.Kind; val8 = val.AimPoint; float x2 = ((SimVector2)(ref val8)).X; float floorY2 = _floorY; val8 = val.AimPoint; _telegraphAim = new Vector3(x2, floorY2, ((SimVector2)(ref val8)).Z); _telegraphStart = _time; _telegraphSeconds = Mathf.Max(0.05f, val.TelegraphSeconds); ILogger logger7 = _logger; if (logger7 != null) { object[] obj = new object[4] { val.Kind, null, null, null }; attack = val.Attack; obj[1] = ((AttackInstanceId)(ref attack)).Value; val8 = val.AimPoint; obj[2] = ((SimVector2)(ref val8)).X; val8 = val.AimPoint; obj[3] = ((SimVector2)(ref val8)).Z; logger7.Log(string.Format("[cue] AttackTelegraphStarted {0} attack={1} aim=({2:0.0},{3:0.0})", obj)); } } } else { _appearPulseTimer = 0.4f; ILogger logger8 = _logger; if (logger8 != null) { logger8.Log("[cue] BossAppeared"); } } } public void Render(float deltaSeconds) { //IL_0046: 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_0067: 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_00c4: Invalid comparison between Unknown and I4 //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Invalid comparison between Unknown and I4 //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Invalid comparison between Unknown and I4 //IL_010a: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) if (deltaSeconds > 0f) { _time += deltaSeconds; } Camera main = Camera.main; if (SpriteScale > 0f) { _root.transform.localScale = new Vector3(SpriteScale, SpriteScale, SpriteScale); } if (_hasState) { if (_state.Activity != _lastActivity) { _lastActivity = _state.Activity; _activityStart = _time; if ((int)_state.Activity != 1 && (int)_state.Activity != 2) { _telegraphActive = false; } } RelocationOffset(out var sink, out var tilt); bool flag = (int)_state.Activity != 6 && !IsBuried(); if (_collisionBody.activeSelf != flag) { _collisionBody.SetActive(flag); _hitBody.SetActive(flag); } Transform transform = _root.transform; SimVector2 val = _state.Position; float x = ((SimVector2)(ref val)).X; float num = _state.PositionHeight + sink; val = _state.Position; transform.position = new Vector3(x, num, ((SimVector2)(ref val)).Z); _relocationTilt = tilt; val = _state.Facing; if (!(Math.Abs(((SimVector2)(ref val)).X) > 0.0001f)) { val = _state.Facing; if (!(Math.Abs(((SimVector2)(ref val)).Z) > 0.0001f)) { goto IL_01d1; } } Transform aimPivot = _aimPivot; val = _state.Facing; float x2 = ((SimVector2)(ref val)).X; val = _state.Facing; aimPivot.rotation = Quaternion.LookRotation(new Vector3(x2, 0f, ((SimVector2)(ref val)).Z), Vector3.up); goto IL_01d1; } goto IL_01d7; IL_01d7: OrientBody(main); AnimateTelegraph(); AnimateTransients(deltaSeconds); if (_flashTimer > 0f) { _flashTimer -= deltaSeconds; if (_flashTimer <= 0f) { UpdateBodyColor(); } } if (_phasePulseTimer > 0f) { _phasePulseTimer -= deltaSeconds; } if (_appearPulseTimer > 0f) { _appearPulseTimer -= deltaSeconds; } if (_roarTimer > 0f) { _roarTimer -= deltaSeconds; } if (_flinchTimer > 0f) { _flinchTimer -= deltaSeconds; } if (_dead) { _deathElapsed += deltaSeconds; _bodyBillboard.localScale = Vector3.one; } else { float num2 = 1f + ((_phasePulseTimer > 0f) ? (_phasePulseTimer * 0.5f) : 0f) + ((_appearPulseTimer > 0f) ? (_appearPulseTimer * 0.4f) : 0f); float num3 = RoarRise() * 0.45f - FlinchDrop() * 0.09f; _bodyBillboard.localScale = new Vector3(num2 * (1f - num3 * 0.55f), num2 * (1f + num3), num2); } return; IL_01d1: UpdateBodyColor(); goto IL_01d7; } private void OrientBody(Camera camera) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_0070: 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_00bb: 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_00d0: Unknown result type (might be due to invalid IL or missing references) OrientBodyFacing(camera); if (Math.Abs(_relocationTilt) > 0.01f) { Transform bodyBillboard = _bodyBillboard; bodyBillboard.rotation *= Quaternion.Euler(0f, 0f, _relocationTilt); } float num = FlinchDrop(); if (num > 0.001f) { Transform bodyBillboard2 = _bodyBillboard; bodyBillboard2.rotation *= Quaternion.Euler(0f, 0f, 4f * num); } float num2 = RoarRise(); if (num2 > 0.001f) { float num3 = Mathf.Sin(_time * 9f * (float)Math.PI * 2f) * 7f * num2; Transform bodyBillboard3 = _bodyBillboard; bodyBillboard3.rotation *= Quaternion.Euler(0f, 0f, num3); } } private void OrientBodyFacing(Camera camera) { //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_002f: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_006d: 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_007a: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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) switch (FacingMode) { case BossFacingMode.Fixed: _bodyBillboard.rotation = Quaternion.LookRotation(-_fixedForward, Vector3.up); break; case BossFacingMode.NearestPlayer: { ? val; if (!_hasState) { val = _fixedForward; } else { SimVector2 facing = _state.Facing; float x = ((SimVector2)(ref facing)).X; facing = _state.Facing; val = new Vector3(x, 0f, ((SimVector2)(ref facing)).Z); } Vector3 val2 = (Vector3)val; if (((Vector3)(ref val2)).sqrMagnitude < 1E-06f) { val2 = _fixedForward; } _bodyBillboard.rotation = Quaternion.LookRotation(-((Vector3)(ref val2)).normalized, Vector3.up); break; } default: if ((Object)(object)camera != (Object)null) { _bodyBillboard.rotation = FaceCameraRotation(_bodyBillboard.position, ((Component)camera).transform.position, LockPitch); } break; } } private void RelocationOffset(out float sink, out float tilt) { //IL_002f: 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_0035: 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_0049: Expected I4, but got Unknown if (_dead) { DeathOffset(out sink, out tilt); return; } float num = Math.Max(0f, _time - _activityStart); BossVisualActivity activity = _state.Activity; switch (activity - 5) { case 0: { float num4 = Mathf.Clamp01(num / 0.42f); sink = -3.2f * num4 * num4; tilt = 23f * Mathf.Sin(num4 * (float)Math.PI * 2f); break; } case 1: sink = -3.2f; tilt = 0f; break; case 2: { float num2 = Mathf.Clamp01(num / 0.33f); sink = -3.2f * (1f - num2) * (1f - num2); float num3 = Mathf.Clamp01(1f - num / 1.6f); tilt = 23f * num3 * num3 * Mathf.Sin(num * 3.2f * (float)Math.PI * 2f); break; } default: sink = 0f; tilt = 0f; break; } } private void DeathOffset(out float sink, out float tilt) { float num = Mathf.Clamp01(_deathElapsed / 2.4f); sink = (0f - DeathDepth()) * num * num; tilt = 14f * (1f - num * 0.4f) * Mathf.Sin(_deathElapsed * 1.1f * (float)Math.PI * 2f); } private float DeathDepth() { return 2.4f * ((SpriteScale > 0f) ? SpriteScale : 2f) + 1.5f; } private bool IsBuried() { if (_dead) { return _deathElapsed >= 1.2f; } return false; } private float FlinchDrop() { if (_flinchTimer <= 0f) { return 0f; } float num = Mathf.Clamp01(_flinchTimer / 0.16f); return num * num; } private Quaternion FaceCameraRotation(Vector3 spritePos, Vector3 cameraPos, bool lockPitch) { //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_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_002c: 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_001c: 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_0056: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00b7: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //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_00c4: Unknown result type (might be due to invalid IL or missing references) Vector3 val = cameraPos - spritePos; if (((Vector3)(ref val)).sqrMagnitude < 1E-06f) { return _bodyBillboard.rotation; } Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(normalized.x, 0f, normalized.z); if (((Vector3)(ref val2)).sqrMagnitude < 1E-06f) { val2 = _bodyBillboard.forward; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude < 1E-06f) { val2 = _fixedForward; } } val2 = ((Vector3)(ref val2)).normalized; if (lockPitch) { return Quaternion.LookRotation(-val2, Vector3.up); } Vector3 val3 = ((Mathf.Abs(Vector3.Dot(Vector3.up, normalized)) > 0.999f) ? Vector3.forward : Vector3.up); return Quaternion.LookRotation(-normalized, val3); } private float RoarRise() { if (_roarTimer <= 0f) { return 0f; } float num = Mathf.Clamp01(1f - _roarTimer / 1.9f); if (num < 0.18f) { return Mathf.SmoothStep(0f, 1f, num / 0.18f); } float num2 = 0.52f; if (num < num2) { return 1f; } return Mathf.SmoothStep(1f, 0f, (num - num2) / Mathf.Max(0.0001f, 1f - num2)); } private Color Fogged(Color color) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_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_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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; float fogStartDistance = RenderSettings.fogStartDistance; float fogEndDistance = RenderSettings.fogEndDistance; float num = (((Object)(object)main != (Object)null) ? Vector3.Distance(((Component)main).transform.position, _bodyBillboard.position) : 0f); if ((Object)(object)main == (Object)null || fogEndDistance <= fogStartDistance) { return color; } if (!_reportedFog) { _reportedFog = true; ILogger logger = _logger; if (logger != null) { logger.Log($"[boss-fog] the level fades to {RenderSettings.fogColor} between {fogStartDistance:0.#}m and " + $"{fogEndDistance:0.#}m; the boss now fades with it."); } } float num2 = Mathf.Clamp01((fogEndDistance - num) / (fogEndDistance - fogStartDistance)); Color result = Color.Lerp(RenderSettings.fogColor, color, num2); result.a = color.a; return result; } private void UpdateBodyColor() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) Color color; if (_dead) { color = DeadColor; } else { if (_flashTimer > 0f && !_flashWeakPoint) { SetColor(_bodyMat, Color.white * 2.6f); return; } color = ((_hasState && _state.Enraged) ? RageTint : ((!_bodyTextured) ? ((_hasState && _state.PhaseVisualId >= 2) ? PhaseTwoColor : PhaseOneColor) : Color.white)); } SetColor(_bodyMat, Fogged(color)); } private void AnimateTelegraph() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0081: 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_0092: Invalid comparison between Unknown and I4 //IL_009b: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Invalid comparison between Unknown and I4 //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) if (_telegraphActive) { EnsureTelegraph(); float num = ((_telegraphSeconds > 0f) ? Mathf.Clamp01((_time - _telegraphStart) / _telegraphSeconds) : 1f); _telegraph.transform.position = _telegraphAim + Vector3.up * 0.02f; _telegraph.transform.rotation = Quaternion.Euler(90f, 0f, 0f); Color val = (((int)_telegraphKind == 1) ? TelegraphProjectileColor : TelegraphAreaColor); float num2 = (((int)_telegraphKind == 1) ? Mathf.Lerp(3f, 1f, num) : Mathf.Lerp(0.3f, 3f, num)); _telegraph.transform.localScale = new Vector3(num2, num2, 1f); float num3 = 0.5f + 0.5f * Mathf.Sin(_time * Mathf.Lerp(6f, 24f, num)); SetColor(_telegraphMat, val * (0.4f + 0.6f * num3)); } } private void SpawnImpact(AttackVisualKind kind, Vector3 aim) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_006c: 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_0080: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) if ((int)kind == 1) { Transform val = CreateCube("Projectile", TelegraphProjectileColor); val.position = _muzzle.position; val.localScale = Vector3.one * 0.3f; _transients.Add(new Transient(((Component)val).gameObject, _muzzle.position, aim, 0.28f, TransientKind.Fly)); } else { Material material; GameObject val2 = CreateQuad("AreaBurst", null, TelegraphAreaColor, out material); val2.transform.position = aim + Vector3.up * 0.03f; val2.transform.rotation = Quaternion.Euler(90f, 0f, 0f); val2.transform.localScale = new Vector3(3f, 3f, 1f); _transients.Add(new Transient(val2, aim, aim, 0.35f, TransientKind.Fade, material)); } } private void AnimateTransients(float deltaSeconds) { //IL_0077: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) for (int num = _transients.Count - 1; num >= 0; num--) { Transient transient = _transients[num]; transient.Elapsed += deltaSeconds; float num2 = ((transient.Seconds > 0f) ? Mathf.Clamp01(transient.Elapsed / transient.Seconds) : 1f); if ((Object)(object)transient.Object != (Object)null) { if (transient.Kind == TransientKind.Fly) { transient.Object.transform.position = Vector3.Lerp(transient.From, transient.To, num2); } else if (transient.Kind == TransientKind.Fade) { transient.Object.transform.localScale = new Vector3(3f + num2 * 2f, 3f + num2 * 2f, 1f); } } if (num2 >= 1f) { if ((Object)(object)transient.Object != (Object)null) { Object.Destroy((Object)(object)transient.Object); } _transients.RemoveAt(num); } } } public void Dispose() { foreach (Transient transient in _transients) { if ((Object)(object)transient.Object != (Object)null) { Object.Destroy((Object)(object)transient.Object); } } _transients.Clear(); HideTelegraph(); if ((Object)(object)_telegraph != (Object)null) { Object.Destroy((Object)(object)_telegraph); _telegraph = null; } if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } if ((Object)(object)_bodyTexture != (Object)null) { Object.Destroy((Object)(object)_bodyTexture); } } private static Vector3 ComputeSpawnFacing(Vector3 bossPos) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) //IL_0026: 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_0049: 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) Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return Vector3.forward; } Vector3 val = ((Component)main).transform.position - bossPos; val.y = 0f; if (!(((Vector3)(ref val)).sqrMagnitude > 1E-06f)) { return Vector3.forward; } return ((Vector3)(ref val)).normalized; } private GameObject CreateQuad(string name, Transform parent, Color color, out Material material) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) GameObject val = GameObject.CreatePrimitive((PrimitiveType)5); ((Object)val).name = name; StripCollider(val); if ((Object)(object)parent != (Object)null) { val.transform.SetParent(parent, false); } material = new Material(_shader); SetColor(material, color); ((Renderer)val.GetComponent<MeshRenderer>()).sharedMaterial = material; return val; } private Transform CreateCube(string name, Color color) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)obj).name = name; StripCollider(obj); Material val = new Material(_shader); SetColor(val, color); ((Renderer)obj.GetComponent<MeshRenderer>()).sharedMaterial = val; return obj.transform; } private static Collider AddBox(GameObject go) { BoxCollider obj = go.AddComponent<BoxCollider>(); ((Collider)obj).isTrigger = true; go.layer = 2; return (Collider)(object)obj; } private static void StripCollider(GameObject go) { Collider component = go.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } } private void EnsureTelegraph() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_telegraph != (Object)null) { _telegraph.SetActive(true); return; } _telegraph = GameObject.CreatePrimitive((PrimitiveType)5); ((Object)_telegraph).name = "Telegraph"; StripCollider(_telegraph); _telegraphMat = new Material(_shader); SetColor(_telegraphMat, TelegraphAreaColor); ((Renderer)_telegraph.GetComponent<MeshRenderer>()).sharedMaterial = _telegraphMat; } private void HideTelegraph() { if ((Object)(object)_telegraph != (Object)null) { _telegraph.SetActive(false); } } private static Texture2D LoadEmbeddedBodyTexture(ILogger logger) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown try { Assembly assembly = typeof(BossPresentation).Assembly; string text = null; string[] manifestResourceNames = assembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (text2.EndsWith("boss-body.png", StringComparison.OrdinalIgnoreCase)) { text = text2; break; } } if (text == null) { if (logger != null) { logger.Log("boss body sprite: none embedded; using a flat coloured quad."); } return null; } byte[] array; using (Stream stream = assembly.GetManifestResourceStream(text)) { if (stream == null) { return null; } array = new byte[stream.Length]; int num; for (int j = 0; j < array.Length; j += num) { num = stream.Read(array, j, array.Length - j); if (num <= 0) { break; } } } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1, name = "FalseGodsBossBody" }; if (!TryLoadImageViaGame(val, array)) { Object.Destroy((Object)(object)val); if (logger != null) { logger.LogWarning("boss body sprite '" + text + "' failed to decode; using a flat coloured quad."); } return null; } if (logger != null) { logger.Log($"boss body sprite: '{text}' loaded ({((Texture)val).width}x{((Texture)val).height})."); } return val; } catch (Exception ex) { if (logger != null) { logger.LogWarning("boss body sprite failed to load (" + ex.Message + "); using a flat coloured quad."); } return null; } } private static bool TryLoadImageViaGame(Texture2D texture, byte[] bytes) { Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule"); if (type == null) { return false; } MethodInfo method = type.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); if (method != null) { return (bool)method.Invoke(null, new object[2] { texture, bytes }); } MethodInfo method2 = type.GetMethod("LoadImage", new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }); if (method2 != null) { return (bool)method2.Invoke(null, new object[3] { texture, bytes, false }); } return false; } private static Shader ResolveShader(ILogger logger, out string chosenName) { string[] array = new string[5] { "Universal Render Pipeline/Unlit", "Sprites/Default", "Unlit/Color", "Universal Render Pipeline/Lit", "Hidden/Internal-Colored" }; foreach (string text in array) { Shader val = Shader.Find(text); if ((Object)(object)val != (Object)null && val.isSupported) { chosenName = text; return val; } } if (logger != null) { logger.LogWarning("No unlit colour shader resolved; boss will render with the fallback (magenta)."); } Shader val2 = Shader.Find("Hidden/InternalErrorShader"); chosenName = (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "<none>"); return val2; } private static void SetColor(Material material, Color color) { //IL_002a: 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: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { bool num = material.HasProperty("_BaseColor"); bool flag = material.HasProperty("_Color"); if (num) { material.SetColor("_BaseColor", color); } if (flag) { material.SetColor("_Color", color); } if (!num && !flag) { material.color = color; } } } } } namespace FalseGods.UnityRuntime.Arena { public sealed class ArenaPresentation : IEncounterPresentation { private const string ExitBlockerPath = "VisualRoot/VanillaProps/ExitRoom/ExitBlocker"; private const string LightingRootName = "LightingRoot"; private static readonly Color EngagedLightColor = new Color(1f, 0.45f, 0.35f); private readonly BundleArenaRealization _realization; private readonly ILogger _logger; public ArenaPresentation(BundleArenaRealization realization, ILogger logger = null) { _realization = realization ?? throw new ArgumentNullException("realization"); _logger = logger; } public void Apply(PresentationState state) { } public void Handle(IPresentationEvent presentationEvent) { //IL_0040: 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) GameObject currentRoot = _realization.CurrentRoot; if ((Object)(object)currentRoot == (Object)null) { return; } MechanismGroupEngaged val = (MechanismGroupEngaged)(object)((presentationEvent is MechanismGroupEngaged) ? presentationEvent : null); if (val == null) { if (presentationEvent is ExitOpened) { OpenExit(currentRoot); } return; } TintLights(currentRoot); ILogger logger = _logger; if (logger != null) { MechanismGroupId val2 = val.Group; logger.Log("[arena-cue] MechanismGroupEngaged '" + ((MechanismGroupId)(ref val2)).Value + "' — lights tinted"); } } private static void TintLights(GameObject root) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) Transform val = root.transform.Find("LightingRoot"); Light[] componentsInChildren = ((Component)(((Object)(object)val != (Object)null) ? val : root.transform)).GetComponentsInChildren<Light>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].color = EngagedLightColor; } } private void OpenExit(GameObject root) { Transform val = root.transform.Find("VisualRoot/VanillaProps/ExitRoom/ExitBlocker"); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); ILogger logger = _logger; if (logger != null) { logger.Log("[arena-cue] ExitOpened — the rock over the doorway is gone"); } } else { ILogger logger2 = _logger; if (logger2 != null) { logger2.LogWarning("[arena-cue] ExitOpened but 'VisualRoot/VanillaProps/ExitRoom/ExitBlocker' was not found"); } } } } public sealed class BundleArenaRealization : IArenaAssetProvider, IArenaRealization { private readonly string _bundlePath; private readonly string _artifactPath; private readonly string _prefabName; private readonly ILogger _logger; private AssetBundle _bundle; private GameObject _prefab; private GameObject _root; public GameObject CurrentRoot => _root; public BundleArenaRealization(string bundlePath, string artifactPath, string prefabName, ILogger logger = null) { _bundlePath = bundlePath ?? throw new ArgumentNullException("bundlePath"); _artifactPath = artifactPath ?? throw new ArgumentNullException("artifactPath"); _prefabName = prefabName ?? throw new ArgumentNullException("prefabName"); _logger = logger; } public ArenaAssetLoadResult Load() { if ((Object)(object)_bundle != (Object)null) { throw new InvalidOperationException("Arena assets are already loaded; the flow loads once per encounter."); } if (!File.Exists(_bundlePath)) { return ArenaAssetLoadResult.Failed("arena bundle not found at " + _bundlePath); } if (!File.Exists(_artifactPath)) { return ArenaAssetLoadResult.Failed("arena content artifact not found at " + _artifactPath); } _bundle = AssetBundle.LoadFromFile(_bundlePath); if ((Object)(object)_bundle == (Object)null) { return ArenaAssetLoadResult.Failed("arena bundle failed to load from " + _bundlePath); } _prefab = _bundle.LoadAsset<GameObject>(_prefabName); if ((Object)(object)_prefab == (Object)null) { return ArenaAssetLoadResult.Failed("prefab '" + _prefabName + "' not found in the arena bundle"); } string text; try { text = File.ReadAllText(_artifactPath); } catch (Exception ex) { return ArenaAssetLoadResult.Failed("arena artifact unreadable: " + ex.Message); } ILogger logger = _logger; if (logger != null) { logger.Log("[arena-assets] bundle + artifact loaded (" + _prefabName + ")"); } return ArenaAssetLoadResult.Loaded(text); } public void Release() { if ((Object)(object)_root != (Object)null) { Teardown(); } if ((Object)(object)_bundle != (Object)null) { _bundle.Unload(true); _bundle = null; _prefab = null; ILogger logger = _logger; if (logger != null) { logger.Log("[arena-assets] bundle released"); } } } public ArenaRealizationResult Realize(ArenaWorldPoint origin, IReadOnlyList<string> parityPaths, IReadOnlyList<string> markerPaths, IReadOnlyList<string> markerGroupPaths) { //IL_004e: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Expected O, but got Unknown //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Expected O, but got Unknown if ((Object)(object)_prefab == (Object)null) { return ArenaRealizationResult.Failed("arena assets are not loaded"); } if ((Object)(object)_root != (Object)null) { return ArenaRealizationResult.Failed("the arena is already realized"); } _root = Object.Instantiate<GameObject>(_prefab, new Vector3(((ArenaWorldPoint)(ref origin)).X, ((ArenaWorldPoint)(ref origin)).Y, ((ArenaWorldPoint)(ref origin)).Z), Quaternion.identity); ((Object)_root).name = "FalseGodsArena"; List<RealizedParityNode> list = new List<RealizedParityNode>(parityPaths.Count); foreach (string parityPath in parityPaths) { Transform val = _root.transform.Find(parityPath); if (!((Object)(object)val == (Object)null)) { list.Add(new RealizedParityNode(parityPath, ToPoint(val.localPosition), new ArenaRotation(val.localRotation.x, val.localRotation.y, val.localRotation.z, val.localRotation.w), ToPoint(val.localScale))); } } List<RealizedMarker> list2 = new List<RealizedMarker>(markerPaths.Count); foreach (string markerPath in markerPaths) { Transform val2 = _root.transform.Find(markerPath); if ((Object)(object)val2 != (Object)null) { list2.Add(new RealizedMarker(markerPath, ToPoint(val2.position), ToPoint(val2.localScale))); } } int num = 0; foreach (string markerGroupPath in markerGroupPaths) { Transform val3 = _root.transform.Find(markerGroupPath); if (!((Object)(object)val3 == (Object)null)) { for (int i = 0; i < val3.childCount; i++) { Transform child = val3.GetChild(i); list2.Add(new RealizedMarker(markerGroupPath + "/" + ((Object)child).name, ToPoint(child.position), ToPoint(child.localScale))); num++; } } } ILogger logger = _logger; if (logger != null) { logger.Log($"[arena] realized at ({((ArenaWorldPoint)(ref origin)).X:0.0}, {((ArenaWorldPoint)(ref origin)).Y:0.0}, {((ArenaWorldPoint)(ref origin)).Z:0.0}); " + $"{list.Count}/{parityPaths.Count} parity nodes, " + $"{list2.Count - num}/{markerPaths.Count} markers, {num} grouped marker(s)"); } return new ArenaRealizationResult(true, (string)null, (IReadOnlyList<RealizedParityNode>)list, (IReadOnlyList<RealizedMarker>)list2); } public void Teardown() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); _root = null; ILogger logger = _logger; if (logger != null) { logger.Log("[arena] realized hierarchy destroyed"); } } } private static ArenaWorldPoint ToPoint(Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new ArenaWorldPoint(v.x, v.y, v.z); } } }