Skip to content
This repository has been archived by the owner on Oct 22, 2023. It is now read-only.

Commit

Permalink
Merge pull request #22 from proepkes/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
proepkes authored Jan 29, 2019
2 parents 0393469 + e5f656a commit aedd763
Show file tree
Hide file tree
Showing 70 changed files with 1,450 additions and 406 deletions.
68 changes: 38 additions & 30 deletions Engine/Client/CommandBuffer.cs
Original file line number Diff line number Diff line change
@@ -1,60 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using Lockstep.Core.Data;
using Lockstep.Core.Interfaces;

namespace Lockstep.Client.Implementations
{
public class CommandBuffer : ICommandBuffer
{
private readonly Dictionary<long, List<ICommand>> _commands = new Dictionary<long, List<ICommand>>();
/// <summary>
/// Mapping: FrameNumber -> Commands per player(Id)
/// </summary>
public Dictionary<uint, Dictionary<byte, List<ICommand>>> Buffer { get; } = new Dictionary<uint, Dictionary<byte, List<ICommand>>>(5000);

public event Action<long, ICommand> Inserted;
public uint LastInsertedFrame { get; private set; }

public long Count
public virtual void Insert(uint frameNumber, byte commanderId, ICommand[] commands)
{
get
{
lock (_commands)
lock (Buffer)
{
if (!Buffer.ContainsKey(frameNumber))
{
return _commands.LongCount();
Buffer.Add(frameNumber, new Dictionary<byte, List<ICommand>>(10)); //Initial size for 10 players
}
}
}

public long ItemIndex { get; private set; }
if (!Buffer[frameNumber].ContainsKey(commanderId))
{
Buffer[frameNumber].Add(commanderId, new List<ICommand>(5)); //Initial size of 5 commands per frame
}

//TODO: order by timestamp in case of multiple commands in the same frame => if commands intersect, the first one should win, requires !serverside! timestamp
//ordering is enough, validation should take place in the simulation(core)
Buffer[frameNumber][commanderId].AddRange(commands);

public long Remaining => Count - ItemIndex;
LastInsertedFrame = frameNumber;
}
}

public virtual void Insert(long frameNumber, ICommand command)
public Dictionary<byte, List<ICommand>> Get(uint frame)
{
lock (_commands)
lock (Buffer)
{
if (!_commands.ContainsKey(frameNumber))
//If no commands were inserted then return an empty list
if (!Buffer.ContainsKey(frame))
{
_commands.Add(frameNumber, new List<ICommand>(10));
Buffer.Add(frame, new Dictionary<byte, List<ICommand>>());
}

_commands[frameNumber].Add(command);

Inserted?.Invoke(frameNumber, command);
}
return Buffer[frame];
}
}

public ICommand[] GetNext()
{
lock (_commands)
public ICommand[] GetMany(uint frame)
{
lock (Buffer)
{
//If no commands were inserted then return an empty list
if (!_commands.ContainsKey(ItemIndex))
if (!Buffer.ContainsKey(frame))
{
_commands[ItemIndex] = new List<ICommand>();
Buffer.Add(frame, new Dictionary<byte, List<ICommand>>());
}

return _commands[ItemIndex++].ToArray();

}
return Buffer[frame].SelectMany(pair => pair.Value).ToArray();
}
}

}
}
80 changes: 56 additions & 24 deletions Engine/Client/NetworkCommandBuffer.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO;
using System.Linq;
using Lockstep.Client.Implementations;
using Lockstep.Client.Interfaces;
using Lockstep.Core.Data;
using Lockstep.Core.Data;
using Lockstep.Core.Interfaces;
using Lockstep.Network;
using Lockstep.Network.Messages;
using Lockstep.Network.Utils;
Expand All @@ -12,14 +14,17 @@ namespace Lockstep.Client
{
public class NetworkCommandBuffer : CommandBuffer
{
//TODO: refactor: don't receive meta information through commandbuffer
public event Action<Init> InitReceived;

private readonly INetwork _network;
private readonly ILogService _log;
private readonly IDictionary<ushort, Func<ISerializableCommand>> _commandFactories = new Dictionary<ushort, Func<ISerializableCommand>>();

public NetworkCommandBuffer(INetwork network)
public NetworkCommandBuffer(INetwork network, ILogService log)
{
_network = network;
_log = log;
_network.DataReceived += OnDataReceived;
}

Expand All @@ -33,20 +38,34 @@ public void RegisterCommand(Func<ISerializableCommand> commandFactory)
_commandFactories.Add(tag, commandFactory);
}

public override void Insert(long frameNumber, ICommand command)
{
if (command is ISerializableCommand serializable)
public override void Insert(uint frameNumber, byte commanderId, ICommand[] commands)
{
//Tell the server
var writer = new Serializer();
writer.Put((byte)MessageTag.Input);
writer.Put(commanderId);
writer.Put(frameNumber);
writer.Put(commands.Length);
foreach (var command in commands)
{
//Tell the server
var writer = new Serializer();
writer.Put((byte)MessageTag.Input);
writer.Put(frameNumber);
writer.Put(serializable.Tag);
serializable.Serialize(writer);

_network.Send(Compressor.Compress(writer));
if (command is ISerializableCommand serializable)
{
writer.Put(serializable.Tag);
serializable.Serialize(writer);
}
}
}

_network.Send(Compressor.Compress(writer));
}

public void Log(uint frameNumber)
{
var writer = new Serializer();
writer.Put((byte)MessageTag.Log);
writer.Put(frameNumber);

_network.Send(Compressor.Compress(writer));
}

private void OnDataReceived(byte[] data)
{
Expand All @@ -56,24 +75,37 @@ private void OnDataReceived(byte[] data)
var messageTag = (MessageTag)reader.GetByte();
switch (messageTag)
{
case MessageTag.Log:
var n = reader.GetUInt();
var count = Buffer.SelectMany(pair => pair.Value).SelectMany(pair => pair.Value).Count();
if (count > 0)
{
_log.Warn(count.ToString());
}
break;
case MessageTag.StartSimulation:
var init = new Init();
init.Deserialize(reader);
InitReceived?.Invoke(init);
break;
case MessageTag.Input:
var frameNumber = reader.GetLong();
var tag = reader.GetUShort();

if (_commandFactories.ContainsKey(tag))
var commanderId = reader.GetByte();
var frameNumber = reader.GetUInt();
var countCommands = reader.GetInt();
var commands = new ICommand[countCommands];
for (var i = 0; i < countCommands; i++)
{
var newCommand = _commandFactories[tag].Invoke();
newCommand.Deserialize(reader);

var tag = reader.GetUShort();

base.Insert(frameNumber, newCommand);
}
if (_commandFactories.ContainsKey(tag))
{
var newCommand = _commandFactories[tag].Invoke();
newCommand.Deserialize(reader);
commands[i] = newCommand;
}
}

base.Insert(frameNumber, commanderId, commands);
break;
}
}
Expand Down
Loading

0 comments on commit aedd763

Please sign in to comment.