Added PacketBuffer, Optional and ConnectionList

This commit is contained in:
Sofia 2017-11-22 20:39:24 +02:00
parent f1fe29c2f8
commit 7f2fc019d6
17 changed files with 377 additions and 179 deletions

View File

@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{2B5DC68F-C753-49CB-AD01-8E42EDE95B43}</ProjectGuid> <ProjectGuid>{0DD2D816-33C3-432E-9705-2E0D0077835C}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<OutputPath>.mono\temp\bin\$(Configuration)</OutputPath> <OutputPath>.mono\temp\bin\$(Configuration)</OutputPath>
<RootNamespace>TicTacToe</RootNamespace> <RootNamespace>TicTacToe</RootNamespace>
@ -50,12 +50,15 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="scripts\Client.cs" /> <Compile Include="scripts\net\Client.cs" />
<Compile Include="scripts\Connection.cs" /> <Compile Include="scripts\net\ConnectionList.cs" />
<Compile Include="scripts\net\Connection.cs" />
<Compile Include="scripts\MainMenu.cs" /> <Compile Include="scripts\MainMenu.cs" />
<Compile Include="scripts\Net.cs" /> <Compile Include="scripts\net\Net.cs" />
<Compile Include="scripts\Peer.cs" /> <Compile Include="scripts\net\packethandling\PacketBuffer.cs" />
<Compile Include="scripts\Server.cs" /> <Compile Include="scripts\net\Peer.cs" />
<Compile Include="scripts\net\Server.cs" />
<Compile Include="scripts\util\Optional.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View File

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012 # Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TicTacToe", "TicTacToe.csproj", "{2B5DC68F-C753-49CB-AD01-8E42EDE95B43}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TicTacToe", "TicTacToe.csproj", "{0DD2D816-33C3-432E-9705-2E0D0077835C}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -9,11 +9,11 @@ Global
Tools|Any CPU = Tools|Any CPU Tools|Any CPU = Tools|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2B5DC68F-C753-49CB-AD01-8E42EDE95B43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0DD2D816-33C3-432E-9705-2E0D0077835C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B5DC68F-C753-49CB-AD01-8E42EDE95B43}.Debug|Any CPU.Build.0 = Debug|Any CPU {0DD2D816-33C3-432E-9705-2E0D0077835C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B5DC68F-C753-49CB-AD01-8E42EDE95B43}.Release|Any CPU.ActiveCfg = Release|Any CPU {0DD2D816-33C3-432E-9705-2E0D0077835C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B5DC68F-C753-49CB-AD01-8E42EDE95B43}.Release|Any CPU.Build.0 = Release|Any CPU {0DD2D816-33C3-432E-9705-2E0D0077835C}.Release|Any CPU.Build.0 = Release|Any CPU
{2B5DC68F-C753-49CB-AD01-8E42EDE95B43}.Tools|Any CPU.ActiveCfg = Tools|Any CPU {0DD2D816-33C3-432E-9705-2E0D0077835C}.Tools|Any CPU.ActiveCfg = Tools|Any CPU
{2B5DC68F-C753-49CB-AD01-8E42EDE95B43}.Tools|Any CPU.Build.0 = Tools|Any CPU {0DD2D816-33C3-432E-9705-2E0D0077835C}.Tools|Any CPU.Build.0 = Tools|Any CPU
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -16,7 +16,7 @@ config/icon="res://icon.png"
[autoload] [autoload]
Net="*res://scripts/Net.cs" Net="*res://scripts/net/Net.cs"
[gdnative] [gdnative]

View File

@ -1,34 +0,0 @@
using Godot;
public class Client : Peer {
private PacketPeerUDP PacketPeer;
private Connection ServerConn;
private byte[] TempBuffer = {1};
private float Timer = 0;
public Client(PacketPeerUDP packetPeer) : base(packetPeer) {
PacketPeer = packetPeer;
}
public override void Initialize(string address, int port) {
GD.print("Start client.");
GD.print("Starting to send stuff to " + address + ":" + port);
ServerConn = new Connection(address, port);
StartListening(port, "*");
}
public override void ReceivePacket(byte[] buffer, string address, int port) {
GD.print("Client received stuff from " + address + " : " + port + " :");
}
public override void Update(float delta) {
Timer += delta;
if (Timer < 1) { return; }
Timer = 0;
GD.print("Update client.");
SendBuffer(TempBuffer, ServerConn);
}
}

