using System;
using System.Reflection;
using System.Threading;
using Server.Items;
using Server.Tests.Maps;
using Server.Tests.Terrain;
namespace Server.Tests;
///
/// Shared server initialization logic for test fixtures.
/// Ensures the server is only initialized once across all test collections.
///
internal static class TestServerInitializer
{
private static bool _initialized;
private static readonly Lock _lock = new();
///
/// Initializes the test server. Safe to call multiple times - only initializes once.
///
public static void Initialize()
{
lock (_lock)
{
if (_initialized)
{
return;
}
Core.ApplicationAssembly = Assembly.GetExecutingAssembly();
// Load Configurations
ServerConfiguration.Load(true);
SyntheticWorld.LoadData();
// Load an empty assembly list into the resolver
ServerConfiguration.AssemblyDirectories.Add(Core.BaseDirectory);
AssemblyHandler.LoadAssemblies(["Server.dll"]);
Core.LoopContext = new EventLoopContext();
Core.Expansion = Expansion.EJ;
// Seed the loop clock as Main.cs does before the Configure sweep; otherwise Core.Now is
// DateTime.MinValue for the whole test host.
Core._now = DateTime.UtcNow;
// Timer wheel must exist before NetState.Configure(), which schedules a recurring
// sweep via Timer.DelayCall (matches production ordering in Main.cs: Timer.Init runs
// before AssemblyHandler.Invoke("Configure")).
Timer.Init(0);
// Configure networking (initializes RingSocketManager for tests)
Server.Network.NetState.Configure();
// Configure / Initialize
TestMapDefinitions.ConfigureTestMapDefinitions();
SyntheticWorld.StampTerrain();
// Configure the world
World.Configure();
// Load the world
World.Load();
World.ExitSerializationThreads();
DecayScheduler.Configure();
_initialized = true;
}
}
}