diff --git a/TicTacToe.csproj b/TicTacToe.csproj index 6ac2d62..a543f20 100644 --- a/TicTacToe.csproj +++ b/TicTacToe.csproj @@ -3,7 +3,7 @@ Debug AnyCPU - {2B5DC68F-C753-49CB-AD01-8E42EDE95B43} + {0DD2D816-33C3-432E-9705-2E0D0077835C} Library .mono\temp\bin\$(Configuration) TicTacToe @@ -50,12 +50,15 @@ - - + + + - - - + + + + + \ No newline at end of file diff --git a/TicTacToe.sln b/TicTacToe.sln index cb85e7b..e37fbe2 100644 --- a/TicTacToe.sln +++ b/TicTacToe.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # 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 Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -9,11 +9,11 @@ Global Tools|Any CPU = Tools|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2B5DC68F-C753-49CB-AD01-8E42EDE95B43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2B5DC68F-C753-49CB-AD01-8E42EDE95B43}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2B5DC68F-C753-49CB-AD01-8E42EDE95B43}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2B5DC68F-C753-49CB-AD01-8E42EDE95B43}.Release|Any CPU.Build.0 = Release|Any CPU - {2B5DC68F-C753-49CB-AD01-8E42EDE95B43}.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}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0DD2D816-33C3-432E-9705-2E0D0077835C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DD2D816-33C3-432E-9705-2E0D0077835C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DD2D816-33C3-432E-9705-2E0D0077835C}.Release|Any CPU.Build.0 = Release|Any CPU + {0DD2D816-33C3-432E-9705-2E0D0077835C}.Tools|Any CPU.ActiveCfg = Tools|Any CPU + {0DD2D816-33C3-432E-9705-2E0D0077835C}.Tools|Any CPU.Build.0 = Tools|Any CPU EndGlobalSection EndGlobal diff --git a/project.godot b/project.godot index 1775ea3..87f03b6 100644 --- a/project.godot +++ b/project.godot @@ -16,7 +16,7 @@ config/icon="res://icon.png" [autoload] -Net="*res://scripts/Net.cs" +Net="*res://scripts/net/Net.cs" [gdnative] diff --git a/scripts/Client.cs b/scripts/Client.cs deleted file mode 100644 index 6f9589b..0000000 --- a/scripts/Client.cs +++ /dev/null @@ -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); - } -} \ No newline at end of file diff --git a/scripts/Connection.cs b/scripts/Connection.cs deleted file mode 100644 index a28b8cf..0000000 --- a/scripts/Connection.cs +++ /dev/null @@ -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; - } -} \ No newline at end of file diff --git a/scripts/MainMenu.cs b/scripts/MainMenu.cs index f99d62e..be907e8 100644 --- a/scripts/MainMenu.cs +++ b/scripts/MainMenu.cs @@ -1,5 +1,7 @@ using Godot; using System; +using Network; +using Util; public class MainMenu : Panel { diff --git a/scripts/Net.cs b/scripts/Net.cs deleted file mode 100644 index 33e9704..0000000 --- a/scripts/Net.cs +++ /dev/null @@ -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); - } -} diff --git a/scripts/Peer.cs b/scripts/Peer.cs deleted file mode 100644 index de8e62a..0000000 --- a/scripts/Peer.cs +++ /dev/null @@ -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); - } - } - -} \ No newline at end of file diff --git a/scripts/Server.cs b/scripts/Server.cs deleted file mode 100644 index 1488da1..0000000 --- a/scripts/Server.cs +++ /dev/null @@ -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) { - } -} \ No newline at end of file diff --git a/scripts/net/Client.cs b/scripts/net/Client.cs new file mode 100644 index 0000000..b8cc065 --- /dev/null +++ b/scripts/net/Client.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/scripts/net/Connection.cs b/scripts/net/Connection.cs new file mode 100644 index 0000000..eb6848e --- /dev/null +++ b/scripts/net/Connection.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/scripts/net/ConnectionList.cs b/scripts/net/ConnectionList.cs new file mode 100644 index 0000000..59f6c0f --- /dev/null +++ b/scripts/net/ConnectionList.cs @@ -0,0 +1,45 @@ + +using System.Collections.Generic; +using Util; + +namespace Network { + public class ConnectionList { + + private Peer Peer; + private List 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 GetOriginal(Connection conn) { + foreach (Connection inList in Connections) { + if (inList.Equals(conn)) { + return inList; + } + } + return null; + } + } +} \ No newline at end of file diff --git a/scripts/net/Net.cs b/scripts/net/Net.cs new file mode 100644 index 0000000..5fe9605 --- /dev/null +++ b/scripts/net/Net.cs @@ -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); + } + } +} diff --git a/scripts/net/Peer.cs b/scripts/net/Peer.cs new file mode 100644 index 0000000..f9929a8 --- /dev/null +++ b/scripts/net/Peer.cs @@ -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)); + } + } + } + } + } +} \ No newline at end of file diff --git a/scripts/net/Server.cs b/scripts/net/Server.cs new file mode 100644 index 0000000..769a74a --- /dev/null +++ b/scripts/net/Server.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/scripts/net/packethandling/PacketBuffer.cs b/scripts/net/packethandling/PacketBuffer.cs new file mode 100644 index 0000000..14096b9 --- /dev/null +++ b/scripts/net/packethandling/PacketBuffer.cs @@ -0,0 +1,33 @@ +using Godot; +using System.Collections.Generic; + +namespace Network.PacketHandling { + public class PacketBuffer { + + private List 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(byteBuffer); + return PB; + } + + } +} \ No newline at end of file diff --git a/scripts/util/Optional.cs b/scripts/util/Optional.cs new file mode 100644 index 0000000..a089fec --- /dev/null +++ b/scripts/util/Optional.cs @@ -0,0 +1,46 @@ + + +namespace Util { + public class Optional { + 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 opt) { + return opt.Value; + } + + public static implicit operator Optional(T val) { + return new Optional(val); + } + + public static implicit operator T(Optional 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 opt) { + if (opt.HasValue == HasValue) { return Equals(opt.Value, Value); } + else { return opt.HasValue == HasValue; } + } + } +}