// Decompiled with JetBrains decompiler // Type: Terraria.GameContent.Ambience.AmbienceServer // Assembly: Terraria, Version=1.4.0.5, Culture=neutral, PublicKeyToken=null // MVID: 67F9E73E-0A81-4937-A22C-5515CD405A83 // Assembly location: C:\Users\mikeyisbaeyt\Downloads\depotdownloader-2.4.5\depots\105601\6707058\Terraria.exe using System; using System.Collections.Generic; using System.Linq; using Terraria.GameContent.NetModules; using Terraria.Net; namespace Terraria.GameContent.Ambience { public class AmbienceServer { private const int MINIMUM_SECONDS_BETWEEN_SPAWNS = 10; private const int MAXIMUM_SECONDS_BETWEEN_SPAWNS = 120; private readonly Dictionary> _spawnConditions = new Dictionary>(); private readonly Dictionary> _secondarySpawnConditionsPerPlayer = new Dictionary>(); private int _updatesUntilNextAttempt; private List _forcedSpawns = new List(); private static bool IsSunnyDay() => !Main.IsItRaining && Main.dayTime && !Main.eclipse; private static bool IsSunset() => Main.dayTime && Main.time > 40500.0; private static bool IsCalmNight() => !Main.IsItRaining && !Main.dayTime && !Main.bloodMoon && !Main.pumpkinMoon && !Main.snowMoon; public AmbienceServer() { this.ResetSpawnTime(); this._spawnConditions[SkyEntityType.BirdsV] = new Func(AmbienceServer.IsSunnyDay); this._spawnConditions[SkyEntityType.Wyvern] = (Func) (() => AmbienceServer.IsSunnyDay() && Main.hardMode); this._spawnConditions[SkyEntityType.Airship] = (Func) (() => AmbienceServer.IsSunnyDay() && Main.IsItAHappyWindyDay); this._spawnConditions[SkyEntityType.AirBalloon] = (Func) (() => AmbienceServer.IsSunnyDay() && !Main.IsItAHappyWindyDay); this._spawnConditions[SkyEntityType.Eyeball] = (Func) (() => !Main.dayTime); this._spawnConditions[SkyEntityType.Butterflies] = (Func) (() => AmbienceServer.IsSunnyDay() && !Main.IsItAHappyWindyDay && !NPC.TooWindyForButterflies && NPC.butterflyChance < 6); this._spawnConditions[SkyEntityType.LostKite] = (Func) (() => Main.dayTime && !Main.eclipse && Main.IsItAHappyWindyDay); this._spawnConditions[SkyEntityType.Vulture] = (Func) (() => AmbienceServer.IsSunnyDay()); this._spawnConditions[SkyEntityType.Bats] = (Func) (() => AmbienceServer.IsSunset() && AmbienceServer.IsSunnyDay() || AmbienceServer.IsCalmNight()); this._spawnConditions[SkyEntityType.PixiePosse] = (Func) (() => AmbienceServer.IsSunnyDay() || AmbienceServer.IsCalmNight()); this._spawnConditions[SkyEntityType.Seagulls] = (Func) (() => AmbienceServer.IsSunnyDay()); this._spawnConditions[SkyEntityType.SlimeBalloons] = (Func) (() => AmbienceServer.IsSunnyDay() && Main.IsItAHappyWindyDay); this._spawnConditions[SkyEntityType.Gastropods] = (Func) (() => AmbienceServer.IsCalmNight()); this._spawnConditions[SkyEntityType.Pegasus] = (Func) (() => AmbienceServer.IsSunnyDay()); this._spawnConditions[SkyEntityType.EaterOfSouls] = (Func) (() => AmbienceServer.IsSunnyDay() || AmbienceServer.IsCalmNight()); this._spawnConditions[SkyEntityType.Crimera] = (Func) (() => AmbienceServer.IsSunnyDay() || AmbienceServer.IsCalmNight()); this._spawnConditions[SkyEntityType.Hellbats] = (Func) (() => true); this._secondarySpawnConditionsPerPlayer[SkyEntityType.Vulture] = (Func) (player => player.ZoneDesert); this._secondarySpawnConditionsPerPlayer[SkyEntityType.PixiePosse] = (Func) (player => player.ZoneHallow); this._secondarySpawnConditionsPerPlayer[SkyEntityType.Seagulls] = (Func) (player => player.ZoneBeach); this._secondarySpawnConditionsPerPlayer[SkyEntityType.Gastropods] = (Func) (player => player.ZoneHallow); this._secondarySpawnConditionsPerPlayer[SkyEntityType.Pegasus] = (Func) (player => player.ZoneHallow); this._secondarySpawnConditionsPerPlayer[SkyEntityType.EaterOfSouls] = (Func) (player => player.ZoneCorrupt); this._secondarySpawnConditionsPerPlayer[SkyEntityType.Crimera] = (Func) (player => player.ZoneCrimson); this._secondarySpawnConditionsPerPlayer[SkyEntityType.Bats] = (Func) (player => player.ZoneJungle); } private bool IsPlayerAtRightHeightForType(SkyEntityType type, Player plr) => type == SkyEntityType.Hellbats ? AmbienceServer.IsPlayerInAPlaceWhereTheyCanSeeAmbienceHell(plr) : AmbienceServer.IsPlayerInAPlaceWhereTheyCanSeeAmbienceSky(plr); public void Update() { this.SpawnForcedEntities(); if (this._updatesUntilNextAttempt > 0) { this._updatesUntilNextAttempt -= Main.dayRate; } else { this.ResetSpawnTime(); IEnumerable source1 = this._spawnConditions.Where>>((Func>, bool>) (pair => pair.Value())).Select>, SkyEntityType>((Func>, SkyEntityType>) (pair => pair.Key)); if (source1.Count((Func) (type => true)) == 0) return; Player player; AmbienceServer.FindPlayerThatCanSeeBackgroundAmbience(out player); if (player == null) return; IEnumerable source2 = source1.Where((Func) (type => this.IsPlayerAtRightHeightForType(type, player) && this._secondarySpawnConditionsPerPlayer.ContainsKey(type) && this._secondarySpawnConditionsPerPlayer[type](player))); int maxValue = source2.Count((Func) (type => true)); if (maxValue == 0 || Main.rand.Next(5) < 3) { source2 = source1.Where((Func) (type => { if (!this.IsPlayerAtRightHeightForType(type, player)) return false; return !this._secondarySpawnConditionsPerPlayer.ContainsKey(type) || this._secondarySpawnConditionsPerPlayer[type](player); })); maxValue = source2.Count((Func) (type => true)); } if (maxValue == 0) return; SkyEntityType type1 = source2.ElementAt(Main.rand.Next(maxValue)); this.SpawnForPlayer(player, type1); } } public void ResetSpawnTime() => this._updatesUntilNextAttempt = Main.rand.Next(600, 7200); public void ForceEntitySpawn(AmbienceServer.AmbienceSpawnInfo info) => this._forcedSpawns.Add(info); private void SpawnForcedEntities() { if (this._forcedSpawns.Count == 0) return; for (int index = this._forcedSpawns.Count - 1; index >= 0; --index) { AmbienceServer.AmbienceSpawnInfo forcedSpawn = this._forcedSpawns[index]; Player player; if (forcedSpawn.targetPlayer == -1) AmbienceServer.FindPlayerThatCanSeeBackgroundAmbience(out player); else player = Main.player[forcedSpawn.targetPlayer]; if (player != null && this.IsPlayerAtRightHeightForType(forcedSpawn.skyEntityType, player)) this.SpawnForPlayer(player, forcedSpawn.skyEntityType); this._forcedSpawns.RemoveAt(index); } } private static void FindPlayerThatCanSeeBackgroundAmbience(out Player player) { player = (Player) null; int maxValue = ((IEnumerable) Main.player).Count((Func) (plr => plr.active && AmbienceServer.IsPlayerInAPlaceWhereTheyCanSeeAmbience(plr))); if (maxValue == 0) return; player = ((IEnumerable) Main.player).Where((Func) (plr => plr.active && AmbienceServer.IsPlayerInAPlaceWhereTheyCanSeeAmbience(plr))).ElementAt(Main.rand.Next(maxValue)); } private static bool IsPlayerInAPlaceWhereTheyCanSeeAmbience(Player plr) => AmbienceServer.IsPlayerInAPlaceWhereTheyCanSeeAmbienceSky(plr) || AmbienceServer.IsPlayerInAPlaceWhereTheyCanSeeAmbienceHell(plr); private static bool IsPlayerInAPlaceWhereTheyCanSeeAmbienceSky(Player plr) => (double) plr.position.Y <= Main.worldSurface * 16.0 + 1600.0; private static bool IsPlayerInAPlaceWhereTheyCanSeeAmbienceHell(Player plr) => (double) plr.position.Y >= (double) ((Main.UnderworldLayer - 100) * 16); private void SpawnForPlayer(Player player, SkyEntityType type) => NetManager.Instance.BroadcastOrLoopback(NetAmbienceModule.SerializeSkyEntitySpawn(player, type)); public struct AmbienceSpawnInfo { public SkyEntityType skyEntityType; public int targetPlayer; } } }