SnakeGame/SnakeGame/Network.cs

261 lines
10 KiB
C#
Raw Normal View History

2017-01-07 23:15:15 +01:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
2017-01-07 23:18:03 +01:00
using System.Net.Http;
using System.Collections.Specialized;
using System.Windows.Forms;
using System.IO;
using Newtonsoft.Json.Linq;
using System.Net.Sockets;
using System.Threading;
2017-01-07 23:20:57 +01:00
using System.Drawing;
2017-01-07 23:21:48 +01:00
using Newtonsoft.Json;
2017-01-07 23:15:15 +01:00
namespace SnakeGame
{
2017-01-07 23:21:48 +01:00
public static partial class Network
2017-01-07 23:15:15 +01:00
{
2017-01-07 23:21:48 +01:00
public const int Port = 12885;
2017-01-07 23:22:27 +01:00
public static void SyncUpdate(NetUpdateType updatetype, object data)
2017-01-07 23:15:15 +01:00
{
2017-01-07 23:23:23 +01:00
if (ConnectedMatch == null || !SendUpdate)
2017-01-07 23:22:27 +01:00
return;
2017-01-07 23:23:23 +01:00
try
2017-01-07 23:22:27 +01:00
{
2017-01-07 23:23:23 +01:00
BinaryWriter bw;
foreach (Player player in ConnectedMatch.Players)
2017-01-07 23:22:27 +01:00
{
2017-01-07 23:23:23 +01:00
if (player.Name == Game.Player.Name)
continue; //Don't send to ourselves
bool isserver = ConnectedMatch.OwnerName == Game.Player.Name;
if (!isserver)
{
2017-01-07 23:23:59 +01:00
//bw = new BinaryWriter(ConnectedMatch.GetPlayerByName(ConnectedMatch.OwnerName).Client.GetStream().ToSafeNetStream()); //If not server, send only to server
var c = ConnectedMatch.GetPlayerByName(ConnectedMatch.OwnerName).Client; //If not server, send only to server
bw = new BinaryWriter(c.GetStream().ToSafeNetStream(c, null));
2017-01-07 23:23:23 +01:00
}
else
{
2017-01-07 23:23:59 +01:00
//bw = new BinaryWriter(player.Client.GetStream().ToSafeNetStream());
var c = player.Client;
bw = new BinaryWriter(c.GetStream().ToSafeNetStream(c, null));
2017-01-07 23:23:23 +01:00
bw.Write(Game.Player.Name); //Otherwise write playername as listener expects
}
bw.Write((int)updatetype);
switch (updatetype)
{
case NetUpdateType.Name:
string newname = (string)data;
bw.Write(newname);
break;
case NetUpdateType.Color:
int color = ((Color)data).ToArgb();
bw.Write(color);
break;
case NetUpdateType.Move:
int direction = (int)data; //Converting to enum and back to int is unnecessary
bw.Write(direction);
break;
case NetUpdateType.Leave:
break;
case NetUpdateType.Teleport:
Point point = (Point)data;
bw.Write(point.X);
bw.Write(point.Y);
break;
2017-01-07 23:23:59 +01:00
case NetUpdateType.Score:
int score = (int)data;
bw.Write(score);
break;
case NetUpdateType.Lives:
int lives = (int)data;
bw.Write(lives);
break;
case NetUpdateType.Pause:
bool pause = (bool)data;
bw.Write(pause);
break;
2017-01-07 23:23:23 +01:00
}
if (!isserver)
break; //If not server, only send to the server
2017-01-07 23:22:27 +01:00
}
2017-01-07 23:23:23 +01:00
}
catch (IOException)
{
}
catch (Exception e)
{
Program.HandleException(e);
2017-01-07 23:22:27 +01:00
}
2017-01-07 23:18:03 +01:00
}
public static List<NetMatch> Matches = new List<NetMatch>();
public static NetMatch ConnectedMatch { get; private set; }
public static void CreateGame(NetMatch match)
{
2017-01-07 23:24:42 +01:00
Join(match, true);
2017-01-07 23:18:03 +01:00
}
public static void Connect(NetMatch match)
{
2017-01-07 23:21:48 +01:00
Join(match, false);
2017-01-07 23:20:57 +01:00
}
2017-01-07 23:21:48 +01:00
public static void Join(NetMatch match, bool server)
2017-01-07 23:20:57 +01:00
{
if (ConnectedMatch != null)
Leave();
ConnectedMatch = match;
2017-01-07 23:21:48 +01:00
StartListening(server);
2017-01-07 23:18:03 +01:00
}
2017-01-07 23:21:48 +01:00
private static event EventHandler StopEventPerPlayer;
2017-01-07 23:18:03 +01:00
public static void Leave()
{
if (ConnectedMatch == null)
return;
2017-01-07 23:22:27 +01:00
SyncUpdate(NetUpdateType.Leave, null);
2017-01-07 23:24:42 +01:00
SendUpdate = false;
2017-01-07 23:21:48 +01:00
if (ConnectedMatch.OwnerName == Game.Player.Name)
{
2017-01-07 23:24:42 +01:00
Listener.Stop();
2017-01-07 23:23:23 +01:00
}
2017-01-07 23:20:57 +01:00
ReceiverThread.Abort();
2017-01-07 23:21:48 +01:00
if (StopEventPerPlayer != null)
StopEventPerPlayer(null, null);
2017-01-07 23:20:57 +01:00
foreach (Thread t in PlayerThreads)
t.Abort();
PlayerThreads.Clear();
2017-01-07 23:21:48 +01:00
ConnectedMatch = null;
2017-01-07 23:18:03 +01:00
}
public static IPAddress[] GetIPs()
{
//https://msdn.microsoft.com/en-us/library/ee663252%28v=vs.110%29.aspx
try
{
2017-01-07 23:20:57 +01:00
return Dns.GetHostEntry(Dns.GetHostName()).AddressList.Where(entry => entry.AddressFamily == AddressFamily.InterNetworkV6).ToArray();
2017-01-07 23:18:03 +01:00
}
catch
{
MessageBox.Show("Error! Failed to get IP address.\nDoes your system support IPv6?");
return null;
}
}
public static Thread ReceiverThread;
2017-01-07 23:20:57 +01:00
public static List<Thread> PlayerThreads = new List<Thread>();
2017-01-07 23:21:48 +01:00
public static void StartListening(bool server)
2017-01-07 23:18:03 +01:00
{
2017-01-07 23:21:48 +01:00
/*if (ReceiverThread == null)
(ReceiverThread = new Thread(new ThreadStart(server ? ServerListenerThreadRun : ClientListenerThreadRun))).Start();*/
2017-01-07 23:18:03 +01:00
if (ReceiverThread == null)
2017-01-07 23:20:57 +01:00
{
2017-01-07 23:21:48 +01:00
if (server)
(ReceiverThread = new Thread(new ThreadStart(ServerListenerThreadRun))).Start();
else
(ReceiverThread = new Thread(new ThreadStart(ClientListenerThreadRun))).Start();
2017-01-07 23:20:57 +01:00
}
}
2017-01-07 23:22:27 +01:00
public static bool SendUpdate = false;
private static bool ReceiveAndProcessData(Player player, BinaryReader br)
{
string playername = player.Name;
try
{
NetUpdateType updatetype = (NetUpdateType)br.ReadInt32();
switch (updatetype)
{
case NetUpdateType.Name:
string newname = br.ReadString();
player.Name = newname;
foreach (BinaryWriter bw in ForwardMessage(player, playername, (int)updatetype))
{ //ForwardMessage prepares each send and then here the only thing to do is to send the extra data
bw.Write(newname);
}
break;
case NetUpdateType.Color:
Color color = Color.FromArgb(br.ReadInt32());
player.Color = color;
foreach (BinaryWriter bw in ForwardMessage(player, playername, (int)updatetype))
{
bw.Write(color.ToArgb());
}
break;
case NetUpdateType.Move:
Direction direction = (Direction)br.ReadInt32();
Game.MovePlayerPost(player, Game.MovePlayerPre(player, direction));
foreach (BinaryWriter bw in ForwardMessage(player, playername, (int)updatetype))
{
bw.Write((int)direction);
}
break;
/*case NetUpdateType.Login:
ConnectedMatch.Players.Add(new Player(playername, ConnectedMatch.NextID));
break;*/
case NetUpdateType.Leave:
foreach (BinaryWriter bw in ForwardMessage(player, playername, (int)updatetype))
{
}
Network.ConnectedMatch.Players.RemoveAll(entry => entry.Name == playername);
player.Client.Close();
break;
2017-01-07 23:23:23 +01:00
case NetUpdateType.Teleport:
player.Position = new Point(br.ReadInt32(), br.ReadInt32());
2017-01-07 23:24:42 +01:00
Console.WriteLine("Teleporting player " + player.Name + " to point " + player.Position);
2017-01-07 23:23:23 +01:00
Game.MovePlayerPost(player, player.Position);
foreach (BinaryWriter bw in ForwardMessage(player, playername, (int)updatetype))
{
bw.Write(player.Position.X);
bw.Write(player.Position.Y);
}
break;
2017-01-07 23:23:59 +01:00
case NetUpdateType.Score:
player.Score = br.ReadInt32();
foreach (BinaryWriter bw in ForwardMessage(player, playername, (int)updatetype))
{
bw.Write(player.Score);
}
break;
case NetUpdateType.Lives:
player.Lives = br.ReadInt32();
foreach (BinaryWriter bw in ForwardMessage(player, playername, (int)updatetype))
{
bw.Write(player.Lives);
}
break;
case NetUpdateType.Pause:
Form1.SetTimerWithoutSend(!br.ReadBoolean());
foreach(BinaryWriter bw in ForwardMessage(player, playername, (int)updatetype))
{
bw.Write(Game.Paused);
}
break;
2017-01-07 23:22:27 +01:00
}
}
catch (IOException)
{
return false;
}
2017-01-07 23:24:42 +01:00
catch(ObjectDisposedException)
{
return false;
}
2017-01-07 23:23:23 +01:00
catch (Exception e)
{
Program.HandleException(e);
}
2017-01-07 23:22:27 +01:00
return true;
}
2017-01-07 23:20:57 +01:00
}
public enum NetUpdateType
{
Name,
Color,
Move,
//Login, - Login==Connect
2017-01-07 23:23:23 +01:00
Leave,
2017-01-07 23:23:59 +01:00
Teleport,
Score,
Lives,
Pause
2017-01-07 23:15:15 +01:00
}
}