fix: Eliminates allocations in canned evil timer (#2209)
This commit is contained in:
parent
0d2ed60fed
commit
ea4080ce0e
5 changed files with 145 additions and 146 deletions
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Collections;
|
||||
using Server.Misc;
|
||||
|
||||
namespace Server.Engines.CannedEvil
|
||||
|
|
@ -29,8 +30,8 @@ namespace Server.Engines.CannedEvil
|
|||
Instance.OnTick();
|
||||
}
|
||||
|
||||
private static readonly HashSet<DungeonChampionSpawn> _dungeonSpawns = new();
|
||||
private static readonly HashSet<LLChampionSpawn> _lostLandsSpawns = new();
|
||||
private static readonly HashSet<ChampionSpawn> _dungeonSpawns = new();
|
||||
private static readonly HashSet<ChampionSpawn> _lostLandsSpawns = new();
|
||||
private static DateTime _sliceTime;
|
||||
|
||||
public static CannedEvilTimer Instance { get; private set; }
|
||||
|
|
@ -38,25 +39,25 @@ namespace Server.Engines.CannedEvil
|
|||
public static void AddSpawn(DungeonChampionSpawn spawn)
|
||||
{
|
||||
_dungeonSpawns.Add(spawn);
|
||||
Instance?.OnSlice(_dungeonSpawns, false);
|
||||
OnSlice(_dungeonSpawns, false);
|
||||
}
|
||||
|
||||
public static void AddSpawn(LLChampionSpawn spawn)
|
||||
{
|
||||
_lostLandsSpawns.Add(spawn);
|
||||
Instance?.OnSlice(_lostLandsSpawns, false);
|
||||
OnSlice(_lostLandsSpawns, false);
|
||||
}
|
||||
|
||||
public static void RemoveSpawn(DungeonChampionSpawn spawn)
|
||||
{
|
||||
_dungeonSpawns.Remove(spawn);
|
||||
Instance?.OnSlice(_dungeonSpawns, false);
|
||||
OnSlice(_dungeonSpawns, false);
|
||||
}
|
||||
|
||||
public static void RemoveSpawn(LLChampionSpawn spawn)
|
||||
{
|
||||
_lostLandsSpawns.Remove(spawn);
|
||||
Instance?.OnSlice(_lostLandsSpawns, false);
|
||||
OnSlice(_lostLandsSpawns, false);
|
||||
}
|
||||
|
||||
public CannedEvilTimer() : base(TimeSpan.Zero, TimeSpan.FromMinutes(1.0))
|
||||
|
|
@ -64,32 +65,34 @@ namespace Server.Engines.CannedEvil
|
|||
_sliceTime = Core.Now;
|
||||
}
|
||||
|
||||
public void OnSlice<T>(ICollection<T> list, bool rotate = true) where T : ChampionSpawn
|
||||
public static void OnSlice(HashSet<ChampionSpawn> spawns, bool rotate = true)
|
||||
{
|
||||
if (list.Count > 0)
|
||||
if (spawns.Count <= 0)
|
||||
{
|
||||
List<T> valid = new List<T>();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (T spawn in list)
|
||||
using var queue = rotate ? PooledRefQueue<Item>.Create() : default;
|
||||
|
||||
foreach (var spawn in spawns)
|
||||
{
|
||||
if (spawn.AlwaysActive && !spawn.Active)
|
||||
{
|
||||
if (spawn.AlwaysActive && !spawn.Active)
|
||||
{
|
||||
spawn.ReadyToActivate = true;
|
||||
}
|
||||
else if (rotate && (!spawn.Active || spawn.Kills == 0 && spawn.Level == 0))
|
||||
{
|
||||
spawn.Active = false;
|
||||
spawn.ReadyToActivate = false;
|
||||
|
||||
valid.Add(spawn);
|
||||
}
|
||||
spawn.ReadyToActivate = true;
|
||||
}
|
||||
|
||||
if (valid.Count > 0)
|
||||
else if (rotate && (!spawn.Active || spawn.Kills == 0 && spawn.Level == 0))
|
||||
{
|
||||
valid[Utility.Random(valid.Count)].ReadyToActivate = true;
|
||||
spawn.Active = false;
|
||||
spawn.ReadyToActivate = false;
|
||||
|
||||
queue.Enqueue(spawn);
|
||||
}
|
||||
}
|
||||
|
||||
if (rotate && queue.Count > 0)
|
||||
{
|
||||
((ChampionSpawn)queue.PeekRandom()).ReadyToActivate = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
|
|
|
|||
|
|
@ -26,11 +26,6 @@ public partial class DungeonChampionSpawn : ChampionSpawn
|
|||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
|
||||
public DungeonChampionSpawn(Serial serial) : base(serial)
|
||||
{
|
||||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
|
||||
public override bool ProximitySpawn => true;
|
||||
public override bool AlwaysActive => false;
|
||||
|
||||
|
|
@ -39,4 +34,7 @@ public partial class DungeonChampionSpawn : ChampionSpawn
|
|||
base.OnAfterDelete();
|
||||
CannedEvilTimer.RemoveSpawn(this);
|
||||
}
|
||||
|
||||
[AfterDeserialization]
|
||||
private void AfterDeserialization() => CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,35 +15,34 @@
|
|||
|
||||
using System;
|
||||
|
||||
namespace Server.Engines.CannedEvil
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
public class ChampionEntry
|
||||
{
|
||||
public record ChampionEntry
|
||||
public readonly bool _randomizeType;
|
||||
public readonly ChampionSpawnType _type;
|
||||
public readonly Point3D _signLocation;
|
||||
public readonly Type _champType;
|
||||
public readonly Map _map;
|
||||
public readonly Point3D _ejectLocation;
|
||||
public readonly Map _ejectMap;
|
||||
|
||||
public ChampionEntry(Type champtype, Point3D signloc, Map map, Point3D ejectloc, Map ejectmap) :
|
||||
this(champtype, ChampionSpawnType.Abyss, signloc, map, ejectloc, ejectmap, true)
|
||||
{
|
||||
public readonly bool m_RandomizeType;
|
||||
public readonly ChampionSpawnType m_Type;
|
||||
public readonly Point3D m_SignLocation;
|
||||
public readonly Type m_ChampType;
|
||||
public readonly Map m_Map;
|
||||
public readonly Point3D m_EjectLocation;
|
||||
public readonly Map m_EjectMap;
|
||||
}
|
||||
|
||||
public ChampionEntry(Type champtype, Point3D signloc, Map map, Point3D ejectloc, Map ejectmap) :
|
||||
this(champtype, ChampionSpawnType.Abyss, signloc, map, ejectloc, ejectmap, true)
|
||||
{
|
||||
}
|
||||
|
||||
public ChampionEntry(
|
||||
Type champtype, ChampionSpawnType type, Point3D signloc, Map map, Point3D ejectloc, Map ejectmap,
|
||||
bool randomizetype = false
|
||||
)
|
||||
{
|
||||
m_ChampType = champtype;
|
||||
m_RandomizeType = randomizetype;
|
||||
m_Type = type;
|
||||
m_SignLocation = signloc;
|
||||
m_Map = map;
|
||||
m_EjectLocation = ejectloc;
|
||||
m_EjectMap = ejectmap;
|
||||
}
|
||||
public ChampionEntry(
|
||||
Type champtype, ChampionSpawnType type, Point3D signloc, Map map, Point3D ejectloc, Map ejectmap,
|
||||
bool randomizetype = false
|
||||
)
|
||||
{
|
||||
_champType = champtype;
|
||||
_randomizeType = randomizetype;
|
||||
_type = type;
|
||||
_signLocation = signloc;
|
||||
_map = map;
|
||||
_ejectLocation = ejectloc;
|
||||
_ejectMap = ejectmap;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,105 +17,106 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using Server.Logging;
|
||||
|
||||
namespace Server.Engines.CannedEvil
|
||||
namespace Server.Engines.CannedEvil;
|
||||
|
||||
public static class ChampionGenerator
|
||||
{
|
||||
public static class ChampionGenerator
|
||||
private static readonly ILogger logger = LogFactory.GetLogger(typeof(ChampionGenerator));
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
private static readonly ILogger logger = LogFactory.GetLogger(typeof(ChampionGenerator));
|
||||
CommandSystem.Register("GenChamps", AccessLevel.Developer, ChampGen_OnCommand);
|
||||
}
|
||||
|
||||
public static void Configure()
|
||||
private static readonly ChampionEntry[] LLLocations =
|
||||
[
|
||||
new(typeof(LLChampionSpawn), new Point3D(5511, 2360, 42), Map.Felucca, new Point3D(5439, 2323, 26), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(6038, 2401, 47), Map.Felucca, new Point3D(5988, 2340, 24), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5549, 2640, 16), Map.Felucca, new Point3D(5645, 2696, -8), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5636, 2916, 37), Map.Felucca, new Point3D(5721, 2949, 28), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(6035, 2943, 50), Map.Felucca, new Point3D(6098, 2997, 17), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5265, 3171, 105), Map.Felucca, new Point3D(5314, 3232, 2), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5282, 3368, 50), Map.Felucca, new Point3D(5215, 3318, 3), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5207, 3637, 20), Map.Felucca, new Point3D(5263, 3687, 0), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5954, 3475, 25), Map.Felucca, new Point3D(6013, 3529, 0), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5982, 3882, 20), Map.Felucca, new Point3D(5929, 3820, -1), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5724, 3991, 41), Map.Felucca, new Point3D(5774, 4041, 26), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), ChampionSpawnType.ForestLord, new Point3D(5559, 3757, 21), Map.Felucca, new Point3D(5513, 3878, 3), Map.Felucca)
|
||||
];
|
||||
|
||||
private static readonly ChampionEntry[] DungeonLocations =
|
||||
[
|
||||
new(typeof(DungeonChampionSpawn), ChampionSpawnType.UnholyTerror, new Point3D(5179, 709, 20), Map.Felucca, new Point3D(4111, 432, 5), Map.Felucca),
|
||||
new(typeof(DungeonChampionSpawn), ChampionSpawnType.VerminHorde, new Point3D(5557, 827, 65), Map.Felucca, new Point3D(5580, 632, 30), Map.Felucca),
|
||||
new(typeof(DungeonChampionSpawn), ChampionSpawnType.ColdBlood, new Point3D(5259, 837, 64), Map.Felucca, new Point3D(1176, 2637, 0), Map.Felucca),
|
||||
new(typeof(DungeonChampionSpawn), ChampionSpawnType.Abyss, new Point3D(5815, 1352, 5), Map.Felucca, new Point3D(2923, 3406, 8), Map.Felucca),
|
||||
new(typeof(DungeonChampionSpawn), ChampionSpawnType.Arachnid, new Point3D(5190, 1607, 20), Map.Felucca, new Point3D(5482, 3161, -54), Map.Felucca)
|
||||
];
|
||||
|
||||
[Usage("GenChamps")]
|
||||
[Description("Generates champions for Felucca Dungeons & Lost Lands.")]
|
||||
private static void ChampGen_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
/*
|
||||
//We take the assumption that we are spawning managed champions
|
||||
for (int i = CannedEvilTimer.DungeonSpawns.Count - 1; i >= 0; i--)
|
||||
CannedEvilTimer.DungeonSpawns[i].Delete();
|
||||
|
||||
for (int i = CannedEvilTimer.LLSpawns.Count - 1; i >= 0; i--)
|
||||
CannedEvilTimer.LLSpawns[i].Delete();
|
||||
*/
|
||||
|
||||
//We assume that all champion spawns are generated here.
|
||||
List<ChampionSpawn> spawns = [];
|
||||
foreach (Item item in World.Items.Values)
|
||||
{
|
||||
CommandSystem.Register("GenChamps", AccessLevel.Developer, ChampGen_OnCommand);
|
||||
if (item is ChampionSpawn spawn)
|
||||
{
|
||||
spawns.Add(spawn);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly ChampionEntry[] LLLocations = {
|
||||
new(typeof(LLChampionSpawn), new Point3D(5511, 2360, 42), Map.Felucca, new Point3D(5439, 2323, 26 ), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(6038, 2401, 47), Map.Felucca, new Point3D(5988, 2340, 24), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5549, 2640, 16), Map.Felucca, new Point3D(5645, 2696, -8), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5636, 2916, 37), Map.Felucca, new Point3D(5721, 2949, 28), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(6035, 2943, 50), Map.Felucca, new Point3D(6098, 2997, 17), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5265, 3171, 105), Map.Felucca, new Point3D(5314, 3232, 2), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5282, 3368, 50), Map.Felucca, new Point3D(5215, 3318, 3), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5207, 3637, 20), Map.Felucca, new Point3D(5263, 3687, 0), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5954, 3475, 25), Map.Felucca, new Point3D(6013, 3529, 0), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5982, 3882, 20), Map.Felucca, new Point3D(5929, 3820, -1), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), new Point3D(5724, 3991, 41), Map.Felucca, new Point3D(5774, 4041, 26), Map.Felucca),
|
||||
new(typeof(LLChampionSpawn), ChampionSpawnType.ForestLord, new Point3D(5559, 3757, 21), Map.Felucca, new Point3D(5513, 3878, 3), Map.Felucca),
|
||||
};
|
||||
|
||||
private static readonly ChampionEntry[] DungeonLocations = {
|
||||
new(typeof(DungeonChampionSpawn), ChampionSpawnType.UnholyTerror, new Point3D(5179, 709, 20), Map.Felucca, new Point3D(4111, 432, 5), Map.Felucca),
|
||||
new(typeof(DungeonChampionSpawn), ChampionSpawnType.VerminHorde, new Point3D(5557, 827, 65), Map.Felucca, new Point3D(5580, 632, 30), Map.Felucca),
|
||||
new(typeof(DungeonChampionSpawn), ChampionSpawnType.ColdBlood, new Point3D(5259, 837, 64), Map.Felucca, new Point3D(1176, 2637, 0), Map.Felucca),
|
||||
new(typeof(DungeonChampionSpawn), ChampionSpawnType.Abyss, new Point3D(5815, 1352, 5), Map.Felucca, new Point3D(2923, 3406, 8), Map.Felucca),
|
||||
new(typeof(DungeonChampionSpawn), ChampionSpawnType.Arachnid, new Point3D(5190, 1607, 20), Map.Felucca, new Point3D(5482, 3161, -54), Map.Felucca),
|
||||
};
|
||||
|
||||
[Usage("GenChamps")]
|
||||
[Description("Generates champions for Felucca Dungeons & Lost Lands.")]
|
||||
private static void ChampGen_OnCommand(CommandEventArgs e)
|
||||
for (int i = spawns.Count - 1; i >= 0; i--)
|
||||
{
|
||||
/*
|
||||
//We take the assumption that we are spawning managed champions
|
||||
for (int i = CannedEvilTimer.DungeonSpawns.Count - 1; i >= 0; i--)
|
||||
CannedEvilTimer.DungeonSpawns[i].Delete();
|
||||
|
||||
for (int i = CannedEvilTimer.LLSpawns.Count - 1; i >= 0; i--)
|
||||
CannedEvilTimer.LLSpawns[i].Delete();
|
||||
*/
|
||||
|
||||
//We assume that all champion spawns are generated here.
|
||||
List<ChampionSpawn> spawns = new List<ChampionSpawn>();
|
||||
foreach (Item item in World.Items.Values)
|
||||
{
|
||||
if (item is ChampionSpawn spawn)
|
||||
{
|
||||
spawns.Add(spawn);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = spawns.Count - 1; i >= 0; i--)
|
||||
{
|
||||
spawns[i].Delete();
|
||||
}
|
||||
|
||||
Process(DungeonLocations);
|
||||
Process(LLLocations);
|
||||
//ProcessIlshenar();
|
||||
//ProcessTokuno();
|
||||
spawns[i].Delete();
|
||||
}
|
||||
|
||||
private static void Process(ChampionEntry[] entries)
|
||||
{
|
||||
for (int i = 0; i < entries.Length; i++)
|
||||
{
|
||||
ChampionEntry entry = entries[i];
|
||||
Process(DungeonLocations);
|
||||
Process(LLLocations);
|
||||
//ProcessIlshenar();
|
||||
//ProcessTokuno();
|
||||
}
|
||||
|
||||
try
|
||||
private static void Process(ChampionEntry[] entries)
|
||||
{
|
||||
for (int i = 0; i < entries.Length; i++)
|
||||
{
|
||||
ChampionEntry entry = entries[i];
|
||||
|
||||
try
|
||||
{
|
||||
if (Activator.CreateInstance(entry._champType) is ChampionSpawn spawn)
|
||||
{
|
||||
if (Activator.CreateInstance(entry.m_ChampType) is ChampionSpawn spawn)
|
||||
spawn.RandomizeType = entry._randomizeType;
|
||||
spawn.Type = entry._type;
|
||||
spawn.MoveToWorld(entry._signLocation, entry._map);
|
||||
spawn.EjectLocation = entry._ejectLocation;
|
||||
spawn.EjectMap = entry._ejectMap;
|
||||
if (spawn.AlwaysActive)
|
||||
{
|
||||
spawn.RandomizeType = entry.m_RandomizeType;
|
||||
spawn.Type = entry.m_Type;
|
||||
spawn.MoveToWorld(entry.m_SignLocation, entry.m_Map);
|
||||
spawn.EjectLocation = entry.m_EjectLocation;
|
||||
spawn.EjectMap = entry.m_EjectMap;
|
||||
if (spawn.AlwaysActive)
|
||||
{
|
||||
spawn.ReadyToActivate = true;
|
||||
}
|
||||
spawn.ReadyToActivate = true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error(
|
||||
e,
|
||||
"Failed to generate champion \"{Type}\" at {Location} ({Map}).",
|
||||
entry.m_ChampType.FullName,
|
||||
entry.m_SignLocation,
|
||||
entry.m_Map
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error(
|
||||
e,
|
||||
"Failed to generate champion \"{Type}\" at {Location} ({Map}).",
|
||||
entry._champType.FullName,
|
||||
entry._signLocation,
|
||||
entry._map
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,6 @@ public partial class LLChampionSpawn : ChampionSpawn
|
|||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
|
||||
public LLChampionSpawn(Serial serial) : base(serial)
|
||||
{
|
||||
CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
|
||||
public override bool AlwaysActive => false;
|
||||
|
||||
public override void OnAfterDelete()
|
||||
|
|
@ -40,4 +35,7 @@ public partial class LLChampionSpawn : ChampionSpawn
|
|||
base.OnAfterDelete();
|
||||
CannedEvilTimer.RemoveSpawn(this);
|
||||
}
|
||||
|
||||
[AfterDeserialization]
|
||||
private void AfterDeserialization() => CannedEvilTimer.AddSpawn(this);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue