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
}
}