diff --git a/TrueCraft.API/Server/IEventScheduler.cs b/TrueCraft.API/Server/IEventScheduler.cs index 12706c5..8fe83ce 100644 --- a/TrueCraft.API/Server/IEventScheduler.cs +++ b/TrueCraft.API/Server/IEventScheduler.cs @@ -10,7 +10,7 @@ namespace TrueCraft.API.Server /// The subject of the event. If the subject is disposed, the event is cancelled. /// When to trigger the event. /// The event to trigger. - void ScheduleEvent(IEventSubject subject, DateTime when, Action action); + void ScheduleEvent(IEventSubject subject, TimeSpan when, Action action); /// /// Triggers all pending scheduled events whose scheduled time has transpired. /// diff --git a/TrueCraft.Core/Logic/Blocks/CropsBlock.cs b/TrueCraft.Core/Logic/Blocks/CropsBlock.cs index 771c97d..66e9736 100644 --- a/TrueCraft.Core/Logic/Blocks/CropsBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/CropsBlock.cs @@ -50,7 +50,7 @@ namespace TrueCraft.Core.Logic.Blocks { var chunk = world.FindChunk(coords); server.Scheduler.ScheduleEvent( - chunk, DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(30, 60)), + chunk, TimeSpan.FromSeconds(MathHelper.Random.Next(30, 60)), (_server) => GrowBlock(_server, world, coords)); } } @@ -67,14 +67,14 @@ namespace TrueCraft.Core.Logic.Blocks public override void BlockPlaced(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user) { var chunk = world.FindChunk(descriptor.Coordinates); - user.Server.Scheduler.ScheduleEvent(chunk, DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(30, 60)), + user.Server.Scheduler.ScheduleEvent(chunk, TimeSpan.FromSeconds(MathHelper.Random.Next(30, 60)), (server) => GrowBlock(server, world, descriptor.Coordinates + MathHelper.BlockFaceToCoordinates(face))); } public override void BlockLoadedFromChunk(Coordinates3D coords, IMultiplayerServer server, IWorld world) { var chunk = world.FindChunk(coords); - server.Scheduler.ScheduleEvent(chunk, DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(30, 60)), + server.Scheduler.ScheduleEvent(chunk, TimeSpan.FromSeconds(MathHelper.Random.Next(30, 60)), (s) => GrowBlock(s, world, coords)); } } diff --git a/TrueCraft.Core/Logic/Blocks/FarmlandBlock.cs b/TrueCraft.Core/Logic/Blocks/FarmlandBlock.cs index 5dc9c35..6b32317 100644 --- a/TrueCraft.Core/Logic/Blocks/FarmlandBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/FarmlandBlock.cs @@ -87,7 +87,7 @@ namespace TrueCraft.Core.Logic.Blocks } var chunk = world.FindChunk(coords); server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(UpdateIntervalSeconds), + TimeSpan.FromSeconds(UpdateIntervalSeconds), _server => HydrationCheckEvent(_server, coords, world)); } @@ -99,7 +99,7 @@ namespace TrueCraft.Core.Logic.Blocks } var chunk = world.FindChunk(descriptor.Coordinates); user.Server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(UpdateIntervalSeconds), + TimeSpan.FromSeconds(UpdateIntervalSeconds), server => HydrationCheckEvent(server, descriptor.Coordinates, world)); } @@ -107,7 +107,7 @@ namespace TrueCraft.Core.Logic.Blocks { var chunk = world.FindChunk(coords); server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(UpdateIntervalSeconds), + TimeSpan.FromSeconds(UpdateIntervalSeconds), s => HydrationCheckEvent(s, coords, world)); } } diff --git a/TrueCraft.Core/Logic/Blocks/FluidBlock.cs b/TrueCraft.Core/Logic/Blocks/FluidBlock.cs index d751d14..b41087c 100644 --- a/TrueCraft.Core/Logic/Blocks/FluidBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/FluidBlock.cs @@ -71,7 +71,7 @@ namespace TrueCraft.Core.Logic.Blocks { var chunk = world.FindChunk(coords); server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(SecondsBetweenUpdates), (_server) => + TimeSpan.FromSeconds(SecondsBetweenUpdates), (_server) => AutomataUpdate(_server, world, coords)); } @@ -111,7 +111,7 @@ namespace TrueCraft.Core.Logic.Blocks { var chunk = world.FindChunk(coords); server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(SecondsBetweenUpdates), (_server) => + TimeSpan.FromSeconds(SecondsBetweenUpdates), (_server) => AutomataUpdate(_server, world, coords)); } } @@ -166,7 +166,7 @@ namespace TrueCraft.Core.Logic.Blocks world.SetMetadata(target.TargetBlock, target.Level); var chunk = world.FindChunk(target.TargetBlock); server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(SecondsBetweenUpdates), + TimeSpan.FromSeconds(SecondsBetweenUpdates), s => AutomataUpdate(s, world, target.TargetBlock)); } diff --git a/TrueCraft.Core/Logic/Blocks/GrassBlock.cs b/TrueCraft.Core/Logic/Blocks/GrassBlock.cs index 0251bb0..794b4cc 100644 --- a/TrueCraft.Core/Logic/Blocks/GrassBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/GrassBlock.cs @@ -76,7 +76,7 @@ namespace TrueCraft.Core.Logic.Blocks { var chunk = world.FindChunk(descriptor.Coordinates, generate: false); server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(MinDecayTime, MaxDecayTime)), s => + TimeSpan.FromSeconds(MathHelper.Random.Next(MinDecayTime, MaxDecayTime)), s => { ScheduledUpdate(world, descriptor.Coordinates); }); @@ -118,7 +118,7 @@ namespace TrueCraft.Core.Logic.Blocks } world.SetBlockID(candidate, GrassBlock.BlockID); server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(MinGrowthTime, MaxGrowthTime)), + TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthTime, MaxGrowthTime)), s => TrySpread(candidate, world, server)); break; } @@ -129,7 +129,7 @@ namespace TrueCraft.Core.Logic.Blocks { var chunk = world.FindChunk(descriptor.Coordinates); user.Server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(MinGrowthTime, MaxGrowthTime)), + TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthTime, MaxGrowthTime)), s => TrySpread(descriptor.Coordinates, world, user.Server)); } @@ -137,7 +137,7 @@ namespace TrueCraft.Core.Logic.Blocks { var chunk = world.FindChunk(coords); server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(MinGrowthTime, MaxGrowthTime)), + TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthTime, MaxGrowthTime)), s => TrySpread(coords, world, server)); } } diff --git a/TrueCraft.Core/Logic/Blocks/SugarcaneBlock.cs b/TrueCraft.Core/Logic/Blocks/SugarcaneBlock.cs index c96037b..c05ddd9 100644 --- a/TrueCraft.Core/Logic/Blocks/SugarcaneBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/SugarcaneBlock.cs @@ -12,6 +12,7 @@ namespace TrueCraft.Core.Logic.Blocks { public static readonly int MinGrowthSeconds = 30; public static readonly int MaxGrowthSeconds = 120; + public static readonly int MaxGrowHeight = 3; public static readonly byte BlockID = 0x53; @@ -90,12 +91,12 @@ namespace TrueCraft.Core.Logic.Blocks return; // Find current height of stalk int height = 0; - for (int y = -3; y <= 3; y++) + for (int y = -MaxGrowHeight; y <= MaxGrowHeight; y++) { if (world.GetBlockID(coords + (Coordinates3D.Down * y)) == BlockID) height++; } - if (height < 3) + if (height < MaxGrowHeight) { var meta = world.GetMetadata(coords); meta++; @@ -103,15 +104,18 @@ namespace TrueCraft.Core.Logic.Blocks var chunk = world.FindChunk(coords); if (meta == 15) { - world.SetBlockID(coords + Coordinates3D.Up, BlockID); - server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)), - (_server) => TryGrowth(_server, coords + Coordinates3D.Up, world)); + if (world.GetBlockID(coords + Coordinates3D.Up) == 0) + { + world.SetBlockID(coords + Coordinates3D.Up, BlockID); + server.Scheduler.ScheduleEvent(chunk, + TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)), + (_server) => TryGrowth(_server, coords + Coordinates3D.Up, world)); + } } else { server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)), + TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)), (_server) => TryGrowth(_server, coords, world)); } } @@ -121,7 +125,7 @@ namespace TrueCraft.Core.Logic.Blocks { var chunk = world.FindChunk(descriptor.Coordinates); user.Server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)), + TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)), (server) => TryGrowth(server, descriptor.Coordinates, world)); } @@ -129,7 +133,7 @@ namespace TrueCraft.Core.Logic.Blocks { var chunk = world.FindChunk(coords); server.Scheduler.ScheduleEvent(chunk, - DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)), + TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)), s => TryGrowth(s, coords, world)); } } diff --git a/TrueCraft.Profiling/Profiler.cs b/TrueCraft.Profiling/Profiler.cs new file mode 100644 index 0000000..426d52a --- /dev/null +++ b/TrueCraft.Profiling/Profiler.cs @@ -0,0 +1,99 @@ +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Linq; + +namespace TrueCraft.Profiling +{ + public static class Profiler + { + static Profiler() + { + Stopwatch = new Stopwatch(); + EnabledBuckets = new List(); + ActiveTimers = new Stack(); + Stopwatch.Start(); + } + + private static Stopwatch Stopwatch { get; set; } + private static List EnabledBuckets { get; set; } + private static Stack ActiveTimers { get; set; } + + private struct ActiveTimer + { + public long Started, Finished; + public string Bucket; + } + + [Conditional("DEBUG")] + public static void EnableBucket(string bucket) + { + EnabledBuckets.Add(bucket); + } + + [Conditional("DEBUG")] + public static void DisableBucket(string bucket) + { + EnabledBuckets.Remove(bucket); + } + + [Conditional("DEBUG")] + public static void Start(string bucket) + { + ActiveTimers.Push(new ActiveTimer + { + Started = Stopwatch.ElapsedMilliseconds, + Finished = -1, + Bucket = bucket + }); + } + + [Conditional("DEBUG")] + public static void Done() + { + if (ActiveTimers.Count > 0) + { + var timer = ActiveTimers.Pop(); + timer.Finished = Stopwatch.ElapsedMilliseconds; + for (int i = 0; i < EnabledBuckets.Count; i++) + { + if (Match(EnabledBuckets[i], timer.Bucket)) + { + Console.WriteLine("{0} took {1}ms", timer.Bucket, timer.Finished - timer.Started); + break; + } + } + } + } + + private static bool Match(string mask, string value) + { + if (value == null) + value = string.Empty; + int i = 0; + int j = 0; + for (; j < value.Length && i < mask.Length; j++) + { + if (mask[i] == '?') + i++; + else if (mask[i] == '*') + { + i++; + if (i >= mask.Length) + return true; + while (++j < value.Length && value[j] != mask[i]) ; + if (j-- == value.Length) + return false; + } + else + { + if (char.ToUpper(mask[i]) != char.ToUpper(value[j])) + return false; + i++; + } + } + return i == mask.Length && j == value.Length; + } + + } +} \ No newline at end of file diff --git a/TrueCraft.Profiling/Properties/AssemblyInfo.cs b/TrueCraft.Profiling/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..735ca33 --- /dev/null +++ b/TrueCraft.Profiling/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("TrueCraft.Profiling")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("sircmpwn")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/TrueCraft.Profiling/TrueCraft.Profiling.csproj b/TrueCraft.Profiling/TrueCraft.Profiling.csproj new file mode 100644 index 0000000..88436ea --- /dev/null +++ b/TrueCraft.Profiling/TrueCraft.Profiling.csproj @@ -0,0 +1,39 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {BCA0E139-CF47-43B3-9DC9-D4611C0A2AAD} + Library + TrueCraft.Profiling + TrueCraft.Profiling + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + true + bin\Release + prompt + 4 + false + + + + + + + + + + \ No newline at end of file diff --git a/TrueCraft.sln b/TrueCraft.sln index 5aa3fe6..6fb1a8e 100644 --- a/TrueCraft.sln +++ b/TrueCraft.sln @@ -17,6 +17,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{6756B61E-5 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrueCraft.Core.Test", "TrueCraft.Core.Test\TrueCraft.Core.Test.csproj", "{BCFDCD93-C23E-49E6-9767-A887B3C2A709}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrueCraft.Profiling", "TrueCraft.Profiling\TrueCraft.Profiling.csproj", "{BCA0E139-CF47-43B3-9DC9-D4611C0A2AAD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -35,6 +37,10 @@ Global {A6516869-A2FB-4E31-85C8-2285490CB32C}.Debug|Any CPU.Build.0 = Debug|Any CPU {A6516869-A2FB-4E31-85C8-2285490CB32C}.Release|Any CPU.ActiveCfg = Release|Any CPU {A6516869-A2FB-4E31-85C8-2285490CB32C}.Release|Any CPU.Build.0 = Release|Any CPU + {BCA0E139-CF47-43B3-9DC9-D4611C0A2AAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BCA0E139-CF47-43B3-9DC9-D4611C0A2AAD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BCA0E139-CF47-43B3-9DC9-D4611C0A2AAD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BCA0E139-CF47-43B3-9DC9-D4611C0A2AAD}.Release|Any CPU.Build.0 = Release|Any CPU {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Debug|Any CPU.Build.0 = Debug|Any CPU {BCFDCD93-C23E-49E6-9767-A887B3C2A709}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/TrueCraft/EventScheduler.cs b/TrueCraft/EventScheduler.cs index 3663a13..93f19fc 100644 --- a/TrueCraft/EventScheduler.cs +++ b/TrueCraft/EventScheduler.cs @@ -2,6 +2,8 @@ using TrueCraft.API.Server; using System.Collections.Generic; using TrueCraft.API; +using System.Diagnostics; +using TrueCraft.Profiling; namespace TrueCraft { @@ -11,18 +13,22 @@ namespace TrueCraft private readonly object EventLock = new object(); private IMultiplayerServer Server { get; set; } private HashSet Subjects { get; set; } + private Stopwatch Stopwatch { get; set; } public EventScheduler(IMultiplayerServer server) { Events = new List(); Server = server; Subjects = new HashSet(); + Stopwatch = new Stopwatch(); + Stopwatch.Start(); } - public void ScheduleEvent(IEventSubject subject, DateTime when, Action action) + public void ScheduleEvent(IEventSubject subject, TimeSpan when, Action action) { lock (EventLock) { + long _when = Stopwatch.ElapsedTicks + when.Ticks; if (!Subjects.Contains(subject)) { Subjects.Add(subject); @@ -31,10 +37,15 @@ namespace TrueCraft int i; for (i = 0; i < Events.Count; i++) { - if (Events[i].When > when) + if (Events[i].When > _when) break; } - Events.Insert(i, new ScheduledEvent { Subject = subject, When = when, Action = action }); + Events.Insert(i, new ScheduledEvent + { + Subject = subject, + When = _when, + Action = action + }); } } @@ -57,9 +68,10 @@ namespace TrueCraft public void Update() { + Profiler.Start("scheduler"); lock (EventLock) { - var start = DateTime.UtcNow; + var start = Stopwatch.ElapsedTicks; for (int i = 0; i < Events.Count; i++) { var e = Events[i]; @@ -73,11 +85,12 @@ namespace TrueCraft break; // List is sorted, we can exit early } } + Profiler.Done(); } private struct ScheduledEvent { - public DateTime When; + public long When; public Action Action; public IEventSubject Subject; } diff --git a/TrueCraft/Handlers/LoginHandlers.cs b/TrueCraft/Handlers/LoginHandlers.cs index 209e001..ab65c80 100644 --- a/TrueCraft/Handlers/LoginHandlers.cs +++ b/TrueCraft/Handlers/LoginHandlers.cs @@ -70,8 +70,8 @@ namespace TrueCraft.Handlers var entityManager = server.GetEntityManagerForWorld(remoteClient.World); entityManager.SpawnEntity(remoteClient.Entity); entityManager.SendEntitiesToClient(remoteClient); - server.Scheduler.ScheduleEvent(remoteClient, DateTime.UtcNow.AddSeconds(10), remoteClient.SendKeepAlive); - server.Scheduler.ScheduleEvent(remoteClient, DateTime.UtcNow.AddSeconds(1), remoteClient.ExpandChunkRadius); + server.Scheduler.ScheduleEvent(remoteClient, TimeSpan.FromSeconds(10), remoteClient.SendKeepAlive); + server.Scheduler.ScheduleEvent(remoteClient, TimeSpan.FromSeconds(1), remoteClient.ExpandChunkRadius); if (!string.IsNullOrEmpty(Program.ServerConfiguration.MOTD)) remoteClient.SendMessage(Program.ServerConfiguration.MOTD); diff --git a/TrueCraft/MultiplayerServer.cs b/TrueCraft/MultiplayerServer.cs index 61fedd8..4af7dce 100644 --- a/TrueCraft/MultiplayerServer.cs +++ b/TrueCraft/MultiplayerServer.cs @@ -20,6 +20,7 @@ using TrueCraft.Core.World; using System.Threading.Tasks; using System.Diagnostics; using System.Collections.Concurrent; +using TrueCraft.Profiling; namespace TrueCraft { @@ -43,6 +44,8 @@ namespace TrueCraft public bool EnableClientLogging { get; set; } public IPEndPoint EndPoint { get; private set; } + private static readonly int MillisecondsPerTick = 1000 / 20; + private bool _BlockUpdatesEnabled = true; private struct BlockUpdate @@ -131,7 +134,7 @@ namespace TrueCraft AcceptClient(this, args); Log(LogCategory.Notice, "Running TrueCraft server on {0}", EndPoint); - EnvironmentWorker.Change(1000 / 20, 0); + EnvironmentWorker.Change(MillisecondsPerTick, 0); if(Program.ServerConfiguration.Query) QueryProtocol.Start(); } @@ -367,11 +370,19 @@ namespace TrueCraft { if (ShuttingDown) return; + + Profiler.Start("environment"); + Scheduler.Update(); + + Profiler.Start("environment.entities"); foreach (var manager in EntityManagers) { manager.Update(); } + Profiler.Done(); + + Profiler.Start("environment.lighting"); foreach (var lighter in WorldLighters) { int attempts = 500; @@ -379,10 +390,17 @@ namespace TrueCraft { } } + Profiler.Done(); + + Profiler.Start("environment.chunks"); Tuple t; if (ChunksToSchedule.TryTake(out t)) ScheduleUpdatesForChunk(t.Item1, t.Item2); - EnvironmentWorker.Change(1000 / 20, 0); + Profiler.Done(); + + Profiler.Done(); + + EnvironmentWorker.Change(MillisecondsPerTick, 0); } public bool PlayerIsWhitelisted(string client) diff --git a/TrueCraft/Program.cs b/TrueCraft/Program.cs index 08d3f58..67994a0 100644 --- a/TrueCraft/Program.cs +++ b/TrueCraft/Program.cs @@ -11,6 +11,7 @@ using TrueCraft.API.World; using System; using TrueCraft.API; using YamlDotNet.Serialization; +using TrueCraft.Profiling; namespace TrueCraft { @@ -33,6 +34,15 @@ namespace TrueCraft ServerConfiguration = Configuration.LoadConfiguration("config.yaml"); + var buckets = ServerConfiguration.Debug?.Profiler?.Buckets?.Split(','); + if (buckets != null) + { + foreach (var bucket in buckets) + { + Profiler.EnableBucket(bucket.Trim()); + } + } + if (ServerConfiguration.Debug.DeleteWorldOnStartup) { if (Directory.Exists("world")) diff --git a/TrueCraft/RemoteClient.cs b/TrueCraft/RemoteClient.cs index 0b62463..d826926 100644 --- a/TrueCraft/RemoteClient.cs +++ b/TrueCraft/RemoteClient.cs @@ -392,7 +392,7 @@ namespace TrueCraft { ChunkRadius++; UpdateChunks(); - server.Scheduler.ScheduleEvent(this, DateTime.UtcNow.AddSeconds(1), ExpandChunkRadius); + server.Scheduler.ScheduleEvent(this, TimeSpan.FromSeconds(1), ExpandChunkRadius); } }); } @@ -400,7 +400,7 @@ namespace TrueCraft internal void SendKeepAlive(IMultiplayerServer server) { QueuePacket(new KeepAlivePacket()); - server.Scheduler.ScheduleEvent(this, DateTime.UtcNow.AddSeconds(1), SendKeepAlive); + server.Scheduler.ScheduleEvent(this, TimeSpan.FromSeconds(1), SendKeepAlive); } internal void UpdateChunks() diff --git a/TrueCraft/ServerConfiguration.cs b/TrueCraft/ServerConfiguration.cs index b09cf29..d2160e8 100644 --- a/TrueCraft/ServerConfiguration.cs +++ b/TrueCraft/ServerConfiguration.cs @@ -7,6 +7,17 @@ namespace TrueCraft { public class DebugConfiguration { + public class ProfilerConfiguration + { + public ProfilerConfiguration() + { + Buckets = ""; + } + + [YamlMember(Alias = "buckets")] + public string Buckets { get; set; } + } + public DebugConfiguration() { DeleteWorldOnStartup = false; @@ -18,6 +29,9 @@ namespace TrueCraft [YamlMember(Alias = "deletePlayersOnStartup")] public bool DeletePlayersOnStartup { get; set; } + + [YamlMember(Alias = "profiler")] + public ProfilerConfiguration Profiler { get; set; } } public ServerConfiguration() diff --git a/TrueCraft/TrueCraft.csproj b/TrueCraft/TrueCraft.csproj index f9dabd4..6199a9b 100644 --- a/TrueCraft/TrueCraft.csproj +++ b/TrueCraft/TrueCraft.csproj @@ -17,6 +17,7 @@ 4 true false + DEBUG; true @@ -29,7 +30,7 @@ ..\lib\Ionic.Zip.Reduced.dll - ..\packages\YamlDotNet.3.6.1\lib\net35\YamlDotNet.dll + ..\packages\YamlDotNet.3.7.0\lib\net35\YamlDotNet.dll @@ -74,11 +75,15 @@ {4488498D-976D-4DA3-BF72-109531AF0488} fNbt - - - + + {BCA0E139-CF47-43B3-9DC9-D4611C0A2AAD} + TrueCraft.Profiling + + + + \ No newline at end of file diff --git a/TrueCraft/packages.config b/TrueCraft/packages.config index a044efe..0a615c3 100644 --- a/TrueCraft/packages.config +++ b/TrueCraft/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file