Added PacketBuffer, Optional and ConnectionList
This commit is contained in:
parent
f1fe29c2f8
commit
7f2fc019d6
@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{2B5DC68F-C753-49CB-AD01-8E42EDE95B43}</ProjectGuid>
|
||||
<ProjectGuid>{0DD2D816-33C3-432E-9705-2E0D0077835C}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<OutputPath>.mono\temp\bin\$(Configuration)</OutputPath>
|
||||
<RootNamespace>TicTacToe</RootNamespace>
|
||||
@ -50,12 +50,15 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="scripts\Client.cs" />
|
||||
<Compile Include="scripts\Connection.cs" />
|
||||
<Compile Include="scripts\net\Client.cs" />
|
||||
<Compile Include="scripts\net\ConnectionList.cs" />
|
||||
<Compile Include="scripts\net\Connection.cs" />
|
||||
<Compile Include="scripts\MainMenu.cs" />
|
||||
<Compile Include="scripts\Net.cs" />
|
||||
<Compile Include="scripts\Peer.cs" />
|
||||
<Compile Include="scripts\Server.cs" />
|
||||
<Compile Include="scripts\net\Net.cs" />
|
||||
<Compile Include="scripts\net\packethandling\PacketBuffer.cs" />
|
||||
<Compile Include="scripts\net\Peer.cs" />
|
||||
<Compile Include="scripts\net\Server.cs" />
|
||||
<Compile Include="scripts\util\Optional.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
@ -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
|
||||
|
@ -16,7 +16,7 @@ config/icon="res://icon.png"
|
||||
|
||||
[autoload]
|
||||
|
||||
Net="*res://scripts/Net.cs"
|
||||
Net="*res://scripts/net/Net.cs"
|
||||
|
||||
[gdnative]
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using Network;
|
||||
using Util;
|
||||
|
||||
public class MainMenu : Panel {
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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
46
scripts/net/Client.cs
Normal 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
23
scripts/net/Connection.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
45
scripts/net/ConnectionList.cs
Normal file
45
scripts/net/ConnectionList.cs
Normal 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
40
scripts/net/Net.cs
Normal 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
86
scripts/net/Peer.cs
Normal 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
39
scripts/net/Server.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
33
scripts/net/packethandling/PacketBuffer.cs
Normal file
33
scripts/net/packethandling/PacketBuffer.cs
Normal 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
46
scripts/util/Optional.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user