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