using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Runtime.InteropServices; using EntityStates; using RoR2.CharacterAI; using RoR2.UI; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Networking; namespace RoR2; [RequireComponent(typeof(HoldoutZoneController))] [RequireComponent(typeof(SceneExitController))] public sealed class TeleporterInteraction : NetworkBehaviour, IInteractable { public enum ActivationState { Idle, IdleToCharging, Charging, Charged, Finished } private abstract class BaseTeleporterState : BaseState { protected TeleporterInteraction teleporterInteraction { get; private set; } public abstract ActivationState backwardsCompatibleActivationState { get; } protected virtual bool shouldEnableChargingSphere => false; public override void OnEnter() { base.OnEnter(); teleporterInteraction = GetComponent(); teleporterInteraction.holdoutZoneController.enabled = shouldEnableChargingSphere; } public virtual Interactability GetInteractability(Interactor activator) { return Interactability.Disabled; } public virtual string GetContextString(Interactor activator) { return null; } public virtual void OnInteractionBegin(Interactor activator) { } protected void SetChildActive(string childLocatorName, bool newActive) { Transform transform = teleporterInteraction.modelChildLocator.FindChild(childLocatorName); if ((bool)transform) { transform.gameObject.SetActive(newActive); } } } private class IdleState : BaseTeleporterState { private float _tutorialWavePillarTimer; private bool _canTutorialWavePillarTrigger = TutorialManager.isTutorialEnabled; public override ActivationState backwardsCompatibleActivationState => ActivationState.Idle; public override Interactability GetInteractability(Interactor activator) { return Interactability.Available; } public override string GetContextString(Interactor activator) { return Language.GetString(base.teleporterInteraction.beginContextString); } public override void OnInteractionBegin(Interactor activator) { Chat.SendBroadcastChat(new SubjectChatMessage { subjectAsCharacterBody = activator.GetComponent(), baseToken = "PLAYER_ACTIVATED_TELEPORTER" }); if (base.teleporterInteraction.showExtraBossesIndicator) { Chat.SendBroadcastChat(new Chat.SimpleChatMessage { baseToken = "SHRINE_BOSS_BEGIN_TRIAL" }); } base.teleporterInteraction.chargeActivatorServer = activator.gameObject; outer.SetNextState(new IdleToChargingState()); } public override void FixedUpdate() { base.FixedUpdate(); if (!_canTutorialWavePillarTrigger) { return; } _tutorialWavePillarTimer -= Time.fixedDeltaTime; if (_tutorialWavePillarTimer < 0f) { _tutorialWavePillarTimer = base.teleporterInteraction.triggerWavePillarInterval; if (Run.instance.ambientLevel >= base.teleporterInteraction.sceneStartAmbientLevel + 2f) { _canTutorialWavePillarTrigger = false; SetChildActive("TutorialWavePillar", newActive: true); } } } public override void OnExit() { base.OnExit(); SetChildActive("TutorialWavePillar", newActive: false); } } private class IdleToChargingState : BaseTeleporterState { public override ActivationState backwardsCompatibleActivationState => ActivationState.IdleToCharging; public override void OnEnter() { base.OnEnter(); SetChildActive("IdleToChargingEffect", newActive: true); SetChildActive("PPVolume", newActive: true); base.teleporterInteraction.NetworkisActivated = true; base.teleporterInteraction.teleporterPositionIndicator.GetComponent().isActivated = true; } public override void OnExit() { SetChildActive("IdleToChargingEffect", newActive: false); base.OnExit(); } public override void FixedUpdate() { base.FixedUpdate(); if (base.fixedAge > 3f && NetworkServer.active) { outer.SetNextState(new ChargingState()); } } } private class ChargingState : BaseTeleporterState { private CombatDirector bonusDirector => base.teleporterInteraction.bonusDirector; private CombatDirector bossDirector => base.teleporterInteraction.bossDirector; protected override bool shouldEnableChargingSphere => true; public override ActivationState backwardsCompatibleActivationState => ActivationState.Charging; public override void OnEnter() { base.OnEnter(); TeleporterInteraction.onTeleporterBeginChargingGlobal?.Invoke(base.teleporterInteraction); if (NetworkServer.active) { if ((bool)bonusDirector) { bonusDirector.enabled = true; } if ((bool)bossDirector) { bossDirector.enabled = true; bossDirector.monsterCredit += (int)(600f * Mathf.Pow(Run.instance.compensatedDifficultyCoefficient, 0.5f) * (float)(1 + base.teleporterInteraction.shrineBonusStacks)); bossDirector.currentSpawnTarget = base.gameObject; bossDirector.SetNextSpawnAsBoss(); } if ((bool)DirectorCore.instance) { CombatDirector[] components = DirectorCore.instance.GetComponents(); if (components.Length != 0) { CombatDirector[] array = components; for (int i = 0; i < array.Length; i++) { array[i].enabled = false; } } } if ((bool)base.teleporterInteraction.outsideInteractableLocker) { base.teleporterInteraction.outsideInteractableLocker.enabled = true; } ReadOnlyCollection teamMembers = TeamComponent.GetTeamMembers(TeamIndex.Player); for (int j = 0; j < teamMembers.Count; j++) { TeamComponent teamComponent = teamMembers[j]; CharacterBody body = teamComponent.body; if (!body) { continue; } CharacterMaster master = teamComponent.body.master; if ((bool)master) { int itemCount = master.inventory.GetItemCount(RoR2Content.Items.WardOnLevel); if (itemCount > 0) { GameObject obj = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/NetworkedObjects/WarbannerWard"), body.transform.position, Quaternion.identity); obj.GetComponent().teamIndex = TeamIndex.Player; obj.GetComponent().Networkradius = 8f + 8f * (float)itemCount; NetworkServer.Spawn(obj); } } } } SetChildActive("ChargingEffect", newActive: true); } public override void OnExit() { if (NetworkServer.active) { if ((bool)base.teleporterInteraction.outsideInteractableLocker) { base.teleporterInteraction.outsideInteractableLocker.enabled = false; } if ((bool)bossDirector) { bossDirector.enabled = false; } if ((bool)bonusDirector) { bonusDirector.enabled = false; } } SetChildActive("ChargingEffect", newActive: false); base.OnExit(); } public override void FixedUpdate() { base.FixedUpdate(); if (NetworkServer.active) { if (base.teleporterInteraction.holdoutZoneController.charge >= 1f) { if ((bool)bonusDirector) { bonusDirector.enabled = false; } if (base.teleporterInteraction.monstersCleared) { if ((bool)bossDirector) { bossDirector.enabled = false; } outer.SetNextState(new ChargedState()); } } if ((bool)base.teleporterInteraction.outsideInteractableLocker) { base.teleporterInteraction.outsideInteractableLocker.radius = base.teleporterInteraction.holdoutZoneController.currentRadius; } } if ((bool)SceneWeatherController.instance) { SceneWeatherController.instance.weatherLerp = SceneWeatherController.instance.weatherLerpOverChargeTime.Evaluate((float)base.teleporterInteraction.chargePercent * 0.01f); } base.teleporterInteraction.UpdateMonstersClear(); } public override Interactability GetInteractability(Interactor activator) { return Interactability.ConditionsNotMet; } } private class ChargedState : BaseTeleporterState { public override ActivationState backwardsCompatibleActivationState => ActivationState.Charged; public override void OnEnter() { base.OnEnter(); base.teleporterInteraction.teleporterPositionIndicator.GetComponent().isCharged = true; SetChildActive("ChargedEffect", newActive: true); if (NetworkServer.active) { base.teleporterInteraction.AttemptToSpawnAllEligiblePortals(); if (RunArtifactManager.instance.IsArtifactEnabled(CU8Content.Artifacts.Delusion)) { ResetChests(); } } TeleporterInteraction.onTeleporterChargedGlobal?.Invoke(base.teleporterInteraction); } private void ResetChests() { foreach (ChestBehavior instances in InstanceTracker.GetInstancesList()) { instances.CallRpcResetChests(); } } public override void OnExit() { SetChildActive("ChargedEffect", newActive: false); base.OnExit(); } public override void FixedUpdate() { base.FixedUpdate(); } public override Interactability GetInteractability(Interactor activator) { if (!base.teleporterInteraction.monstersCleared) { return Interactability.ConditionsNotMet; } return Interactability.Available; } public override string GetContextString(Interactor activator) { return Language.GetString(base.teleporterInteraction.exitContextString); } public override void OnInteractionBegin(Interactor activator) { outer.SetNextState(new FinishedState()); } } private class FinishedState : BaseTeleporterState { public override ActivationState backwardsCompatibleActivationState => ActivationState.Finished; public override void OnEnter() { base.OnEnter(); base.teleporterInteraction.sceneExitController.Begin(); TeleporterInteraction.onTeleporterFinishGlobal?.Invoke(base.teleporterInteraction); } } [Header("Component and Object References")] public CombatDirector bonusDirector; public CombatDirector bossDirector; public EntityStateMachine mainStateMachine; public OutsideInteractableLocker outsideInteractableLocker; [Header("Interactability")] public string beginContextString; public string exitContextString; [Header("Teleporter Tutorial")] public float triggerWavePillarInterval = 1f; private Dictionary interactableObjectMap; private BossGroup bossGroup; private ChildLocator modelChildLocator; [SyncVar] private bool _locked; [SyncVar(hook = "OnSyncTeleporterDiscovered")] private bool isDiscovered; [SyncVar] private bool isActivated; [SerializeField] private float discoveryRadius = 20f; private PositionIndicator teleporterPositionIndicator; private ChargeIndicatorController teleporterChargeIndicatorController; private Color originalTeleporterColor; private GameObject bossShrineIndicator; [SyncVar(hook = "OnSyncShouldAttemptToSpawnShopPortal")] private bool _shouldAttemptToSpawnShopPortal; [SyncVar(hook = "OnSyncShouldAttemptToSpawnGoldshoresPortal")] private bool _shouldAttemptToSpawnGoldshoresPortal; [SyncVar(hook = "OnSyncShouldAttemptToSpawnMSPortal")] private bool _shouldAttemptToSpawnMSPortal; private Xoroshiro128Plus rng; private GameObject chargeActivatorServer; private bool monstersCleared; [SyncVar] private bool showExtraBossesIndicator; public SpawnCard shopPortalSpawnCard; public SpawnCard goldshoresPortalSpawnCard; public SpawnCard msPortalSpawnCard; public PortalSpawner[] portalSpawners; public float baseShopSpawnChance = 0.375f; private List currentPings = new List(); private Particle_SetMinSize cachedParticleMinSizeScript; private float particleScaleUpdateTimer; private const float particleScaleUpdateInterval = 0.5f; private bool shouldScaleParticles; private LocalUser cachedLocalUser; private static int kRpcRpcClientOnActivated; public float sceneStartAmbientLevel { get; private set; } public HoldoutZoneController holdoutZoneController { get; private set; } public SceneExitController sceneExitController { get; private set; } private BaseTeleporterState currentState => mainStateMachine.state as BaseTeleporterState; public ActivationState activationState => currentState?.backwardsCompatibleActivationState ?? ActivationState.Idle; public bool locked { get { return _locked; } set { Network_locked = value; } } public bool isIdle => currentState is IdleState; public bool isIdleToCharging => currentState is IdleToChargingState; public bool isInFinalSequence => currentState is FinishedState; public bool isCharging => currentState is ChargingState; public bool isCharged => activationState >= ActivationState.Charged; public float chargeFraction => holdoutZoneController.charge; public int shrineBonusStacks { get; set; } private int chargePercent => holdoutZoneController.displayChargePercent; public static TeleporterInteraction instance { get; private set; } public bool shouldAttemptToSpawnShopPortal { get { return _shouldAttemptToSpawnShopPortal; } set { if (_shouldAttemptToSpawnShopPortal != value) { Network_shouldAttemptToSpawnShopPortal = value; if (_shouldAttemptToSpawnShopPortal && NetworkServer.active) { Chat.SendBroadcastChat(new Chat.SimpleChatMessage { baseToken = "PORTAL_SHOP_WILL_OPEN" }); } } } } public bool shouldAttemptToSpawnGoldshoresPortal { get { return _shouldAttemptToSpawnGoldshoresPortal; } set { if (_shouldAttemptToSpawnGoldshoresPortal != value) { Network_shouldAttemptToSpawnGoldshoresPortal = value; if (_shouldAttemptToSpawnGoldshoresPortal && NetworkServer.active) { Chat.SendBroadcastChat(new Chat.SimpleChatMessage { baseToken = "PORTAL_GOLDSHORES_WILL_OPEN" }); } } } } public bool shouldAttemptToSpawnMSPortal { get { return _shouldAttemptToSpawnMSPortal; } set { if (_shouldAttemptToSpawnMSPortal != value) { Network_shouldAttemptToSpawnMSPortal = value; if (_shouldAttemptToSpawnMSPortal && NetworkServer.active) { Chat.SendBroadcastChat(new Chat.SimpleChatMessage { baseToken = "PORTAL_MS_WILL_OPEN" }); } } } } public bool Network_locked { get { return _locked; } [param: In] set { SetSyncVar(value, ref _locked, 1u); } } public bool NetworkisDiscovered { get { return isDiscovered; } [param: In] set { if (NetworkServer.localClientActive && !base.syncVarHookGuard) { base.syncVarHookGuard = true; OnSyncTeleporterDiscovered(value); base.syncVarHookGuard = false; } SetSyncVar(value, ref isDiscovered, 2u); } } public bool NetworkisActivated { get { return isActivated; } [param: In] set { SetSyncVar(value, ref isActivated, 4u); } } public bool Network_shouldAttemptToSpawnShopPortal { get { return _shouldAttemptToSpawnShopPortal; } [param: In] set { if (NetworkServer.localClientActive && !base.syncVarHookGuard) { base.syncVarHookGuard = true; OnSyncShouldAttemptToSpawnShopPortal(value); base.syncVarHookGuard = false; } SetSyncVar(value, ref _shouldAttemptToSpawnShopPortal, 8u); } } public bool Network_shouldAttemptToSpawnGoldshoresPortal { get { return _shouldAttemptToSpawnGoldshoresPortal; } [param: In] set { if (NetworkServer.localClientActive && !base.syncVarHookGuard) { base.syncVarHookGuard = true; OnSyncShouldAttemptToSpawnGoldshoresPortal(value); base.syncVarHookGuard = false; } SetSyncVar(value, ref _shouldAttemptToSpawnGoldshoresPortal, 16u); } } public bool Network_shouldAttemptToSpawnMSPortal { get { return _shouldAttemptToSpawnMSPortal; } [param: In] set { if (NetworkServer.localClientActive && !base.syncVarHookGuard) { base.syncVarHookGuard = true; OnSyncShouldAttemptToSpawnMSPortal(value); base.syncVarHookGuard = false; } SetSyncVar(value, ref _shouldAttemptToSpawnMSPortal, 32u); } } public bool NetworkshowExtraBossesIndicator { get { return showExtraBossesIndicator; } [param: In] set { SetSyncVar(value, ref showExtraBossesIndicator, 64u); } } public static event Action onTeleporterBeginChargingGlobal; public static event Action onTeleporterChargedGlobal; public static event Action onTeleporterFinishGlobal; private void OnSyncShouldAttemptToSpawnShopPortal(bool newValue) { Network_shouldAttemptToSpawnShopPortal = newValue; if ((bool)modelChildLocator) { modelChildLocator.FindChild("ShopPortalIndicator").gameObject.SetActive(newValue); } } private void OnSyncShouldAttemptToSpawnGoldshoresPortal(bool newValue) { Network_shouldAttemptToSpawnGoldshoresPortal = newValue; if ((bool)modelChildLocator) { modelChildLocator.FindChild("GoldshoresPortalIndicator").gameObject.SetActive(newValue); } } private void OnSyncShouldAttemptToSpawnMSPortal(bool newValue) { Network_shouldAttemptToSpawnMSPortal = newValue; if ((bool)modelChildLocator) { modelChildLocator.FindChild("MSPortalIndicator").gameObject.SetActive(newValue); } } private void OnSyncTeleporterDiscovered(bool newValue) { NetworkisDiscovered = newValue; ChargeIndicatorController component = teleporterPositionIndicator.GetComponent(); if ((object)component != null) { component.isDiscovered = newValue; if (newValue) { component.TriggerPingAnimation(); } } } private void Awake() { modelChildLocator = GetComponent().modelTransform.GetComponent(); holdoutZoneController = GetComponent(); sceneExitController = GetComponent(); bossShrineIndicator = modelChildLocator.FindChild("BossShrineSymbol").gameObject; bossGroup = GetComponent(); if (NetworkServer.active && (bool)bossDirector) { bossDirector.onSpawnedServer.AddListener(OnBossDirectorSpawnedMonsterServer); } teleporterPositionIndicator = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load("Prefabs/PositionIndicators/TeleporterChargingPositionIndicator"), base.transform.position, Quaternion.identity).GetComponent(); teleporterPositionIndicator.targetTransform = base.transform; teleporterChargeIndicatorController = teleporterPositionIndicator.GetComponent(); teleporterChargeIndicatorController.holdoutZoneController = holdoutZoneController; teleporterPositionIndicator.gameObject.SetActive(value: false); Particle_SetMinSize component = modelChildLocator.FindChild("PassiveParticleSphere").GetComponent(); if ((object)component != null) { cachedParticleMinSizeScript = component; } else { Debug.LogWarning("TeleporterInteraction could not get PassiveParticleSphere's Particle_SetMinSize. Make sure it's set in the Child Locator"); } cachedLocalUser = ((MPEventSystem)EventSystem.current)?.localUser; } private void OnDestroy() { if ((bool)teleporterPositionIndicator) { UnityEngine.Object.Destroy(teleporterPositionIndicator.gameObject); teleporterPositionIndicator = null; teleporterChargeIndicatorController = null; } } private void OnEnable() { instance = SingletonHelper.Assign(instance, this); InstanceTracker.Add(this); sceneStartAmbientLevel = Run.instance.ambientLevel; } private void OnDisable() { InstanceTracker.Remove(this); instance = SingletonHelper.Unassign(instance, this); } private void Start() { if (NetworkServer.active) { rng = new Xoroshiro128Plus(Run.instance.stageRng.nextUlong); Run.instance.PickNextStageSceneFromCurrentSceneDestinations(); float nextNormalizedFloat = rng.nextNormalizedFloat; float num = baseShopSpawnChance / (float)(Run.instance.shopPortalCount + 1); shouldAttemptToSpawnShopPortal = nextNormalizedFloat < num; int stageClearCount = Run.instance.stageClearCount; if ((stageClearCount + 1) % Run.stagesPerLoop == 3 && stageClearCount > Run.stagesPerLoop && !Run.instance.GetEventFlag("NoMysterySpace")) { shouldAttemptToSpawnMSPortal = true; } } if (base.isClient) { OnSyncTeleporterDiscovered(isDiscovered); teleporterPositionIndicator.GetComponent().isActivated = isActivated; teleporterPositionIndicator.GetComponent().isCharged = isCharged; } } public void FixedUpdate() { bossShrineIndicator.SetActive(showExtraBossesIndicator && !isCharged); teleporterPositionIndicator.gameObject.SetActive(!isIdle || (isDiscovered && cachedLocalUser.userProfile.useTeleporterDiscoveryIndicator) || currentPings.Count > 0); if (base.hasAuthority && !isDiscovered && HoldoutZoneController.CountPlayersInRadius(holdoutZoneController, base.transform.position, discoveryRadius * discoveryRadius, TeamIndex.Player) > 0) { NetworkisDiscovered = true; teleporterPositionIndicator.GetComponent().isDiscovered = true; teleporterPositionIndicator.GetComponent().TriggerPingAnimation(); } if (cachedLocalUser != null && cachedLocalUser.userProfile.useTeleporterParticleScaling) { shouldScaleParticles = true; particleScaleUpdateTimer -= Time.fixedDeltaTime; if (particleScaleUpdateTimer <= 0f) { particleScaleUpdateTimer = 0.5f; cachedParticleMinSizeScript.SetEnabled(isEnabled: true); } } else if (shouldScaleParticles) { shouldScaleParticles = false; cachedParticleMinSizeScript.SetEnabled(isEnabled: false); } } public string GetContextString(Interactor activator) { return currentState?.GetContextString(activator); } public Interactability GetInteractability(Interactor activator) { if (locked) { return Interactability.Disabled; } return currentState?.GetInteractability(activator) ?? Interactability.Disabled; } public void OnInteractionBegin(Interactor activator) { CallRpcClientOnActivated(activator.gameObject); currentState?.OnInteractionBegin(activator); } public bool ShouldShowOnScanner() { return true; } public bool ShouldProximityHighlight() { return true; } public bool ShouldIgnoreSpherecastForInteractibility(Interactor activator) { return false; } [ConCommand(commandName = "activate_teleporter", flags = ConVarFlags.None, helpText = "Activates teleporter")] private static void ActivateTeleporter(ConCommandArgs args) { Interactor component = TeamComponent.GetTeamMembers(TeamIndex.Player)[0].GetComponent(); if ((bool)component) { instance.CallRpcClientOnActivated(component.gameObject); instance.currentState?.OnInteractionBegin(component); CharacterBody component2 = component.GetComponent(); if ((bool)component2) { TeleportHelper.TeleportBody(component2, instance.transform.position); } } } [ClientRpc] private void RpcClientOnActivated(GameObject activatorObject) { Util.PlaySound("Play_env_teleporter_active_button", base.gameObject); } private void UpdateMonstersClear() { monstersCleared = !bossGroup.enabled; } [Server] public void AddShrineStack() { if (!NetworkServer.active) { Debug.LogWarning("[Server] function 'System.Void RoR2.TeleporterInteraction::AddShrineStack()' called on client"); } else if (activationState <= ActivationState.IdleToCharging) { BossGroup obj = bossGroup; int bonusRewardCount = obj.bonusRewardCount + 1; obj.bonusRewardCount = bonusRewardCount; shrineBonusStacks++; NetworkshowExtraBossesIndicator = true; } } [Obsolete] public bool IsInChargingRange(CharacterBody body) { return holdoutZoneController.IsBodyInChargingRadius(body); } private void OnBossDirectorSpawnedMonsterServer(GameObject masterObject) { BaseAI ai; if ((bool)chargeActivatorServer) { ai = masterObject.GetComponent(); if ((bool)ai) { ai.onBodyDiscovered += AiOnBodyDiscovered; } } void AiOnBodyDiscovered(CharacterBody newBody) { ai.currentEnemy.gameObject = chargeActivatorServer; ai.onBodyDiscovered -= AiOnBodyDiscovered; } } [Server] private void AttemptToSpawnAllEligiblePortals() { if (!NetworkServer.active) { Debug.LogWarning("[Server] function 'System.Void RoR2.TeleporterInteraction::AttemptToSpawnAllEligiblePortals()' called on client"); return; } if (shouldAttemptToSpawnShopPortal) { AttemptToSpawnShopPortal(); } if (shouldAttemptToSpawnGoldshoresPortal) { AttemptToSpawnGoldshoresPortal(); } if (shouldAttemptToSpawnMSPortal) { AttemptToSpawnMSPortal(); } PortalSpawner[] array = portalSpawners; for (int i = 0; i < array.Length; i++) { array[i].AttemptSpawnPortalServer(); } } private bool AttemptSpawnPortal(SpawnCard portalSpawnCard, float minDistance, float maxDistance, string successChatToken) { GameObject obj = DirectorCore.instance.TrySpawnObject(new DirectorSpawnRequest(portalSpawnCard, new DirectorPlacementRule { minDistance = minDistance, maxDistance = maxDistance, placementMode = DirectorPlacementRule.PlacementMode.Approximate, position = base.transform.position, spawnOnTarget = base.transform }, rng)); if ((bool)obj) { Chat.SendBroadcastChat(new Chat.SimpleChatMessage { baseToken = successChatToken }); } return obj; } [Server] private void AttemptToSpawnShopPortal() { if (!NetworkServer.active) { Debug.LogWarning("[Server] function 'System.Void RoR2.TeleporterInteraction::AttemptToSpawnShopPortal()' called on client"); } else if (AttemptSpawnPortal(shopPortalSpawnCard, 0f, 30f, "PORTAL_SHOP_OPEN")) { Run.instance.shopPortalCount++; } } [Server] private void AttemptToSpawnGoldshoresPortal() { if (!NetworkServer.active) { Debug.LogWarning("[Server] function 'System.Void RoR2.TeleporterInteraction::AttemptToSpawnGoldshoresPortal()' called on client"); } else { AttemptSpawnPortal(goldshoresPortalSpawnCard, 10f, 40f, "PORTAL_GOLDSHORES_OPEN"); } } [Server] private void AttemptToSpawnMSPortal() { if (!NetworkServer.active) { Debug.LogWarning("[Server] function 'System.Void RoR2.TeleporterInteraction::AttemptToSpawnMSPortal()' called on client"); } else { AttemptSpawnPortal(msPortalSpawnCard, 10f, 40f, "PORTAL_MS_OPEN"); } } public void PingTeleporter(string pingOwnerName, PingIndicator pingObject) { if ((bool)pingObject) { if (base.hasAuthority) { NetworkisDiscovered = true; } currentPings.Add(pingObject); teleporterPositionIndicator.GetComponent()?.TriggerPing(pingOwnerName); } } public void CancelTeleporterPing(PingIndicator cancelledPingObject) { if ((bool)cancelledPingObject && currentPings.Contains(cancelledPingObject)) { currentPings.Remove(cancelledPingObject); } ChargeIndicatorController component = teleporterPositionIndicator.GetComponent(); if (!component) { return; } int num = currentPings.Count - 1; while (num >= 0) { if (!currentPings[num]) { currentPings.RemoveAt(num); num--; continue; } component.TriggerPing(currentPings[num].GetOwnerName(), triggerAnimation: false); return; } component.isPinged = false; } private void UNetVersion() { } protected static void InvokeRpcRpcClientOnActivated(NetworkBehaviour obj, NetworkReader reader) { if (!NetworkClient.active) { Debug.LogError("RPC RpcClientOnActivated called on server."); } else { ((TeleporterInteraction)obj).RpcClientOnActivated(reader.ReadGameObject()); } } public void CallRpcClientOnActivated(GameObject activatorObject) { if (!NetworkServer.active) { Debug.LogError("RPC Function RpcClientOnActivated called on client."); return; } NetworkWriter networkWriter = new NetworkWriter(); networkWriter.Write((short)0); networkWriter.Write((short)2); networkWriter.WritePackedUInt32((uint)kRpcRpcClientOnActivated); networkWriter.Write(GetComponent().netId); networkWriter.Write(activatorObject); SendRPCInternal(networkWriter, 0, "RpcClientOnActivated"); } static TeleporterInteraction() { kRpcRpcClientOnActivated = 1157394167; NetworkBehaviour.RegisterRpcDelegate(typeof(TeleporterInteraction), kRpcRpcClientOnActivated, InvokeRpcRpcClientOnActivated); NetworkCRC.RegisterBehaviour("TeleporterInteraction", 0); } public override bool OnSerialize(NetworkWriter writer, bool forceAll) { if (forceAll) { writer.Write(_locked); writer.Write(isDiscovered); writer.Write(isActivated); writer.Write(_shouldAttemptToSpawnShopPortal); writer.Write(_shouldAttemptToSpawnGoldshoresPortal); writer.Write(_shouldAttemptToSpawnMSPortal); writer.Write(showExtraBossesIndicator); return true; } bool flag = false; if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0) { if (!flag) { writer.WritePackedUInt32(base.syncVarDirtyBits); flag = true; } writer.Write(_locked); } if ((base.syncVarDirtyBits & 2u) != 0) { if (!flag) { writer.WritePackedUInt32(base.syncVarDirtyBits); flag = true; } writer.Write(isDiscovered); } if ((base.syncVarDirtyBits & 4u) != 0) { if (!flag) { writer.WritePackedUInt32(base.syncVarDirtyBits); flag = true; } writer.Write(isActivated); } if ((base.syncVarDirtyBits & 8u) != 0) { if (!flag) { writer.WritePackedUInt32(base.syncVarDirtyBits); flag = true; } writer.Write(_shouldAttemptToSpawnShopPortal); } if ((base.syncVarDirtyBits & 0x10u) != 0) { if (!flag) { writer.WritePackedUInt32(base.syncVarDirtyBits); flag = true; } writer.Write(_shouldAttemptToSpawnGoldshoresPortal); } if ((base.syncVarDirtyBits & 0x20u) != 0) { if (!flag) { writer.WritePackedUInt32(base.syncVarDirtyBits); flag = true; } writer.Write(_shouldAttemptToSpawnMSPortal); } if ((base.syncVarDirtyBits & 0x40u) != 0) { if (!flag) { writer.WritePackedUInt32(base.syncVarDirtyBits); flag = true; } writer.Write(showExtraBossesIndicator); } if (!flag) { writer.WritePackedUInt32(base.syncVarDirtyBits); } return flag; } public override void OnDeserialize(NetworkReader reader, bool initialState) { if (initialState) { _locked = reader.ReadBoolean(); isDiscovered = reader.ReadBoolean(); isActivated = reader.ReadBoolean(); _shouldAttemptToSpawnShopPortal = reader.ReadBoolean(); _shouldAttemptToSpawnGoldshoresPortal = reader.ReadBoolean(); _shouldAttemptToSpawnMSPortal = reader.ReadBoolean(); showExtraBossesIndicator = reader.ReadBoolean(); return; } int num = (int)reader.ReadPackedUInt32(); if (((uint)num & (true ? 1u : 0u)) != 0) { _locked = reader.ReadBoolean(); } if (((uint)num & 2u) != 0) { OnSyncTeleporterDiscovered(reader.ReadBoolean()); } if (((uint)num & 4u) != 0) { isActivated = reader.ReadBoolean(); } if (((uint)num & 8u) != 0) { OnSyncShouldAttemptToSpawnShopPortal(reader.ReadBoolean()); } if (((uint)num & 0x10u) != 0) { OnSyncShouldAttemptToSpawnGoldshoresPortal(reader.ReadBoolean()); } if (((uint)num & 0x20u) != 0) { OnSyncShouldAttemptToSpawnMSPortal(reader.ReadBoolean()); } if (((uint)num & 0x40u) != 0) { showExtraBossesIndicator = reader.ReadBoolean(); } } public override void PreStartClient() { } }