diff --git a/src/Executables/Game/GameServer.cs b/src/Executables/Game/GameServer.cs index 33a3be74..e7b13c33 100644 --- a/src/Executables/Game/GameServer.cs +++ b/src/Executables/Game/GameServer.cs @@ -1,5 +1,6 @@ using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.Metrics; using System.Net; using System.Reflection; using Microsoft.Extensions.Logging; @@ -14,9 +15,6 @@ using QuantumCore.Core.Networking; using QuantumCore.Core.Utils; using QuantumCore.Extensions; -using QuantumCore.Game.Commands; -using QuantumCore.Game.Persistence; -using QuantumCore.Game.PlayerUtils; using QuantumCore.Game.Services; using QuantumCore.Networking; @@ -24,6 +22,8 @@ namespace QuantumCore.Game { public class GameServer : ServerBase, IGame, IGameServer { + public static readonly Meter Meter = new Meter("QuantumCore:Game"); + private readonly Histogram _serverTimes = Meter.CreateHistogram("TickTime", "ms"); private readonly HostingOptions _hostingOptions; private readonly ILogger _logger; private readonly PluginExecutor _pluginExecutor; @@ -78,6 +78,7 @@ public GameServer(IOptions hostingOptions, IPacketManager packet _dropProvider = dropProvider; _skillManager = skillManager; Instance = this; + Meter.CreateObservableGauge("Connections", () => Connections.Length); } private void Update(double elapsedTime) @@ -111,7 +112,7 @@ await Task.WhenAll( _skillManager.LoadAsync(stoppingToken) ); - + // Initialize session manager _sessionManager.Init(this); @@ -166,13 +167,15 @@ await _pluginExecutor.ExecutePlugins(_logger, private async ValueTask Tick() { var currentTicks = _gameTime.Elapsed.Ticks; - _accumulatedElapsedTime += TimeSpan.FromTicks(currentTicks - _previousTicks); + var elapsedTime = TimeSpan.FromTicks(currentTicks - _previousTicks); + _serverTimes.Record(elapsedTime.TotalMilliseconds); + _accumulatedElapsedTime += elapsedTime; _previousTicks = currentTicks; if (_accumulatedElapsedTime < _targetElapsedTime) { var sleepTime = (_targetElapsedTime - _accumulatedElapsedTime).TotalMilliseconds; - await Task.Delay((int)sleepTime).ConfigureAwait(false); + await Task.Delay((int) sleepTime).ConfigureAwait(false); return; } @@ -200,4 +203,4 @@ public void RegisterCommandNamespace(Type t) _commandManager.Register(t.Namespace!, t.Assembly); } } -} \ No newline at end of file +} diff --git a/src/Executables/Game/World/Map.cs b/src/Executables/Game/World/Map.cs index ae58fd04..ab91ba88 100644 --- a/src/Executables/Game/World/Map.cs +++ b/src/Executables/Game/World/Map.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using System.Diagnostics.Metrics; using System.Security.Cryptography; using EnumsNET; using Microsoft.Extensions.Logging; @@ -33,6 +34,7 @@ public class Map : IMap public IWorld World => _world; public IReadOnlyCollection Entities => _entities; + private readonly ObservableGauge _entityGauge; private readonly List _entities = new(); private readonly QuadTree _quadTree; private readonly List _spawnPoints = new(); @@ -70,6 +72,7 @@ public Map(IMonsterManager monsterManager, IAnimationManager animationManager, I Width = width; Height = height; _quadTree = new QuadTree((int) x, (int) y, (int) (width * MapUnit), (int) (height * MapUnit), 20); + _entityGauge = GameServer.Meter.CreateObservableGauge($"Map:{name}:EntityCount", () => Entities.Count); } public async Task Initialize() @@ -83,7 +86,7 @@ public async Task Initialize() _spawnPoints.AddRange(await _spawnPointProvider.GetSpawnPointsForMap(Name)); _logger.LogDebug("Loaded {SpawnPointsCount} spawn points for map {MapName}", _spawnPoints.Count, Name); - + // Populate map foreach (var spawnPoint in _spawnPoints) { @@ -298,34 +301,39 @@ private MonsterEntity SpawnMonster(uint id, SpawnPoint spawnPoint) if (monster.Proto.AiFlag.HasAnyFlags(EAiFlags.NoMove)) { - monster.PositionX = (int)(PositionX + baseX * SPAWN_POSITION_MULTIPLIER); - monster.PositionY = (int)(PositionY + baseY * SPAWN_POSITION_MULTIPLIER); - var compassDirection = (int)spawnPoint.Direction - 1; - - if (compassDirection < 0 || compassDirection > (int)Enum.GetValues().Last()) + monster.PositionX = (int) (PositionX + baseX * SPAWN_POSITION_MULTIPLIER); + monster.PositionY = (int) (PositionY + baseY * SPAWN_POSITION_MULTIPLIER); + var compassDirection = (int) spawnPoint.Direction - 1; + + if (compassDirection < 0 || compassDirection > (int) Enum.GetValues().Last()) { - compassDirection = (int)ESpawnPointDirection.Random; + compassDirection = (int) ESpawnPointDirection.Random; } + var rotation = SPAWN_ROTATION_SLICE_DEGREES * compassDirection; monster.Rotation = rotation; } else { - monster.PositionX = (int) PositionX + (baseX + RandomNumberGenerator.GetInt32(-SPAWN_BASE_OFFSET, SPAWN_BASE_OFFSET)) * SPAWN_POSITION_MULTIPLIER; - monster.PositionY = (int) PositionY + (baseY + RandomNumberGenerator.GetInt32(-SPAWN_BASE_OFFSET, SPAWN_BASE_OFFSET)) * SPAWN_POSITION_MULTIPLIER; + monster.PositionX = (int) PositionX + + (baseX + RandomNumberGenerator.GetInt32(-SPAWN_BASE_OFFSET, SPAWN_BASE_OFFSET)) * + SPAWN_POSITION_MULTIPLIER; + monster.PositionY = (int) PositionY + + (baseY + RandomNumberGenerator.GetInt32(-SPAWN_BASE_OFFSET, SPAWN_BASE_OFFSET)) * + SPAWN_POSITION_MULTIPLIER; } if (monster.Rotation == 0) { monster.Rotation = RandomNumberGenerator.GetInt32(0, 360); } - + EventSystem.EnqueueEvent(() => { _world.SpawnEntity(monster); return 0; }, spawnPoint.RespawnTime * 1000); - + return monster; } @@ -362,7 +370,8 @@ public void SpawnEntity(IEntity entity) /// public void AddGroundItem(ItemInstance item, int x, int y, uint amount = 0, string? ownerName = null) { - var groundItem = new GroundItem(_animationManager, _world.GenerateVid(), item, amount, ownerName) { + var groundItem = new GroundItem(_animationManager, _world.GenerateVid(), item, amount, ownerName) + { PositionX = x, PositionY = y }; diff --git a/src/Executables/Game/World/World.cs b/src/Executables/Game/World/World.cs index 40ed8183..cacce5ba 100644 --- a/src/Executables/Game/World/World.cs +++ b/src/Executables/Game/World/World.cs @@ -287,6 +287,7 @@ public void SpawnEntity(IEntity e) _pluginExecutor.ExecutePlugins(_logger, x => x.OnPreCreatedAsync()).Wait(); map.SpawnEntity(e); + _pluginExecutor.ExecutePlugins(_logger, x => x.OnPostCreatedAsync()).Wait(); }