r2mods/ilspy_dump/ror2_csproj/RoR2/Run.cs

2228 lines
57 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Xml.Linq;
using HG;
using JetBrains.Annotations;
using RoR2.ConVar;
using RoR2.ExpansionManagement;
using RoR2.Navigation;
using RoR2.Networking;
using RoR2.Stats;
using Unity;
using UnityEngine;
using UnityEngine.Networking;
namespace RoR2;
[DisallowMultipleComponent]
[RequireComponent(typeof(NetworkRuleBook))]
[RequireComponent(typeof(RunArtifactManager))]
public class Run : NetworkBehaviour
{
[Serializable]
public struct RunStopwatch : IEquatable<RunStopwatch>
{
public float offsetFromFixedTime;
public bool isPaused;
public bool Equals(RunStopwatch other)
{
if (offsetFromFixedTime.Equals(other.offsetFromFixedTime))
{
return isPaused == other.isPaused;
}
return false;
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (obj is RunStopwatch other)
{
return Equals(other);
}
return false;
}
public override int GetHashCode()
{
return (offsetFromFixedTime.GetHashCode() * 397) ^ isPaused.GetHashCode();
}
}
[Serializable]
public struct TimeStamp : IEquatable<TimeStamp>, IComparable<TimeStamp>
{
public readonly float t;
private static float tNow;
public static readonly TimeStamp zero;
public static readonly TimeStamp positiveInfinity;
public static readonly TimeStamp negativeInfinity;
public float timeUntil => t - tNow;
public float timeSince => tNow - t;
public float timeUntilClamped => Mathf.Max(timeUntil, 0f);
public float timeSinceClamped => Mathf.Max(timeSince, 0f);
public bool hasPassed => t <= tNow;
public bool isInfinity => float.IsInfinity(t);
public bool isPositiveInfinity => float.IsPositiveInfinity(t);
public bool isNegativeInfinity => float.IsNegativeInfinity(t);
public static TimeStamp now => new TimeStamp(tNow);
public override int GetHashCode()
{
return t.GetHashCode();
}
public static void Update()
{
tNow = instance.time;
}
private TimeStamp(float t)
{
this.t = t;
}
public bool Equals(TimeStamp other)
{
return t.Equals(other.t);
}
public override bool Equals(object obj)
{
if (obj is TimeStamp)
{
return Equals((TimeStamp)obj);
}
return false;
}
public int CompareTo(TimeStamp other)
{
return t.CompareTo(other.t);
}
public static TimeStamp operator +(TimeStamp a, float b)
{
return new TimeStamp(a.t + b);
}
public static TimeStamp operator -(TimeStamp a, float b)
{
return new TimeStamp(a.t - b);
}
public static float operator -(TimeStamp a, TimeStamp b)
{
return a.t - b.t;
}
public static bool operator <(TimeStamp a, TimeStamp b)
{
return a.t < b.t;
}
public static bool operator >(TimeStamp a, TimeStamp b)
{
return a.t > b.t;
}
public static bool operator <=(TimeStamp a, TimeStamp b)
{
return a.t <= b.t;
}
public static bool operator >=(TimeStamp a, TimeStamp b)
{
return a.t >= b.t;
}
public static bool operator ==(TimeStamp a, TimeStamp b)
{
return a.Equals(b);
}
public static bool operator !=(TimeStamp a, TimeStamp b)
{
return !a.Equals(b);
}
public static float operator -(TimeStamp a, FixedTimeStamp b)
{
return a.t - b.t;
}
public static TimeStamp Deserialize(NetworkReader reader)
{
return new TimeStamp(reader.ReadSingle());
}
public static void Serialize(NetworkWriter writer, TimeStamp timeStamp)
{
writer.Write(timeStamp.t);
}
public static void ToXml(XElement element, TimeStamp src)
{
element.Value = TextSerialization.ToStringInvariant(src.t);
}
public static bool FromXml(XElement element, ref TimeStamp dest)
{
if (TextSerialization.TryParseInvariant(element.Value, out float result))
{
dest = new TimeStamp(result);
return true;
}
return false;
}
static TimeStamp()
{
zero = new TimeStamp(0f);
positiveInfinity = new TimeStamp(float.PositiveInfinity);
negativeInfinity = new TimeStamp(float.NegativeInfinity);
HGXml.Register<TimeStamp>(ToXml, FromXml);
}
}
[Serializable]
public struct FixedTimeStamp : IEquatable<FixedTimeStamp>, IComparable<FixedTimeStamp>
{
public readonly float t;
private static float tNow;
public static readonly FixedTimeStamp zero;
public static readonly FixedTimeStamp positiveInfinity;
public static readonly FixedTimeStamp negativeInfinity;
public float timeUntil => t - tNow;
public float timeSince => tNow - t;
public float timeUntilClamped => Mathf.Max(timeUntil, 0f);
public float timeSinceClamped => Mathf.Max(timeSince, 0f);
public bool hasPassed => t <= tNow;
public bool isInfinity => float.IsInfinity(t);
public bool isPositiveInfinity => float.IsPositiveInfinity(t);
public bool isNegativeInfinity => float.IsNegativeInfinity(t);
public static FixedTimeStamp now => new FixedTimeStamp(tNow);
public override int GetHashCode()
{
return t.GetHashCode();
}
public static void Update()
{
tNow = instance.fixedTime;
}
private FixedTimeStamp(float t)
{
this.t = t;
}
public bool Equals(FixedTimeStamp other)
{
return t.Equals(other.t);
}
public override bool Equals(object obj)
{
if (obj is FixedTimeStamp)
{
return Equals((FixedTimeStamp)obj);
}
return false;
}
public int CompareTo(FixedTimeStamp other)
{
return t.CompareTo(other.t);
}
public static FixedTimeStamp operator +(FixedTimeStamp a, float b)
{
return new FixedTimeStamp(a.t + b);
}
public static FixedTimeStamp operator -(FixedTimeStamp a, float b)
{
return new FixedTimeStamp(a.t - b);
}
public static float operator -(FixedTimeStamp a, FixedTimeStamp b)
{
return a.t - b.t;
}
public static bool operator <(FixedTimeStamp a, FixedTimeStamp b)
{
return a.t < b.t;
}
public static bool operator >(FixedTimeStamp a, FixedTimeStamp b)
{
return a.t > b.t;
}
public static bool operator <=(FixedTimeStamp a, FixedTimeStamp b)
{
return a.t <= b.t;
}
public static bool operator >=(FixedTimeStamp a, FixedTimeStamp b)
{
return a.t >= b.t;
}
public static bool operator ==(FixedTimeStamp a, FixedTimeStamp b)
{
return a.Equals(b);
}
public static bool operator !=(FixedTimeStamp a, FixedTimeStamp b)
{
return !a.Equals(b);
}
public static FixedTimeStamp Deserialize(NetworkReader reader)
{
return new FixedTimeStamp(reader.ReadSingle());
}
public static void Serialize(NetworkWriter writer, FixedTimeStamp timeStamp)
{
writer.Write(timeStamp.t);
}
public static void ToXml(XElement element, FixedTimeStamp src)
{
element.Value = TextSerialization.ToStringInvariant(src.t);
}
public static bool FromXml(XElement element, ref FixedTimeStamp dest)
{
if (TextSerialization.TryParseInvariant(element.Value, out float result))
{
dest = new FixedTimeStamp(result);
return true;
}
return false;
}
static FixedTimeStamp()
{
zero = new FixedTimeStamp(0f);
positiveInfinity = new FixedTimeStamp(float.PositiveInfinity);
negativeInfinity = new FixedTimeStamp(float.NegativeInfinity);
HGXml.Register<FixedTimeStamp>(ToXml, FromXml);
}
}
private NetworkRuleBook networkRuleBookComponent;
[Tooltip("This is assigned to the prefab automatically by GameModeCatalog at runtime. Do not set this value manually.")]
[HideInInspector]
public GameModeIndex gameModeIndex = GameModeIndex.Invalid;
public string nameToken = "";
[Tooltip("Whether or not the user can select this game mode for play in the game mode selector UI.")]
public bool userPickable = true;
[Tooltip("Dictates items given when rebirth is active when the user doesn't have a stored item.")]
public PickupDropTable rebirthDropTable;
public static int stagesPerLoop = 5;
public static float baseGravity = -30f;
[SyncVar]
private NetworkGuid _uniqueId;
[SyncVar]
private NetworkDateTime startTimeUtc;
[ShowFieldObsolete]
[Obsolete("Use startingSceneGroup instead.")]
[Tooltip("The pool of scenes to select the first scene of the run from.")]
public SceneDef[] startingScenes = Array.Empty<SceneDef>();
[Tooltip("The pool of scenes to select the first scene of the run from.")]
public SceneCollection startingSceneGroup;
public ItemMask availableItems;
public ItemMask expansionLockedItems;
public EquipmentMask availableEquipment;
public EquipmentMask expansionLockedEquipment;
public bool isRunWeekly;
[SyncVar]
public float fixedTime;
public float time;
[HideInInspector]
public bool isRunning;
[SyncVar]
private RunStopwatch runStopwatch;
[SyncVar]
public int stageClearCount;
public SceneDef nextStageScene;
public SceneDef[] blacklistedScenesForFirstScene = Array.Empty<SceneDef>();
public GameObject gameOverPrefab;
public GameObject lobbyBackgroundPrefab;
public GameObject uiPrefab;
private ulong _seed;
public Xoroshiro128Plus runRNG;
public Xoroshiro128Plus nextStageRng;
public Xoroshiro128Plus stageRngGenerator;
public Xoroshiro128Plus stageRng;
public Xoroshiro128Plus bossRewardRng;
public Xoroshiro128Plus treasureRng;
public Xoroshiro128Plus spawnRng;
public Xoroshiro128Plus randomSurvivorOnRespawnRng;
public float difficultyCoefficient = 1f;
public float compensatedDifficultyCoefficient = 1f;
public float oneOverCompensatedDifficultyCoefficientSquared = 1f;
[SyncVar]
private int selectedDifficultyInternal = 1;
public int shopPortalCount;
private static int ambientLevelCap = 99;
private bool lowerPricedChestsTimerOn;
private float lowerPricedChestsTimer;
private float lowerPricedChestsDuration = 10f;
private static readonly StringConVar cvRunSceneOverride = new StringConVar("run_scene_override", ConVarFlags.Cheat, "", "Overrides the first scene to enter in a run.");
private readonly HashSet<UnlockableDef> unlockablesUnlockedByAnyUser = new HashSet<UnlockableDef>();
private readonly HashSet<UnlockableDef> unlockablesUnlockedByAllUsers = new HashSet<UnlockableDef>();
private readonly HashSet<UnlockableDef> unlockablesAlreadyFullyObtained = new HashSet<UnlockableDef>();
private bool shutdown;
private Dictionary<NetworkUserId, CharacterMaster> userMasters = new Dictionary<NetworkUserId, CharacterMaster>();
private bool allowNewParticipants;
public readonly List<PickupIndex> availableTier1DropList = new List<PickupIndex>();
public readonly List<PickupIndex> availableTier2DropList = new List<PickupIndex>();
public readonly List<PickupIndex> availableTier3DropList = new List<PickupIndex>();
public readonly List<PickupIndex> availableEquipmentDropList = new List<PickupIndex>();
public readonly List<PickupIndex> availableLunarEquipmentDropList = new List<PickupIndex>();
public readonly List<PickupIndex> availableLunarItemDropList = new List<PickupIndex>();
public readonly List<PickupIndex> availableLunarCombinedDropList = new List<PickupIndex>();
public readonly List<PickupIndex> availableBossDropList = new List<PickupIndex>();
public readonly List<PickupIndex> availableVoidTier1DropList = new List<PickupIndex>();
public readonly List<PickupIndex> availableVoidTier2DropList = new List<PickupIndex>();
public readonly List<PickupIndex> availableVoidTier3DropList = new List<PickupIndex>();
public readonly List<PickupIndex> availableVoidBossDropList = new List<PickupIndex>();
public WeightedSelection<List<PickupIndex>> smallChestDropTierSelector = new WeightedSelection<List<PickupIndex>>();
public WeightedSelection<List<PickupIndex>> mediumChestDropTierSelector = new WeightedSelection<List<PickupIndex>>();
public WeightedSelection<List<PickupIndex>> largeChestDropTierSelector = new WeightedSelection<List<PickupIndex>>();
private readonly HashSet<string> eventFlags = new HashSet<string>();
public static Run instance { get; private set; }
public RuleBook ruleBook => networkRuleBookComponent.ruleBook;
public bool isRunStopwatchPaused => runStopwatch.isPaused;
public virtual int loopClearCount => stageClearCount / stagesPerLoop;
public virtual bool spawnWithPod => instance.stageClearCount == 0;
public virtual bool autoGenerateSpawnPoints => true;
public virtual bool canFamilyEventTrigger => true;
public IList<GameObject> uiInstances { get; protected set; } = new List<GameObject>();
public ulong seed
{
get
{
return _seed;
}
set
{
_seed = value;
OnSeedSet();
}
}
public DifficultyIndex selectedDifficulty
{
get
{
return (DifficultyIndex)selectedDifficultyInternal;
}
set
{
NetworkselectedDifficultyInternal = (int)value;
}
}
public int livingPlayerCount => PlayerCharacterMasterController.GetPlayersWithBodiesCount();
public int participatingPlayerCount => PlayerCharacterMasterController.instances.Count;
public float ambientLevel { get; protected set; }
public int ambientLevelFloor { get; protected set; }
public float teamlessDamageCoefficient => difficultyCoefficient;
public bool isGameOverServer { get; private set; }
public NetworkGuid Network_uniqueId
{
get
{
return _uniqueId;
}
[param: In]
set
{
SetSyncVar(value, ref _uniqueId, 1u);
}
}
public NetworkDateTime NetworkstartTimeUtc
{
get
{
return startTimeUtc;
}
[param: In]
set
{
SetSyncVar(value, ref startTimeUtc, 2u);
}
}
public float NetworkfixedTime
{
get
{
return fixedTime;
}
[param: In]
set
{
SetSyncVar(value, ref fixedTime, 4u);
}
}
public RunStopwatch NetworkrunStopwatch
{
get
{
return runStopwatch;
}
[param: In]
set
{
SetSyncVar(value, ref runStopwatch, 8u);
}
}
public int NetworkstageClearCount
{
get
{
return stageClearCount;
}
[param: In]
set
{
SetSyncVar(value, ref stageClearCount, 16u);
}
}
public int NetworkselectedDifficultyInternal
{
get
{
return selectedDifficultyInternal;
}
[param: In]
set
{
SetSyncVar(value, ref selectedDifficultyInternal, 32u);
}
}
public static event Action<Run, RuleBook> onServerRunSetRuleBookGlobal;
public static event Action<Run, RuleBook> onRunSetRuleBookGlobal;
public static event Action<Run> onRunAmbientLevelUp;
public static event Action<Run, PlayerCharacterMasterController> onPlayerFirstCreatedServer;
public static event Action<Run, GameEndingDef> onServerGameOver;
public static event Action<Run, RunReport> onClientGameOverGlobal;
public static event Action<Run> onRunStartGlobal;
public static event Action<Run> onRunDestroyGlobal;
public static event Action<Run> onAvailablePickupsModified;
protected virtual void OnEnable()
{
instance = SingletonHelper.Assign(instance, this);
}
protected virtual void OnDisable()
{
instance = SingletonHelper.Unassign(instance, this);
if (instance == null)
{
RewiredIntegrationManager.RefreshAfterRunFinish();
}
}
protected void Awake()
{
networkRuleBookComponent = GetComponent<NetworkRuleBook>();
networkRuleBookComponent.onRuleBookUpdated += OnRuleBookUpdated;
availableItems = ItemMask.Rent();
expansionLockedItems = ItemMask.Rent();
availableEquipment = EquipmentMask.Rent();
expansionLockedEquipment = EquipmentMask.Rent();
if (NetworkServer.active)
{
Network_uniqueId = (NetworkGuid)Guid.NewGuid();
NetworkstartTimeUtc = (NetworkDateTime)DateTime.UtcNow;
}
}
[Server]
public void SetRuleBook(RuleBook newRuleBook)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::SetRuleBook(RoR2.RuleBook)' called on client");
}
else
{
networkRuleBookComponent.SetRuleBook(newRuleBook);
}
}
private void OnRuleBookUpdated(NetworkRuleBook networkRuleBookComponent)
{
RuleBook ruleBook = networkRuleBookComponent.ruleBook;
selectedDifficulty = ruleBook.FindDifficulty();
ruleBook.GenerateItemMask(availableItems);
ruleBook.GenerateEquipmentMask(availableEquipment);
expansionLockedItems.Clear();
foreach (ItemDef allItemDef in ItemCatalog.allItemDefs)
{
if ((bool)allItemDef && (bool)allItemDef.requiredExpansion && !IsExpansionEnabled(allItemDef.requiredExpansion))
{
expansionLockedItems.Add(allItemDef.itemIndex);
}
}
expansionLockedEquipment.Clear();
foreach (EquipmentIndex item in EquipmentCatalog.allEquipment)
{
EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(item);
if ((bool)equipmentDef && (bool)equipmentDef.requiredExpansion && !IsExpansionEnabled(equipmentDef.requiredExpansion))
{
expansionLockedEquipment.Add(equipmentDef.equipmentIndex);
}
}
if (NetworkServer.active)
{
Run.onServerRunSetRuleBookGlobal?.Invoke(this, ruleBook);
}
Run.onRunSetRuleBookGlobal?.Invoke(this, ruleBook);
}
public Guid GetUniqueId()
{
return (Guid)_uniqueId;
}
public DateTime GetStartTimeUtc()
{
return (DateTime)startTimeUtc;
}
[Server]
private void SetRunStopwatchPaused(bool isPaused)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::SetRunStopwatchPaused(System.Boolean)' called on client");
}
else if (isPaused != runStopwatch.isPaused)
{
RunStopwatch networkrunStopwatch = runStopwatch;
networkrunStopwatch.isPaused = isPaused;
float num = GetRunStopwatch();
if (isPaused)
{
networkrunStopwatch.offsetFromFixedTime = num;
}
else
{
networkrunStopwatch.offsetFromFixedTime = num - fixedTime;
}
NetworkrunStopwatch = networkrunStopwatch;
}
}
public float GetRunStopwatch()
{
if (runStopwatch.isPaused)
{
return runStopwatch.offsetFromFixedTime;
}
return fixedTime + runStopwatch.offsetFromFixedTime;
}
[Server]
public void SetRunStopwatch(float t)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::SetRunStopwatch(System.Single)' called on client");
return;
}
RunStopwatch networkrunStopwatch = runStopwatch;
if (networkrunStopwatch.isPaused)
{
networkrunStopwatch.offsetFromFixedTime = t;
}
else
{
networkrunStopwatch.offsetFromFixedTime = t - fixedTime;
}
NetworkrunStopwatch = networkrunStopwatch;
}
public virtual GameObject InstantiateUi(Transform uiRoot)
{
GameObject gameObject = null;
if ((bool)uiRoot && (bool)uiPrefab)
{
gameObject = UnityEngine.Object.Instantiate(uiPrefab, uiRoot);
uiInstances.Add(gameObject);
}
return gameObject;
}
public void UnregisterUi(GameObject uiInstance)
{
uiInstances.Remove(uiInstance);
}
private void GenerateStageRNG()
{
stageRng = new Xoroshiro128Plus(stageRngGenerator.nextUlong);
bossRewardRng = new Xoroshiro128Plus(stageRng.nextUlong);
treasureRng = new Xoroshiro128Plus(stageRng.nextUlong);
spawnRng = new Xoroshiro128Plus(stageRng.nextUlong);
randomSurvivorOnRespawnRng = new Xoroshiro128Plus(stageRng.nextUlong);
}
protected void OnAmbientLevelUp()
{
Run.onRunAmbientLevelUp?.Invoke(this);
}
protected virtual void FixedUpdate()
{
NetworkfixedTime = fixedTime + Time.fixedDeltaTime;
FixedTimeStamp.Update();
if (NetworkServer.active)
{
SetRunStopwatchPaused(!ShouldUpdateRunStopwatch());
}
OnFixedUpdate();
}
public void RecalculateDifficultyCoefficent()
{
RecalculateDifficultyCoefficentInternal();
}
protected virtual void RecalculateDifficultyCoefficentInternal()
{
float num = GetRunStopwatch();
DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(selectedDifficulty);
float num2 = Mathf.Floor(num * (1f / 60f));
float num3 = (float)participatingPlayerCount * 0.3f;
float num4 = 0.7f + num3;
float num5 = 0.7f + num3;
float num6 = Mathf.Pow(participatingPlayerCount, 0.2f);
float num7 = 0.0506f * difficultyDef.scalingValue * num6;
float num8 = 0.0506f * difficultyDef.scalingValue * num6;
float num9 = Mathf.Pow(1.15f, stageClearCount);
compensatedDifficultyCoefficient = (num5 + num8 * num2) * num9;
difficultyCoefficient = (num4 + num7 * num2) * num9;
oneOverCompensatedDifficultyCoefficientSquared = 1f / (compensatedDifficultyCoefficient * compensatedDifficultyCoefficient);
float num10 = (num4 + num7 * (num * (1f / 60f))) * Mathf.Pow(1.15f, stageClearCount);
ambientLevel = Mathf.Min((num10 - num4) / 0.33f + 1f, ambientLevelCap);
int num11 = ambientLevelFloor;
ambientLevelFloor = Mathf.FloorToInt(ambientLevel);
if (num11 != ambientLevelFloor && num11 != 0 && ambientLevelFloor > num11)
{
OnAmbientLevelUp();
}
}
private void InitializeTimeStamps()
{
NetworkfixedTime = 0f;
time = 0f;
FixedTimeStamp.Update();
TimeStamp.Update();
}
protected virtual void OnFixedUpdate()
{
RecalculateDifficultyCoefficent();
}
public bool GetLowerPricedChestsTimer()
{
return lowerPricedChestsTimerOn;
}
protected void Update()
{
time = Mathf.Clamp(time + Time.deltaTime, fixedTime, fixedTime + Time.fixedDeltaTime);
TimeStamp.Update();
if ((double)GetRunStopwatch() - Math.Floor(GetRunStopwatch() * (1f / 60f)) * 60.0 <= 0.1 && !lowerPricedChestsTimerOn)
{
lowerPricedChestsTimerOn = true;
}
if (lowerPricedChestsTimerOn)
{
lowerPricedChestsTimer += Time.fixedDeltaTime;
}
if (lowerPricedChestsTimer >= lowerPricedChestsDuration)
{
lowerPricedChestsTimerOn = false;
lowerPricedChestsTimer = 0f;
}
}
protected virtual bool ShouldUpdateRunStopwatch()
{
SceneDef mostRecentSceneDef = SceneCatalog.mostRecentSceneDef;
if (mostRecentSceneDef.sceneType != SceneType.Stage && mostRecentSceneDef.sceneType != SceneType.TimedIntermission)
{
return false;
}
return livingPlayerCount > 0;
}
[Obsolete("Use the overload that accepts an UnlockableDef instead. This method may be removed from future releases.", false)]
[Server]
public bool CanUnlockableBeGrantedThisRun(string unlockableName)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Boolean RoR2.Run::CanUnlockableBeGrantedThisRun(System.String)' called on client");
return false;
}
return CanUnlockableBeGrantedThisRun(UnlockableCatalog.GetUnlockableDef(unlockableName));
}
[Server]
public virtual bool CanUnlockableBeGrantedThisRun(UnlockableDef unlockableDef)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Boolean RoR2.Run::CanUnlockableBeGrantedThisRun(RoR2.UnlockableDef)' called on client");
return false;
}
return !unlockablesAlreadyFullyObtained.Contains(unlockableDef);
}
[Obsolete("Use the overload that accepts an UnlockableDef instead. This method may be removed from future releases.", false)]
[Server]
public void GrantUnlockToAllParticipatingPlayers(string unlockableName)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::GrantUnlockToAllParticipatingPlayers(System.String)' called on client");
}
else
{
GrantUnlockToAllParticipatingPlayers(UnlockableCatalog.GetUnlockableDef(unlockableName));
}
}
[Server]
public void GrantUnlockToAllParticipatingPlayers(UnlockableDef unlockableDef)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::GrantUnlockToAllParticipatingPlayers(RoR2.UnlockableDef)' called on client");
}
else
{
if (!unlockableDef || unlockableDef.index == UnlockableIndex.None || unlockablesAlreadyFullyObtained.Contains(unlockableDef))
{
return;
}
unlockablesAlreadyFullyObtained.Add(unlockableDef);
foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
{
if (readOnlyInstances.isParticipating)
{
readOnlyInstances.ServerHandleUnlock(unlockableDef);
}
}
}
}
[Server]
[Obsolete("Use the overload that accepts an UnlockableDef instead. This method may be removed from future releases.", false)]
public void GrantUnlockToSinglePlayer(string unlockableName, CharacterBody body)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::GrantUnlockToSinglePlayer(System.String,RoR2.CharacterBody)' called on client");
}
else
{
GrantUnlockToSinglePlayer(UnlockableCatalog.GetUnlockableDef(unlockableName), body);
}
}
[Server]
public void GrantUnlockToSinglePlayer(UnlockableDef unlockableDef, CharacterBody body)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::GrantUnlockToSinglePlayer(RoR2.UnlockableDef,RoR2.CharacterBody)' called on client");
}
else if ((bool)unlockableDef && unlockableDef.index != UnlockableIndex.None && (bool)body)
{
NetworkUser networkUser = Util.LookUpBodyNetworkUser(body);
if ((bool)networkUser)
{
networkUser.ServerHandleUnlock(unlockableDef);
}
}
}
[Obsolete("Use the overload that accepts an UnlockableDef instead. This method may be removed from future releases.", false)]
[Server]
public bool IsUnlockableUnlocked(string unlockableName)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Boolean RoR2.Run::IsUnlockableUnlocked(System.String)' called on client");
return false;
}
return IsUnlockableUnlocked(UnlockableCatalog.GetUnlockableDef(unlockableName));
}
[Server]
public virtual bool IsUnlockableUnlocked(UnlockableDef unlockableDef)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Boolean RoR2.Run::IsUnlockableUnlocked(RoR2.UnlockableDef)' called on client");
return false;
}
return unlockablesUnlockedByAnyUser.Contains(unlockableDef);
}
[Server]
[Obsolete("Use the overload that accepts an UnlockableDef instead. This method may be removed from future releases.", false)]
public bool DoesEveryoneHaveThisUnlockableUnlocked(string unlockableName)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Boolean RoR2.Run::DoesEveryoneHaveThisUnlockableUnlocked(System.String)' called on client");
return false;
}
return DoesEveryoneHaveThisUnlockableUnlocked(UnlockableCatalog.GetUnlockableDef(unlockableName));
}
[Server]
public virtual bool DoesEveryoneHaveThisUnlockableUnlocked(UnlockableDef unlockableDef)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Boolean RoR2.Run::DoesEveryoneHaveThisUnlockableUnlocked(RoR2.UnlockableDef)' called on client");
return false;
}
return unlockablesUnlockedByAllUsers.Contains(unlockableDef);
}
[Server]
[Obsolete("Use the overload that accepts an UnlockableDef instead. This method may be removed from future releases.", false)]
public void ForceUnlockImmediate(string unlockableName)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::ForceUnlockImmediate(System.String)' called on client");
}
else
{
ForceUnlockImmediate(UnlockableCatalog.GetUnlockableDef(unlockableName));
}
}
[Server]
public void ForceUnlockImmediate(UnlockableDef unlockableDef)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::ForceUnlockImmediate(RoR2.UnlockableDef)' called on client");
}
else
{
unlockablesUnlockedByAnyUser.Add(unlockableDef);
}
}
public void PickNextStageSceneFromCurrentSceneDestinations()
{
WeightedSelection<SceneDef> weightedSelection = new WeightedSelection<SceneDef>();
SceneCatalog.mostRecentSceneDef.AddDestinationsToWeightedSelection(weightedSelection, CanPickStage);
PickNextStageScene(weightedSelection);
}
public bool CanPickStage(SceneDef sceneDef)
{
if ((bool)sceneDef.requiredExpansion)
{
return IsExpansionEnabled(sceneDef.requiredExpansion);
}
return true;
}
public void PickNextStageScene(WeightedSelection<SceneDef> choices)
{
if (choices.Count != 0)
{
if (ruleBook.stageOrder == StageOrder.Normal)
{
nextStageScene = choices.Evaluate(nextStageRng.nextNormalizedFloat);
return;
}
SceneDef[] array = SceneCatalog.allStageSceneDefs.Where(IsValidNextStage).ToArray();
nextStageScene = nextStageRng.NextElementUniform(array);
}
bool IsValidNextStage(SceneDef sceneDef)
{
if (nextStageScene != null && nextStageScene.baseSceneName == sceneDef.baseSceneName)
{
return false;
}
if (!sceneDef.hasAnyDestinations)
{
return false;
}
if (stageClearCount == 0 && blacklistedScenesForFirstScene.Contains(sceneDef))
{
return false;
}
return sceneDef.validForRandomSelection;
}
}
public virtual ulong GenerateSeedForNewRun()
{
return RoR2Application.rng.nextUlong;
}
[Server]
public void RefreshUnlockAvailability()
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::RefreshUnlockAvailability()' called on client");
}
else
{
BuildUnlockAvailability();
}
}
protected virtual void BuildUnlockAvailability()
{
unlockablesUnlockedByAnyUser.Clear();
unlockablesUnlockedByAllUsers.Clear();
unlockablesAlreadyFullyObtained.Clear();
int num = 0;
Dictionary<UnlockableDef, int> dictionary = new Dictionary<UnlockableDef, int>();
foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
{
if (!readOnlyInstances.isParticipating)
{
continue;
}
num++;
foreach (UnlockableDef unlockable in readOnlyInstances.unlockables)
{
unlockablesUnlockedByAnyUser.Add(unlockable);
if (!dictionary.ContainsKey(unlockable))
{
dictionary.Add(unlockable, 0);
}
UnlockableDef key = unlockable;
int value = dictionary[key] + 1;
dictionary[key] = value;
}
}
if (num <= 0)
{
return;
}
foreach (KeyValuePair<UnlockableDef, int> item in dictionary)
{
if (item.Value == num)
{
unlockablesUnlockedByAllUsers.Add(item.Key);
unlockablesAlreadyFullyObtained.Add(item.Key);
}
}
}
protected virtual void Start()
{
InitializeTimeStamps();
OnRuleBookUpdated(networkRuleBookComponent);
if (NetworkServer.active)
{
runRNG = new Xoroshiro128Plus(seed);
nextStageRng = new Xoroshiro128Plus(runRNG.nextUlong);
stageRngGenerator = new Xoroshiro128Plus(runRNG.nextUlong);
GenerateStageRNG();
}
allowNewParticipants = true;
UnityEngine.Object.DontDestroyOnLoad(base.gameObject);
ReadOnlyCollection<NetworkUser> readOnlyInstancesList = NetworkUser.readOnlyInstancesList;
for (int i = 0; i < readOnlyInstancesList.Count; i++)
{
OnUserAdded(readOnlyInstancesList[i]);
}
allowNewParticipants = false;
if (NetworkServer.active)
{
WeightedSelection<SceneDef> weightedSelection = new WeightedSelection<SceneDef>();
string @string = cvRunSceneOverride.GetString();
if (@string != "")
{
weightedSelection.AddChoice(SceneCatalog.GetSceneDefFromSceneName(@string), 1f);
}
else if ((bool)startingSceneGroup)
{
startingSceneGroup.AddToWeightedSelection(weightedSelection, CanPickStage);
}
else
{
for (int j = 0; j < startingScenes.Length; j++)
{
if (CanPickStage(startingScenes[j]))
{
weightedSelection.AddChoice(startingScenes[j], 1f);
}
}
}
PickNextStageScene(weightedSelection);
if (!nextStageScene)
{
Debug.LogError("Cannot set next scene. nextStageScene is null!");
}
NetworkManager.singleton.ServerChangeScene(nextStageScene.cachedName);
}
BuildUnlockAvailability();
BuildDropTable();
isRunning = true;
Run.onRunStartGlobal?.Invoke(this);
if (NetworkServer.active && RunArtifactManager.instance.IsArtifactEnabled(DLC2Content.Artifacts.Rebirth))
{
ServerGiveRebirthItems();
}
if (!NetworkClient.active || !RunArtifactManager.instance.IsArtifactEnabled(DLC2Content.Artifacts.Rebirth))
{
return;
}
foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList)
{
if (readOnlyInstances.isLocalPlayer)
{
readOnlyInstances.localUser.userProfile.RebirthItem = null;
break;
}
}
}
protected virtual void OnDestroy()
{
Run.onRunDestroyGlobal?.Invoke(this);
if ((bool)GameOverController.instance)
{
UnityEngine.Object.Destroy(GameOverController.instance.gameObject);
}
ReadOnlyCollection<CharacterBody> readOnlyInstancesList = CharacterBody.readOnlyInstancesList;
for (int num = readOnlyInstancesList.Count - 1; num >= 0; num--)
{
if ((bool)readOnlyInstancesList[num])
{
UnityEngine.Object.Destroy(readOnlyInstancesList[num].gameObject);
}
}
ReadOnlyCollection<CharacterMaster> readOnlyInstancesList2 = CharacterMaster.readOnlyInstancesList;
for (int num2 = readOnlyInstancesList2.Count - 1; num2 >= 0; num2--)
{
if ((bool)readOnlyInstancesList2[num2])
{
UnityEngine.Object.Destroy(readOnlyInstancesList2[num2].gameObject);
}
}
if ((bool)Stage.instance)
{
UnityEngine.Object.Destroy(Stage.instance.gameObject);
}
Chat.Clear();
if (!shutdown && PlatformSystems.networkManager.isNetworkActive)
{
HandlePostRunDestination();
}
ItemMask.Return(availableItems);
ItemMask.Return(expansionLockedItems);
EquipmentMask.Return(availableEquipment);
EquipmentMask.Return(expansionLockedEquipment);
PlatformSystems.saveSystem.SaveLoggedInUserProfiles();
}
[Server]
private void ServerGiveRebirthItems()
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::ServerGiveRebirthItems()' called on client");
}
else
{
if (!NetworkServer.active)
{
return;
}
ItemIndex itemIndex = ItemIndex.None;
foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
{
Inventory inventory = instance.master.inventory;
NetworkUser networkUser = instance.networkUser;
if (networkUser.rebirthItem != ItemIndex.None)
{
if ((bool)inventory)
{
itemIndex = networkUser.rebirthItem;
networkUser.NetworkrebirthItem = ItemIndex.None;
}
}
else if (rebirthDropTable != null)
{
Xoroshiro128Plus rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong);
itemIndex = PickupCatalog.GetPickupDef(rebirthDropTable.GenerateDrop(rng)).itemIndex;
}
if ((bool)inventory)
{
inventory.GiveItem(itemIndex);
}
}
}
}
protected virtual void HandlePostRunDestination()
{
if (NetworkServer.active)
{
NetworkManager.singleton.ServerChangeScene("lobby");
}
}
protected void OnApplicationQuit()
{
shutdown = true;
}
[Server]
public CharacterMaster GetUserMaster(NetworkUserId networkUserId)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'RoR2.CharacterMaster RoR2.Run::GetUserMaster(RoR2.NetworkUserId)' called on client");
return null;
}
userMasters.TryGetValue(networkUserId, out var value);
return value;
}
[Server]
public void OnServerSceneChanged(string sceneName)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::OnServerSceneChanged(System.String)' called on client");
return;
}
BeginStage();
isGameOverServer = false;
}
[Server]
private void BeginStage()
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::BeginStage()' called on client");
}
else
{
NetworkServer.Spawn(UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load<GameObject>("Prefabs/Stage")));
}
}
[Server]
private void EndStage()
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::EndStage()' called on client");
}
else if ((bool)Stage.instance)
{
UnityEngine.Object.Destroy(Stage.instance);
}
}
public void OnUserAdded(NetworkUser user)
{
if (NetworkServer.active)
{
SetupUserCharacterMaster(user);
}
}
public void OnUserRemoved(NetworkUser user)
{
}
public virtual bool ShouldAllowNewParticipant(NetworkUser user)
{
if (!allowNewParticipants)
{
return (bool)ruleBook.GetRuleChoice(RuleCatalog.FindRuleDef("Misc.AllowDropIn"))?.extraData;
}
return true;
}
[Server]
private void SetupUserCharacterMaster(NetworkUser user)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::SetupUserCharacterMaster(RoR2.NetworkUser)' called on client");
}
else if (!user)
{
Debug.LogError("SetupUserCharacterMaster user is null");
}
else
{
if ((bool)user.masterObject)
{
return;
}
CharacterMaster characterMaster = GetUserMaster(user.id);
bool flag = !characterMaster && ShouldAllowNewParticipant(user);
if (flag)
{
characterMaster = UnityEngine.Object.Instantiate(LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterMasters/CommandoMaster"), Vector3.zero, Quaternion.identity).GetComponent<CharacterMaster>();
if ((bool)characterMaster)
{
userMasters[user.id] = characterMaster;
if (ruleBook != null)
{
characterMaster.GiveMoney(ruleBook.startingMoney);
}
else
{
Debug.LogError("Can't give new master money because there's no rulebook");
}
DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(selectedDifficulty);
if ((bool)characterMaster.inventory)
{
if (selectedDifficulty == DifficultyIndex.Easy)
{
characterMaster.inventory.GiveItem(RoR2Content.Items.DrizzlePlayerHelper);
}
else if (difficultyDef.countsAsHardMode)
{
characterMaster.inventory.GiveItem(RoR2Content.Items.MonsoonPlayerHelper);
}
}
else
{
Debug.LogError("Instantiated master has no inventory");
}
NetworkServer.Spawn(characterMaster.gameObject);
}
else
{
Debug.LogError("Instantiated master object has no CharacterMaster");
}
}
if ((bool)characterMaster)
{
PlayerCharacterMasterController component = characterMaster.GetComponent<PlayerCharacterMasterController>();
if ((bool)component)
{
component.LinkToNetworkUserServer(user);
}
else
{
Debug.LogError("CharacterMaster has no PlayerCharacterMasterController");
}
if (flag)
{
Run.onPlayerFirstCreatedServer?.Invoke(this, component);
}
}
}
}
[Server]
public virtual void HandlePlayerFirstEntryAnimation(CharacterBody body, Vector3 spawnPosition, Quaternion spawnRotation)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::HandlePlayerFirstEntryAnimation(RoR2.CharacterBody,UnityEngine.Vector3,UnityEngine.Quaternion)' called on client");
}
else if ((bool)body)
{
if ((bool)body.preferredPodPrefab)
{
GameObject gameObject = UnityEngine.Object.Instantiate(body.preferredPodPrefab, body.transform.position, spawnRotation);
VehicleSeat component = gameObject.GetComponent<VehicleSeat>();
if ((bool)component)
{
component.AssignPassenger(body.gameObject);
}
else
{
Debug.LogError("Body " + body.name + " has preferred pod " + body.preferredPodPrefab.name + ", but that object has no VehicleSeat.");
}
NetworkServer.Spawn(gameObject);
}
else
{
body.SetBodyStateToPreferredInitialState();
}
}
else
{
Debug.LogError("Can't handle player first entry animation for null body.");
}
}
public virtual void OnServerBossAdded(BossGroup bossGroup, CharacterMaster characterMaster)
{
}
public virtual void OnServerBossDefeated(BossGroup bossGroup)
{
}
public virtual void OnServerCharacterBodySpawned(CharacterBody characterBody)
{
}
public virtual void OnServerTeleporterPlaced(SceneDirector sceneDirector, GameObject teleporter)
{
}
public virtual void OnPlayerSpawnPointsPlaced(SceneDirector sceneDirector)
{
}
public virtual GameObject GetTeleportEffectPrefab(GameObject objectToTeleport)
{
return LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/TeleportOutBoom");
}
public int GetDifficultyScaledCost(int baseCost, float difficultyCoefficient)
{
return (int)((float)baseCost * Mathf.Pow(difficultyCoefficient, 1.25f));
}
public int GetDifficultyScaledCost(int baseCost)
{
return GetDifficultyScaledCost(baseCost, instance.difficultyCoefficient);
}
public void BuildDropTable()
{
availableTier1DropList.Clear();
availableTier2DropList.Clear();
availableTier3DropList.Clear();
availableLunarItemDropList.Clear();
availableEquipmentDropList.Clear();
availableBossDropList.Clear();
availableLunarEquipmentDropList.Clear();
availableVoidTier1DropList.Clear();
availableVoidTier2DropList.Clear();
availableVoidTier3DropList.Clear();
availableVoidBossDropList.Clear();
ItemIndex itemIndex = ItemIndex.Count;
for (ItemIndex itemCount = (ItemIndex)ItemCatalog.itemCount; itemIndex < itemCount; itemIndex++)
{
if (availableItems.Contains(itemIndex))
{
ItemDef itemDef = ItemCatalog.GetItemDef(itemIndex);
List<PickupIndex> list = null;
switch (itemDef.tier)
{
case ItemTier.Tier1:
list = availableTier1DropList;
break;
case ItemTier.Tier2:
list = availableTier2DropList;
break;
case ItemTier.Tier3:
list = availableTier3DropList;
break;
case ItemTier.Lunar:
list = availableLunarItemDropList;
break;
case ItemTier.Boss:
list = availableBossDropList;
break;
case ItemTier.VoidTier1:
list = availableVoidTier1DropList;
break;
case ItemTier.VoidTier2:
list = availableVoidTier2DropList;
break;
case ItemTier.VoidTier3:
list = availableVoidTier3DropList;
break;
case ItemTier.VoidBoss:
list = availableVoidBossDropList;
break;
}
if (list != null && itemDef.DoesNotContainTag(ItemTag.WorldUnique))
{
list.Add(PickupCatalog.FindPickupIndex(itemIndex));
}
}
}
EquipmentIndex equipmentIndex = (EquipmentIndex)0;
for (EquipmentIndex equipmentCount = (EquipmentIndex)EquipmentCatalog.equipmentCount; equipmentIndex < equipmentCount; equipmentIndex++)
{
if (!availableEquipment.Contains(equipmentIndex))
{
continue;
}
EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(equipmentIndex);
if (equipmentDef.canDrop)
{
if (!equipmentDef.isLunar)
{
availableEquipmentDropList.Add(PickupCatalog.FindPickupIndex(equipmentIndex));
}
else
{
availableLunarEquipmentDropList.Add(PickupCatalog.FindPickupIndex(equipmentIndex));
}
}
}
smallChestDropTierSelector.Clear();
smallChestDropTierSelector.AddChoice(availableTier1DropList, 0.8f);
smallChestDropTierSelector.AddChoice(availableTier2DropList, 0.2f);
smallChestDropTierSelector.AddChoice(availableTier3DropList, 0.01f);
mediumChestDropTierSelector.Clear();
mediumChestDropTierSelector.AddChoice(availableTier2DropList, 0.8f);
mediumChestDropTierSelector.AddChoice(availableTier3DropList, 0.2f);
largeChestDropTierSelector.Clear();
RefreshLunarCombinedDropList();
}
public bool IsItemAvailable(ItemIndex itemIndex)
{
return availableItems.Contains(itemIndex);
}
public bool IsEquipmentAvailable(EquipmentIndex equipmentIndex)
{
return availableEquipment.Contains(equipmentIndex);
}
public bool IsItemExpansionLocked(ItemIndex itemIndex)
{
return expansionLockedItems.Contains(itemIndex);
}
public bool IsEquipmentExpansionLocked(EquipmentIndex equipmentIndex)
{
return expansionLockedEquipment.Contains(equipmentIndex);
}
public bool IsPickupAvailable(PickupIndex pickupIndex)
{
PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex);
if (pickupDef.itemIndex != ItemIndex.None)
{
return IsItemAvailable(pickupDef.itemIndex);
}
if (pickupDef.equipmentIndex != EquipmentIndex.None)
{
return IsEquipmentAvailable(pickupDef.equipmentIndex);
}
return true;
}
[Server]
public void DisablePickupDrop(PickupIndex pickupIndex)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::DisablePickupDrop(RoR2.PickupIndex)' called on client");
return;
}
PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex);
if (pickupDef.itemIndex != ItemIndex.None)
{
DisableItemDrop(pickupDef.itemIndex);
}
if (pickupDef.equipmentIndex != EquipmentIndex.None)
{
DisableEquipmentDrop(pickupDef.equipmentIndex);
}
}
[Server]
public void DisableItemDrop(ItemIndex itemIndex)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::DisableItemDrop(RoR2.ItemIndex)' called on client");
return;
}
ItemDef itemDef = ItemCatalog.GetItemDef(itemIndex);
List<PickupIndex> list = null;
bool flag = false;
switch (itemDef.tier)
{
case ItemTier.Tier1:
list = availableTier1DropList;
break;
case ItemTier.Tier2:
list = availableTier2DropList;
break;
case ItemTier.Tier3:
list = availableTier3DropList;
break;
case ItemTier.Lunar:
list = availableLunarItemDropList;
break;
case ItemTier.Boss:
list = availableBossDropList;
break;
case ItemTier.VoidTier1:
list = availableVoidTier1DropList;
break;
case ItemTier.VoidTier2:
list = availableVoidTier2DropList;
break;
case ItemTier.VoidTier3:
list = availableVoidTier3DropList;
break;
case ItemTier.VoidBoss:
list = availableVoidBossDropList;
break;
}
PickupIndex pickupIndex = PickupCatalog.FindPickupIndex(itemIndex);
if (list != null && pickupIndex != PickupIndex.none)
{
list.Remove(pickupIndex);
if (flag)
{
RefreshLunarCombinedDropList();
}
Run.onAvailablePickupsModified?.Invoke(this);
}
}
[Server]
public void DisableEquipmentDrop(EquipmentIndex equipmentIndex)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::DisableEquipmentDrop(RoR2.EquipmentIndex)' called on client");
return;
}
PickupIndex pickupIndex = PickupCatalog.FindPickupIndex(equipmentIndex);
if (!(pickupIndex != PickupIndex.none))
{
return;
}
List<PickupIndex> list = null;
bool flag = false;
if (PickupCatalog.GetPickupDef(pickupIndex).isLunar)
{
flag = true;
list = availableLunarEquipmentDropList;
}
else
{
list = availableEquipmentDropList;
}
if (list.Contains(pickupIndex))
{
list.Remove(pickupIndex);
if (flag)
{
RefreshLunarCombinedDropList();
}
Run.onAvailablePickupsModified?.Invoke(this);
}
}
[Server]
public void EnablePickupDrop(PickupIndex pickupIndex)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::EnablePickupDrop(RoR2.PickupIndex)' called on client");
return;
}
PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex);
if (pickupDef.itemIndex != ItemIndex.None)
{
EnableItemDrop(pickupDef.itemIndex);
}
if (pickupDef.equipmentIndex != EquipmentIndex.None)
{
EnableEquipmentDrop(pickupDef.equipmentIndex);
}
}
[Server]
public void EnableItemDrop(ItemIndex itemIndex)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::EnableItemDrop(RoR2.ItemIndex)' called on client");
return;
}
ItemDef itemDef = ItemCatalog.GetItemDef(itemIndex);
List<PickupIndex> list = null;
bool flag = false;
switch (itemDef.tier)
{
case ItemTier.Tier1:
list = availableTier1DropList;
break;
case ItemTier.Tier2:
list = availableTier2DropList;
break;
case ItemTier.Tier3:
list = availableTier3DropList;
break;
case ItemTier.Lunar:
list = availableLunarItemDropList;
break;
case ItemTier.Boss:
list = availableBossDropList;
break;
case ItemTier.VoidTier1:
list = availableVoidTier1DropList;
break;
case ItemTier.VoidTier2:
list = availableVoidTier2DropList;
break;
case ItemTier.VoidTier3:
list = availableVoidTier3DropList;
break;
case ItemTier.VoidBoss:
list = availableVoidBossDropList;
break;
}
PickupIndex pickupIndex = PickupCatalog.FindPickupIndex(itemIndex);
if (list != null && pickupIndex != PickupIndex.none && !list.Contains(pickupIndex))
{
list.Add(pickupIndex);
if (flag)
{
RefreshLunarCombinedDropList();
}
Run.onAvailablePickupsModified?.Invoke(this);
}
}
[Server]
public void EnableEquipmentDrop(EquipmentIndex equipmentIndex)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::EnableEquipmentDrop(RoR2.EquipmentIndex)' called on client");
return;
}
PickupIndex pickupIndex = PickupCatalog.FindPickupIndex(equipmentIndex);
if (!(pickupIndex != PickupIndex.none))
{
return;
}
List<PickupIndex> list = null;
bool flag = false;
list = ((!PickupCatalog.GetPickupDef(pickupIndex).isLunar) ? availableEquipmentDropList : availableLunarEquipmentDropList);
if (!list.Contains(pickupIndex))
{
list.Add(pickupIndex);
if (flag)
{
RefreshLunarCombinedDropList();
}
Run.onAvailablePickupsModified?.Invoke(this);
}
}
[Server]
private void RefreshLunarCombinedDropList()
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::RefreshLunarCombinedDropList()' called on client");
return;
}
availableLunarCombinedDropList.Clear();
availableLunarCombinedDropList.AddRange(availableLunarEquipmentDropList);
availableLunarCombinedDropList.AddRange(availableLunarItemDropList);
}
[ConCommand(commandName = "run_end", flags = ConVarFlags.SenderMustBeServer, helpText = "Ends the current run.")]
private static void CCRunEnd(ConCommandArgs args)
{
if ((bool)instance)
{
UnityEngine.Object.Destroy(instance.gameObject);
}
}
[ConCommand(commandName = "run_print_unlockables", flags = ConVarFlags.SenderMustBeServer, helpText = "Prints all unlockables available in this run.")]
private static void CCRunPrintUnlockables(ConCommandArgs args)
{
if (!instance)
{
throw new ConCommandException("No run is currently in progress.");
}
List<string> list = new List<string>();
foreach (UnlockableDef item in instance.unlockablesUnlockedByAnyUser)
{
list.Add(item.cachedName);
}
}
[ConCommand(commandName = "run_print_seed", flags = ConVarFlags.None, helpText = "Prints the seed of the current run.")]
private static void CCRunPrintSeed(ConCommandArgs args)
{
if (!instance)
{
throw new ConCommandException("No run is currently in progress.");
}
Debug.LogFormat("Current run seed: {0}", instance.seed);
}
[ConCommand(commandName = "run_set_stages_cleared", flags = (ConVarFlags.ExecuteOnServer | ConVarFlags.Cheat), helpText = "Sets the current number of stages cleared in the run.")]
private static void CCRunSetStagesCleared(ConCommandArgs args)
{
if (!instance)
{
throw new ConCommandException("No run is currently in progress.");
}
instance.NetworkstageClearCount = args.GetArgInt(0);
}
public virtual void AdvanceStage(SceneDef nextScene)
{
if ((bool)Stage.instance)
{
Stage.instance.CompleteServer();
SceneType sceneType = SceneCatalog.GetSceneDefForCurrentScene().sceneType;
if (sceneType == SceneType.Stage || sceneType == SceneType.UntimedStage)
{
NetworkstageClearCount = stageClearCount + 1;
}
}
GenerateStageRNG();
RecalculateDifficultyCoefficent();
NetworkManager.singleton.ServerChangeScene(nextScene.cachedName);
}
public void BeginGameOver([NotNull] GameEndingDef gameEndingDef)
{
if (isGameOverServer)
{
return;
}
if ((bool)Stage.instance && gameEndingDef.isWin)
{
Stage.instance.CompleteServer();
}
isGameOverServer = true;
if (gameEndingDef.lunarCoinReward != 0)
{
for (int i = 0; i < NetworkUser.readOnlyInstancesList.Count; i++)
{
NetworkUser networkUser = NetworkUser.readOnlyInstancesList[i];
if ((bool)networkUser && networkUser.isParticipating)
{
networkUser.AwardLunarCoins(gameEndingDef.lunarCoinReward);
}
}
}
StatManager.ForceUpdate();
GameObject obj = UnityEngine.Object.Instantiate(gameOverPrefab);
GameOverController component = obj.GetComponent<GameOverController>();
component.SetRunReport(RunReport.Generate(this, gameEndingDef));
Run.onServerGameOver?.Invoke(this, gameEndingDef);
NetworkServer.Spawn(obj);
isRunning = false;
component.CallRpcClientGameOver();
}
public virtual void OnClientGameOver(RunReport runReport)
{
isRunning = false;
Run.onClientGameOverGlobal?.Invoke(this, runReport);
}
public virtual void OverrideRuleChoices(RuleChoiceMask mustInclude, RuleChoiceMask mustExclude, ulong runSeed)
{
ForceChoice(mustInclude, mustExclude, "Misc.KeepMoneyBetweenStages.Off");
}
protected void ForceChoice(RuleChoiceMask mustInclude, RuleChoiceMask mustExclude, RuleChoiceDef choiceDef)
{
foreach (RuleChoiceDef choice in choiceDef.ruleDef.choices)
{
mustInclude[choice.globalIndex] = false;
mustExclude[choice.globalIndex] = true;
}
mustInclude[choiceDef.globalIndex] = true;
mustExclude[choiceDef.globalIndex] = false;
}
protected void ForceChoice(RuleChoiceMask mustInclude, RuleChoiceMask mustExclude, string choiceDefGlobalName)
{
ForceChoice(mustInclude, mustExclude, RuleCatalog.FindChoiceDef(choiceDefGlobalName));
}
public virtual Vector3 FindSafeTeleportPosition(CharacterBody characterBody, Transform targetDestination)
{
return FindSafeTeleportPosition(characterBody, targetDestination, float.NegativeInfinity, float.NegativeInfinity);
}
public virtual Vector3 FindSafeTeleportPosition(CharacterBody characterBody, Transform targetDestination, float idealMinDistance, float idealMaxDistance)
{
Vector3 vector = (targetDestination ? targetDestination.position : characterBody.transform.position);
SpawnCard spawnCard = ScriptableObject.CreateInstance<SpawnCard>();
spawnCard.hullSize = characterBody.hullClassification;
spawnCard.nodeGraphType = MapNodeGroup.GraphType.Ground;
spawnCard.prefab = LegacyResourcesAPI.Load<GameObject>("SpawnCards/HelperPrefab");
Vector3 result = vector;
GameObject gameObject = null;
if (idealMaxDistance > 0f && idealMinDistance < idealMaxDistance)
{
gameObject = DirectorCore.instance.TrySpawnObject(new DirectorSpawnRequest(spawnCard, new DirectorPlacementRule
{
placementMode = DirectorPlacementRule.PlacementMode.Approximate,
minDistance = idealMinDistance,
maxDistance = idealMaxDistance,
position = vector
}, RoR2Application.rng));
}
if (!gameObject)
{
gameObject = DirectorCore.instance.TrySpawnObject(new DirectorSpawnRequest(spawnCard, new DirectorPlacementRule
{
placementMode = DirectorPlacementRule.PlacementMode.NearestNode,
position = vector
}, RoR2Application.rng));
if ((bool)gameObject)
{
result = gameObject.transform.position;
}
}
if ((bool)gameObject)
{
UnityEngine.Object.Destroy(gameObject);
}
UnityEngine.Object.Destroy(spawnCard);
return result;
}
[Server]
public void SetEventFlag(string name)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::SetEventFlag(System.String)' called on client");
}
else
{
eventFlags.Add(name);
}
}
[Server]
public bool GetEventFlag(string name)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Boolean RoR2.Run::GetEventFlag(System.String)' called on client");
return false;
}
return eventFlags.Contains(name);
}
[Server]
public void ResetEventFlag(string name)
{
if (!NetworkServer.active)
{
Debug.LogWarning("[Server] function 'System.Void RoR2.Run::ResetEventFlag(System.String)' called on client");
}
else
{
eventFlags.Remove(name);
}
}
public virtual bool ShouldAllowNonChampionBossSpawn()
{
return stageClearCount > 0;
}
public bool IsExpansionEnabled([NotNull] ExpansionDef expansionDef)
{
if (expansionDef.enabledChoice != null)
{
return ruleBook.IsChoiceActive(expansionDef.enabledChoice);
}
return false;
}
protected virtual void OnSeedSet()
{
}
private void UNetVersion()
{
}
public override bool OnSerialize(NetworkWriter writer, bool forceAll)
{
if (forceAll)
{
GeneratedNetworkCode._WriteNetworkGuid_None(writer, _uniqueId);
GeneratedNetworkCode._WriteNetworkDateTime_None(writer, startTimeUtc);
writer.Write(fixedTime);
GeneratedNetworkCode._WriteRunStopwatch_Run(writer, runStopwatch);
writer.WritePackedUInt32((uint)stageClearCount);
writer.WritePackedUInt32((uint)selectedDifficultyInternal);
return true;
}
bool flag = false;
if ((base.syncVarDirtyBits & (true ? 1u : 0u)) != 0)
{
if (!flag)
{
writer.WritePackedUInt32(base.syncVarDirtyBits);
flag = true;
}
GeneratedNetworkCode._WriteNetworkGuid_None(writer, _uniqueId);
}
if ((base.syncVarDirtyBits & 2u) != 0)
{
if (!flag)
{
writer.WritePackedUInt32(base.syncVarDirtyBits);
flag = true;
}
GeneratedNetworkCode._WriteNetworkDateTime_None(writer, startTimeUtc);
}
if ((base.syncVarDirtyBits & 4u) != 0)
{
if (!flag)
{
writer.WritePackedUInt32(base.syncVarDirtyBits);
flag = true;
}
writer.Write(fixedTime);
}
if ((base.syncVarDirtyBits & 8u) != 0)
{
if (!flag)
{
writer.WritePackedUInt32(base.syncVarDirtyBits);
flag = true;
}
GeneratedNetworkCode._WriteRunStopwatch_Run(writer, runStopwatch);
}
if ((base.syncVarDirtyBits & 0x10u) != 0)
{
if (!flag)
{
writer.WritePackedUInt32(base.syncVarDirtyBits);
flag = true;
}
writer.WritePackedUInt32((uint)stageClearCount);
}
if ((base.syncVarDirtyBits & 0x20u) != 0)
{
if (!flag)
{
writer.WritePackedUInt32(base.syncVarDirtyBits);
flag = true;
}
writer.WritePackedUInt32((uint)selectedDifficultyInternal);
}
if (!flag)
{
writer.WritePackedUInt32(base.syncVarDirtyBits);
}
return flag;
}
public override void OnDeserialize(NetworkReader reader, bool initialState)
{
if (initialState)
{
_uniqueId = GeneratedNetworkCode._ReadNetworkGuid_None(reader);
startTimeUtc = GeneratedNetworkCode._ReadNetworkDateTime_None(reader);
fixedTime = reader.ReadSingle();
runStopwatch = GeneratedNetworkCode._ReadRunStopwatch_Run(reader);
stageClearCount = (int)reader.ReadPackedUInt32();
selectedDifficultyInternal = (int)reader.ReadPackedUInt32();
return;
}
int num = (int)reader.ReadPackedUInt32();
if (((uint)num & (true ? 1u : 0u)) != 0)
{
_uniqueId = GeneratedNetworkCode._ReadNetworkGuid_None(reader);
}
if (((uint)num & 2u) != 0)
{
startTimeUtc = GeneratedNetworkCode._ReadNetworkDateTime_None(reader);
}
if (((uint)num & 4u) != 0)
{
fixedTime = reader.ReadSingle();
}
if (((uint)num & 8u) != 0)
{
runStopwatch = GeneratedNetworkCode._ReadRunStopwatch_Run(reader);
}
if (((uint)num & 0x10u) != 0)
{
stageClearCount = (int)reader.ReadPackedUInt32();
}
if (((uint)num & 0x20u) != 0)
{
selectedDifficultyInternal = (int)reader.ReadPackedUInt32();
}
}
public override void PreStartClient()
{
}
}