View File

@ -1,13 +0,0 @@

public class Connection {
private static int IDCounter = 0;
public readonly int ID = IDCounter++;
public string Address;
public int Port;
public Connection(string address, int port) {
Address = address;
Port = port;
}
}

View File

@ -1,5 +1,7 @@
using Godot; using Godot;
using System; using System;
using Network;
using Util;
public class MainMenu : Panel { public class MainMenu : Panel {

View File

@ -1,38 +0,0 @@
using Godot;
using System;
public class Net : Node {
private PacketPeerUDP PacketPeer;
private Client Client;
private Server Server;
public bool IsClient { get { return Client != null; } }
public bool IsServer { get { return Server != null; } }
public override void _Ready() {
PacketPeer = new PacketPeerUDP();
}
public override void _Process(float delta) {
if (IsServer) { Server.Update(delta); }
if (IsClient) { Client.Update(delta); }
}
public override void _ExitTree() {
if (IsServer) { Server.Free(); }
if (IsClient) { Client.Free(); }
}
public void StartClient(string address, int port) {
if (IsClient || IsServer) { return; }
Client = new Client(PacketPeer);
Client.Initialize(address, port);
}
public void StartServer(string address, int port) {
if (IsClient || IsServer) { return; }
Server = new Server(PacketPeer);
Server.Initialize(address, port);
}
}

View File

@ -1,50 +0,0 @@
using Godot;
using System.Threading;
using Thread = System.Threading.Thread;
public abstract class Peer : Object {
private static PacketPeerUDP PacketPeer;
private static Peer Singleton;
private int LastConnectionSended = -1;
private Thread ListenerThread;
public Peer(PacketPeerUDP packetPeer) {
PacketPeer = packetPeer;
}
public abstract void Initialize(string address, int port);
public abstract void Update(float delta);
public abstract void ReceivePacket(byte[] buffer, string address, int port);
public void SendBuffer(byte[] buffer, Connection to) {
int temp1 = PacketPeer.SetDestAddress(to.Address, to.Port);
int temp2 = PacketPeer.PutPacket(buffer);
GD.print("Putting stuff to " + to.Address + ":" + to.Port);
}
public bool StartListening(int port, string address = "*") {
if (PacketPeer.IsListening() || ListenerThread != null) {
GD.printerr("The Peer is already listening or the thread is active!");
return false;
}
Singleton = this;
PacketPeer.Listen(port, address);
ThreadStart ChildRef = new ThreadStart(ListenerThreadMethod);
ListenerThread = new Thread(ChildRef);
ListenerThread.Start();
return true;
}
public static void ListenerThreadMethod() {
GD.print("Started Listener Thread.");
while (true) {
PacketPeer.Wait();
byte[] Buffer = PacketPeer.GetPacket();
string Address = PacketPeer.GetPacketIp();
int Port = PacketPeer.GetPacketPort();
Singleton.ReceivePacket(Buffer, Address, Port);
}
}
}

View File

@ -1,30 +0,0 @@
using Godot;
using System.Threading;
public class Server : Peer {
private static PacketPeerUDP PacketPeer;
private byte[] TempBuffer = { 1 };
public Server(PacketPeerUDP packetPeer) : base(packetPeer) {
PacketPeer = packetPeer;
}
public override void Initialize(string address, int port) {
StartListening(port, address);
GD.print("Server initialization finished.");
GD.print("Started server on " + address + ":" + port);
}
public override void ReceivePacket(byte[] buffer, string address, int port) {
GD.print("Server received stuff from " + address + " : " + port + " :");
for (int i = 0; i < buffer.Length; i++) {
GD.print(buffer[i]);
}
SendBuffer(TempBuffer, new Connection(address, port));
}
public override void Update(float delta) {
}
}

46
scripts/net/Client.cs Normal file
View File

@ -0,0 +1,46 @@
using Godot;
using Network.PacketHandling;
namespace Network {
public class Client : Peer {
private PacketPeerUDP PacketPeer;
private Connection ServerConn;
private PacketBuffer TempBuffer;
private float Timer = 0;
public Client(PacketPeerUDP packetPeer) : base(packetPeer) {
PacketPeer = packetPeer;
TempBuffer = NewPacketBuffer();
TempBuffer.Write(1);
}
public override void Initialize(string address, int port) {
GD.print("Start client.");
GD.print("Starting to send stuff to " + address + ":" + port);
ServerConn = new Connection(address, port);
ServerConn.Name = "Server";
StartListening(port, "*");
}
public override void Update(float delta) {
Timer += delta;
if (Timer < 1) { return; }
Timer = 0;
SendBuffer(TempBuffer, ServerConn);
}
public override void ReceivePacket(PacketBuffer packetBuffer, Connection connection) {
GD.print("Client received stuff from " + connection.Name + " at " + connection.Address + " : " + connection.Port + " :");
while (packetBuffer.HasNext) {
GD.print(packetBuffer.Read());
}
}
public override void Connected(Connection conn) {
GD.print("Connected to " + conn.Name + " at " + conn.Address + ":" + conn.Port);
}
}
}

23
scripts/net/Connection.cs Normal file
View File

@ -0,0 +1,23 @@

using System;
namespace Network {
public class Connection {
private static int IDCounter = 0;
public readonly int ID = IDCounter++;
public string Name;
public string Address;
public int Port;
public Connection(string address, int port) {
Name = "Connection-" + ID;
Address = address;
Port = port;
}
public bool Equals(Connection other) {
return other.Address == Address && other.Port == Port;
}
}
}

View File

@ -0,0 +1,45 @@

using System.Collections.Generic;
using Util;
namespace Network {
public class ConnectionList {
private Peer Peer;
private List<Connection> Connections;
public int Length { get { return Connections.Count; } }
public Connection this[int i] {
get {
return Connections[i];
}
}
public bool AddConnection(Connection conn) {
if (!Contains(conn)) {
Connections.Add(conn);
Peer.Connected(conn);
return true;
}
return false;
}
public bool Contains(Connection conn) {
foreach (Connection inList in Connections) {
if (inList.Equals(conn)) {
return true;
}
}
return false;
}
public Optional<Connection> GetOriginal(Connection conn) {
foreach (Connection inList in Connections) {
if (inList.Equals(conn)) {
return inList;
}
}
return null;
}
}
}

40
scripts/net/Net.cs Normal file
View File

@ -0,0 +1,40 @@
using Godot;
using System;
namespace Network {
public class Net : Node {
private PacketPeerUDP PacketPeer;
private Client Client;
private Server Server;
public bool IsClient { get { return Client != null; } }
public bool IsServer { get { return Server != null; } }
public override void _Ready() {
PacketPeer = new PacketPeerUDP();
}
public override void _Process(float delta) {
if (IsServer) { Server.Update(delta); }
if (IsClient) { Client.Update(delta); }
}
public override void _ExitTree() {
if (IsServer) { Server.Free(); }
if (IsClient) { Client.Free(); }
}
public void StartClient(string address, int port) {
if (IsClient || IsServer) { return; }
Client = new Client(PacketPeer);
Client.Initialize(address, port);
}
public void StartServer(string address, int port) {
if (IsClient || IsServer) { return; }
Server = new Server(PacketPeer);
Server.Initialize(address, port);
}
}
}

86
scripts/net/Peer.cs Normal file
View File

@ -0,0 +1,86 @@
using Godot;
using Network.PacketHandling;
using System.Threading;
using Thread = System.Threading.Thread;
namespace Network {
public abstract class Peer : Object {
private static PacketPeerUDP PacketPeer;
private static Peer Singleton;
private int LastConnectionSended = -1;
private Thread ListenerThread;
private static byte[] ConfirmationBytes = { 0b10011010, 0b11010011 };
public ConnectionList ConnectionList = new ConnectionList();
public Peer(PacketPeerUDP packetPeer) {
PacketPeer = packetPeer;
}
public abstract void Initialize(string address, int port);
public abstract void Update(float delta);
public abstract void ReceivePacket(PacketBuffer packetBuffer, Connection connection);
public abstract void Connected(Connection conn);
public void SendBuffer(PacketBuffer packetBuffer, Connection to) {
if (LastConnectionSended != to.ID) {
PacketPeer.SetDestAddress(to.Address, to.Port);
LastConnectionSended = to.ID;
}
PacketPeer.PutPacket(packetBuffer.ByteBuffer);
GD.print("Putting stuff to " + to.Address + ":" + to.Port);
}
public bool StartListening(int port, string address = "*") {
if (PacketPeer.IsListening() || ListenerThread != null) {
GD.printerr("The Peer is already listening or the thread is active!");
return false;
}
Singleton = this;
PacketPeer.Listen(port, address);
ThreadStart ChildRef = new ThreadStart(ListenerThreadMethod);
ListenerThread = new Thread(ChildRef);
ListenerThread.Start();
return true;
}
public static PacketBuffer NewPacketBuffer() {
PacketBuffer PB = new PacketBuffer();
foreach (byte B in ConfirmationBytes) {
PB.Write(B);
}
return PB;
}
private static void ListenerThreadMethod() {
GD.print("Started Listener Thread.");
while (true) {
PacketPeer.Wait();
byte[] Buffer = PacketPeer.GetPacket();
string Address = PacketPeer.GetPacketIp();
int Port = PacketPeer.GetPacketPort();
PacketBuffer PB = PacketBuffer.FromByteBuffer(Buffer);
if (PB.Length > ConfirmationBytes.Length) {
bool Confirmed = true;
foreach (byte B in ConfirmationBytes) {
if (PB.Read() != B) {
// Ignore packet, confirmation bytes don't match up.
Confirmed = false;
break;
}
}
if (Confirmed) {
Connection conn = new Connection(Address, Port);
Singleton.ConnectionList.AddConnection(conn);
Singleton.ReceivePacket(PB, Singleton.ConnectionList.GetOriginal(conn));
}
}
}
}
}
}

39
scripts/net/Server.cs Normal file
View File

@ -0,0 +1,39 @@
using Godot;
using Network.PacketHandling;
using System.Threading;
namespace Network {
public class Server : Peer {
private static PacketPeerUDP PacketPeer;
private PacketBuffer TempBuffer;
public Server(PacketPeerUDP packetPeer) : base(packetPeer) {
PacketPeer = packetPeer;
TempBuffer = NewPacketBuffer();
TempBuffer.Write(2);
}
public override void Initialize(string address, int port) {
StartListening(port, address);
GD.print("Server initialization finished.");
GD.print("Started server on " + address + ":" + port);
}
public override void Update(float delta) {
}
public override void ReceivePacket(PacketBuffer packetBuffer, Connection connection) {
GD.print("Server received stuff from " + connection.Name + " at " + connection.Address + " : " + connection.Port + " :");
while (packetBuffer.HasNext) {
GD.print(packetBuffer.Read());
}
SendBuffer(TempBuffer, connection);
}
public override void Connected(Connection conn) {
GD.print("Someone connected at " + conn.Address + ":" + conn.Port);
}
}
}

View File

@ -0,0 +1,33 @@
using Godot;
using System.Collections.Generic;
namespace Network.PacketHandling {
public class PacketBuffer {
private List<byte> ByteList;
private int ReadCounter = 0;
public byte[] ByteBuffer { get { return ByteList.ToArray(); } }
public int Length { get { return ByteList.Count; } }
public bool HasNext { get { return ReadCounter > ByteList.Count; } }
public byte Read() {
if (!HasNext) {
GD.printerr("Attempted to read byte; Impossible, byte buffer ended.");
return 0;
}
return ByteList[ReadCounter++];
}
public void Write(byte toWrite) {
ByteList.Add(toWrite);
}
public static PacketBuffer FromByteBuffer(byte[] byteBuffer) {
PacketBuffer PB = new PacketBuffer();
PB.ByteList = new List<byte>(byteBuffer);
return PB;
}
}
}

46
scripts/util/Optional.cs Normal file
View File

@ -0,0 +1,46 @@

namespace Util {
public class Optional<T> {
private T _Value;
public T Value {
get {
if (HasValue) {
return _Value;
} else {
throw new System.InvalidOperationException("Value of the Optional is null.");
}
}
set {
_Value = value;
}
}
public Optional(T val) {
Value = val;
}
public static explicit operator T(Optional<T> opt) {
return opt.Value;
}
public static implicit operator Optional<T>(T val) {
return new Optional<T>(val);
}
public static implicit operator T(Optional<T> opt) {
return opt.Value;
}
public void Clear() {
_Value = default(T);
}
public bool HasValue { get { return _Value != null; } }
public bool isEmpty { get { return !HasValue; } }
public bool Equals(Optional<T> opt) {
if (opt.HasValue == HasValue) { return Equals(opt.Value, Value); }
else { return opt.HasValue == HasValue; }
}
}
}