Implement LobbyServer

This commit is contained in:
2019-05-03 20:24:02 +02:00
parent e3a7e37411
commit ed1771664b
10 changed files with 306 additions and 1 deletions

View File

@@ -0,0 +1,19 @@
using System.Collections.Generic;
namespace LobbyServer
{
class ChatManager
{
private List<Message> _messages;
public IReadOnlyList<Message> Messages => _messages.AsReadOnly();
public ChatManager()
{
_messages = new List<Message>();
}
public void Add(Message message)
{
_messages.Add(message);
}
}
}

11
LobbyServer/Command.cs Normal file
View File

@@ -0,0 +1,11 @@
namespace LobbyServer
{
enum Command
{
ChatAdd,
ChatRequest,
ScoreAdd,
ScoreRequest,
Invalid
}
}

View File

@@ -0,0 +1,19 @@
namespace LobbyServer
{
class CommandPacket
{
public Command Command { get; }
public string Content { get; }
public CommandPacket(Command command, string content)
{
Command = command;
Content = content;
}
public override string ToString()
{
return $"{Command.ToString()}\n{Content}";
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Net.Sockets;
using System.Text;
namespace LobbyServer
{
class CommandStream
{
private NetworkStream _stream;
public CommandStream(NetworkStream stream)
{
_stream = stream;
}
public CommandPacket Receive()
{
// Length
byte[] buffer = new byte[4];
_stream.Read(buffer, 0, buffer.Length);
uint length = BitConverter.ToUInt32(buffer, 0);
// Data
buffer = new byte[length];
_stream.Read(buffer, 0, buffer.Length);
string[] packet = Encoding.UTF8.GetString(buffer).Split('\n');
if (!Enum.TryParse(packet[0], true, out Command command))
{
command = Command.Invalid;
}
return new CommandPacket(command, packet[1]);
}
public void Send(CommandPacket command)
{
string packet = command.ToString();
byte[] data = Encoding.UTF8.GetBytes(packet);
_stream.Write(BitConverter.GetBytes((uint)data.Length), 0, 4);
_stream.Write(data, 0, data.Length);
}
}
}

108
LobbyServer/LobbyServer.cs Normal file
View File

@@ -0,0 +1,108 @@
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System;
namespace LobbyServer
{
class LobbyServer
{
public static LobbyServer Instance { get; private set; }
public ChatManager ChatManager { get; }
public ScoresManager ScoresManager { get; }
public LobbyServer()
{
Instance = this;
Console.WriteLine("Starting LobbyServer...");
ChatManager = new ChatManager();
ScoresManager = new ScoresManager();
Console.WriteLine("LobbyServer started");
}
public void Start()
{
var listener = new TcpListener(IPAddress.Any, 1409);
listener.Start();
while (true)
{
Console.WriteLine("Waiting client...");
using (var client = listener.AcceptTcpClient())
{
ClientLoop(client);
}
}
}
public void ClientLoop(TcpClient client)
{
Console.WriteLine($"Client connected: {client.Client.RemoteEndPoint}");
var stream = new CommandStream(client.GetStream());
while (true)
{
try
{
var packet = stream.Receive();
switch (packet.Command)
{
case Command.ChatAdd:
ChatAdd(packet);
break;
case Command.ChatRequest:
ChatRequest(stream, packet);
break;
case Command.ScoreAdd:
ScoreAdd(packet);
break;
case Command.ScoreRequest:
ScoreRequest(stream, packet);
break;
case Command.Invalid:
throw new InvalidOperationException("Received invalid command");
}
}
catch (Exception e)
{
Console.WriteLine($"Client disconnected: {e.Message}");
}
}
}
private void ChatAdd(CommandPacket packet)
{
var message = new Message(packet.Content);
ChatManager.Add(message);
}
private void ChatRequest(CommandStream stream, CommandPacket packet)
{
var messages = ChatManager.Messages.Reverse().Take(10).Reverse().Select(x => x.ToString());
string data = string.Join('@', messages);
stream.Send(new CommandPacket(Command.ChatRequest, data));
}
private void ScoreAdd(CommandPacket packet)
{
var score = new ScoreEntry(packet.Content);
ScoresManager.Add(score);
}
private void ScoreRequest(CommandStream stream, CommandPacket packet)
{
var scores = ScoresManager.Scores.Take(10).Select(x => x.ToString());
string data = string.Join('@', scores);
stream.Send(new CommandPacket(Command.ScoreRequest, data));
}
}
}

View File

@@ -5,4 +5,8 @@
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>
</Project>

31
LobbyServer/Message.cs Normal file
View File

@@ -0,0 +1,31 @@
using System.Linq;
using System;
namespace LobbyServer
{
class Message
{
public string SendDate { get; }
public string Sender { get; }
public string Content { get; }
public Message(string sendDate, string sender, string content)
{
SendDate = sendDate;
Sender = sender;
Content = content;
}
public Message(string serialized)
{
var split = serialized.Split(';');
SendDate = split[0];
Sender = split[1];
Content = string.Join(';', split.Skip(2));
}
public override string ToString()
{
return $"{SendDate};{Sender};{Content}";
}
}
}

View File

@@ -6,7 +6,7 @@ namespace LobbyServer
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
new LobbyServer().Start();
}
}
}

26
LobbyServer/ScoreEntry.cs Normal file
View File

@@ -0,0 +1,26 @@
namespace LobbyServer
{
public class ScoreEntry
{
public string Pseudo { get; }
public int Score { get; }
public ScoreEntry(string pseudo, int score)
{
Pseudo = pseudo;
Score = score;
}
public ScoreEntry(string serialized)
{
var split = serialized.Split(';');
Pseudo = split[0];
Score = int.Parse(split[1]);
}
public override string ToString()
{
return $"{Pseudo};{Score}";
}
}
}

View File

@@ -0,0 +1,40 @@
using System.Linq;
using System;
using System.IO;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace LobbyServer
{
class ScoresManager
{
public const string FileName = "scores.json";
public string FilePath => Path.Combine(Environment.CurrentDirectory, FileName);
private List<ScoreEntry> _scores;
public IReadOnlyList<ScoreEntry> Scores => _scores.AsReadOnly();
public ScoresManager()
{
if (File.Exists("scores.json"))
{
_scores = JsonConvert.DeserializeObject<List<ScoreEntry>>(File.ReadAllText(FilePath));
}
else
{
_scores = new List<ScoreEntry>();
}
}
public void Add(ScoreEntry entry)
{
_scores.Add(entry);
_scores.OrderByDescending(x => x.Score);
}
public void Save()
{
File.WriteAllText(FilePath, JsonConvert.SerializeObject(_scores));
}
}
}