move to github
This commit is contained in:
19
SpacePew/Networking/NetworkMessage.cs
Normal file
19
SpacePew/Networking/NetworkMessage.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SpacePew.Models;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace SpacePew.Networking
|
||||
{
|
||||
public class NetworkMessage
|
||||
{
|
||||
// TODO: Add SoundAssetName to make NetworkMessenger play custom sounds upon different messages
|
||||
public string Message { get; set; }
|
||||
public DateTime Sent { get; set; }
|
||||
public Color Color { get; set; }
|
||||
public bool IsChatMessage { get; set; }
|
||||
}
|
||||
}
|
374
SpacePew/Networking/NetworkMessenger.cs
Normal file
374
SpacePew/Networking/NetworkMessenger.cs
Normal file
@@ -0,0 +1,374 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.GamerServices;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using Microsoft.Xna.Framework.Media;
|
||||
using Microsoft.Xna.Framework.Net;
|
||||
using Microsoft.Xna.Framework.Storage;
|
||||
using SpacePew.Models;
|
||||
|
||||
|
||||
namespace SpacePew.Networking
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO: This is not really a network messenger yet, so we need to change the functionality a little (send all message over network in the loop down there)
|
||||
/// </summary>
|
||||
public class NetworkMessenger : Microsoft.Xna.Framework.GameComponent, IDrawable
|
||||
{
|
||||
private readonly MainGame _game;
|
||||
private SpriteBatch _spriteBatch;
|
||||
private SpriteFont _netFont;
|
||||
private Rectangle _chatRectangle;
|
||||
private Rectangle _textBounds;
|
||||
private static UdpClient _client;
|
||||
|
||||
private static List<NetworkMessage> _messages;
|
||||
|
||||
private const int DefaultMessageLifeTime = 10;
|
||||
|
||||
public NetworkMessenger(MainGame game, UdpClient client)
|
||||
: base(game)
|
||||
{
|
||||
_game = game;
|
||||
_client = client;
|
||||
_messages = new List<NetworkMessage>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game component to perform any initialization it needs to before starting
|
||||
/// to run. This is where it can query for any required services and load content.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
_spriteBatch = new SpriteBatch(_game.GraphicsDevice);
|
||||
_netFont = _game.Content.Load<SpriteFont>("Fonts\\Default");
|
||||
_chatRectangle = new Rectangle(300, 20, 300, _game.GraphicsDevice.Viewport.Height - 40);
|
||||
_textBounds = new Rectangle();
|
||||
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
public static void AddDeath(IEntity entity)
|
||||
{
|
||||
_client.SendDeath(entity);
|
||||
}
|
||||
|
||||
public static void DisplayMessage(NetworkMessage message)
|
||||
{
|
||||
_messages.Add(message);
|
||||
}
|
||||
|
||||
public static void SendMessage(NetworkMessage message)
|
||||
{
|
||||
_messages.Add(message);
|
||||
_client.SendMessage(message);
|
||||
|
||||
if (message.IsChatMessage)
|
||||
{
|
||||
SoundManager.Play("Audio/Waves/message", _client.LocalPlayer.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private string _chatMessage = string.Empty;
|
||||
|
||||
private KeyboardState _oldKeyboardState;
|
||||
private KeyboardState _currentKeyboardState;
|
||||
|
||||
bool chatting = false;
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game component to update itself.
|
||||
/// </summary>
|
||||
/// <param name="gameTime">Provides a snapshot of timing values.</param>
|
||||
public override void Update(GameTime gameTime)
|
||||
{
|
||||
MainGame.IsKeyboardInUse = chatting;
|
||||
|
||||
_oldKeyboardState = _currentKeyboardState;
|
||||
|
||||
_currentKeyboardState = Keyboard.GetState();
|
||||
Keys[] pressedKeys = _currentKeyboardState.GetPressedKeys();
|
||||
|
||||
bool isShiftDown = pressedKeys.Any(KeyboardHelper.IsShift);
|
||||
|
||||
foreach (Keys key in pressedKeys)
|
||||
{
|
||||
if (!_oldKeyboardState.IsKeyUp(key)) continue;
|
||||
|
||||
if (key == Keys.T && !chatting)
|
||||
{
|
||||
chatting = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!chatting) continue;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case Keys.Back:
|
||||
_chatMessage = _chatMessage.Remove(_chatMessage.Length - 1, 1);
|
||||
break;
|
||||
case Keys.Space:
|
||||
_chatMessage = _chatMessage + " ";
|
||||
break;
|
||||
default:
|
||||
if (key == Keys.Enter && chatting)
|
||||
{
|
||||
chatting = false;
|
||||
SendMessage(new NetworkMessage()
|
||||
{
|
||||
Color = _client.LocalPlayer.Color,
|
||||
Message =
|
||||
string.Format("{0}: {1}", _client.LocalPlayer.Owner,
|
||||
_chatMessage),
|
||||
Sent = DateTime.Now,
|
||||
IsChatMessage = true
|
||||
});
|
||||
|
||||
_chatMessage = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isShiftDown)
|
||||
{
|
||||
_chatMessage += KeyboardHelper.ToPrintableString(key, KbModifiers.None).ToUpper();
|
||||
}
|
||||
else
|
||||
{
|
||||
_chatMessage += KeyboardHelper.ToPrintableString(key, KbModifiers.None);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = _messages.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (_messages[i].Sent.AddSeconds(DefaultMessageLifeTime) <= DateTime.Now)
|
||||
{
|
||||
_messages.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
||||
public void Draw(GameTime gameTime)
|
||||
{
|
||||
_spriteBatch.Begin();
|
||||
|
||||
int yOffset = 0;
|
||||
|
||||
if (chatting)
|
||||
{
|
||||
_spriteBatch.DrawString(_netFont, "Chat: " + _chatMessage,
|
||||
new Vector2(300, _game.GraphicsDevice.Viewport.Height - 140), Color.White);
|
||||
}
|
||||
|
||||
foreach (var message in _messages)
|
||||
{
|
||||
DrawString(_spriteBatch,
|
||||
_netFont,
|
||||
message.Message,
|
||||
_chatRectangle,
|
||||
message.Color,
|
||||
TextAlignment.TopLeft,
|
||||
true,
|
||||
new Vector2(0, (_messages.IndexOf(message) * 15) + yOffset),
|
||||
out _textBounds);
|
||||
|
||||
yOffset += _textBounds.Height;
|
||||
}
|
||||
|
||||
_spriteBatch.End();
|
||||
}
|
||||
|
||||
public int DrawOrder
|
||||
{
|
||||
get { return 5; }
|
||||
}
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
private enum TextAlignment
|
||||
{
|
||||
Top,
|
||||
Left,
|
||||
Middle,
|
||||
Right,
|
||||
Bottom,
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomRight
|
||||
}
|
||||
|
||||
private static void DrawString(SpriteBatch sb, SpriteFont fnt, string text, Rectangle r,
|
||||
Color col, TextAlignment align, bool performWordWrap, Vector2 offsett, out Rectangle textBounds)
|
||||
{
|
||||
textBounds = r;
|
||||
if (text == null) return;
|
||||
if (text == string.Empty) return;
|
||||
|
||||
var lines = new StringCollection();
|
||||
lines.AddRange(text.Split(new string[] { "\\n" }, StringSplitOptions.RemoveEmptyEntries));
|
||||
|
||||
Rectangle tmprect = ProcessLines(fnt, r, performWordWrap, lines);
|
||||
|
||||
var pos = new Vector2(r.X, r.Y);
|
||||
int aStyle = 0;
|
||||
|
||||
switch (align)
|
||||
{
|
||||
case TextAlignment.Bottom:
|
||||
pos.Y = r.Bottom - tmprect.Height;
|
||||
aStyle = 1;
|
||||
break;
|
||||
case TextAlignment.BottomLeft:
|
||||
pos.Y = r.Bottom - tmprect.Height;
|
||||
aStyle = 0;
|
||||
break;
|
||||
case TextAlignment.BottomRight:
|
||||
pos.Y = r.Bottom - tmprect.Height;
|
||||
aStyle = 2;
|
||||
break;
|
||||
case TextAlignment.Left:
|
||||
pos.Y = r.Y + ((r.Height / 2) - (tmprect.Height / 2));
|
||||
aStyle = 0;
|
||||
break;
|
||||
case TextAlignment.Middle:
|
||||
pos.Y = r.Y + ((r.Height / 2) - (tmprect.Height / 2));
|
||||
aStyle = 1;
|
||||
break;
|
||||
case TextAlignment.Right:
|
||||
pos.Y = r.Y + ((r.Height / 2) - (tmprect.Height / 2));
|
||||
aStyle = 2;
|
||||
break;
|
||||
case TextAlignment.Top:
|
||||
aStyle = 1;
|
||||
break;
|
||||
case TextAlignment.TopLeft:
|
||||
aStyle = 0;
|
||||
break;
|
||||
case TextAlignment.TopRight:
|
||||
aStyle = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (string txt in lines)
|
||||
{
|
||||
Vector2 size = fnt.MeasureString(txt);
|
||||
switch (aStyle)
|
||||
{
|
||||
case 0:
|
||||
pos.X = r.X;
|
||||
break;
|
||||
case 1:
|
||||
pos.X = r.X + ((r.Width / 2) - (size.X / 2));
|
||||
break;
|
||||
case 2:
|
||||
pos.X = r.Right - size.X;
|
||||
break;
|
||||
}
|
||||
|
||||
sb.DrawString(fnt, txt, pos + offsett, col);
|
||||
pos.Y += fnt.LineSpacing;
|
||||
}
|
||||
|
||||
textBounds = tmprect;
|
||||
}
|
||||
|
||||
private static Rectangle ProcessLines(SpriteFont fnt, Rectangle r, bool performWordWrap, StringCollection lines)
|
||||
{
|
||||
Rectangle bounds = r;
|
||||
bounds.Width = 0;
|
||||
bounds.Height = 0;
|
||||
int index = 0;
|
||||
float Width;
|
||||
bool lineInserted = false;
|
||||
while (index < lines.Count)
|
||||
{
|
||||
string linetext = lines[index];
|
||||
|
||||
Vector2 size = fnt.MeasureString(linetext);
|
||||
|
||||
if (performWordWrap && size.X > r.Width)
|
||||
{
|
||||
string endspace = string.Empty;
|
||||
if (linetext.EndsWith(" "))
|
||||
{
|
||||
endspace = " ";
|
||||
linetext = linetext.TrimEnd();
|
||||
}
|
||||
|
||||
int i = linetext.LastIndexOf(" ", StringComparison.InvariantCulture);
|
||||
if (i != -1)
|
||||
{
|
||||
string lastword = linetext.Substring(i + 1);
|
||||
|
||||
if (index == lines.Count - 1)
|
||||
{
|
||||
lines.Add(lastword);
|
||||
lineInserted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lineInserted)
|
||||
{
|
||||
lines[index + 1] = lastword + endspace + lines[index + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
lines.Insert(index + 1, lastword);
|
||||
lineInserted = true;
|
||||
}
|
||||
}
|
||||
|
||||
lines[index] = linetext.Substring(0, i + 1);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
lineInserted = false;
|
||||
size = fnt.MeasureString(lines[index]);
|
||||
if (size.X > bounds.Width) Width = size.X;
|
||||
bounds.Height += fnt.LineSpacing;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lineInserted = false;
|
||||
size = fnt.MeasureString(lines[index]);
|
||||
if (size.X > bounds.Width) bounds.Width = (int)size.X;
|
||||
bounds.Height += fnt.LineSpacing;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
|
||||
event EventHandler<EventArgs> IDrawable.DrawOrderChanged
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
event EventHandler<EventArgs> IDrawable.VisibleChanged
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
}
|
||||
}
|
135
SpacePew/Networking/ScoreBoard.cs
Normal file
135
SpacePew/Networking/ScoreBoard.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.GamerServices;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using Microsoft.Xna.Framework.Media;
|
||||
using Microsoft.Xna.Framework.Net;
|
||||
using Microsoft.Xna.Framework.Storage;
|
||||
using SpacePew.Models;
|
||||
|
||||
|
||||
namespace SpacePew.Networking
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a game component that implements IUpdateable.
|
||||
/// </summary>
|
||||
public class ScoreBoard : Microsoft.Xna.Framework.GameComponent, IDrawable
|
||||
{
|
||||
public static List<ScoreBoardItem> CurrentScoreBoard { get; set; }
|
||||
|
||||
private readonly MainGame _game;
|
||||
private readonly UdpClient _client;
|
||||
private Texture2D _scoreBoardTexture;
|
||||
|
||||
private SpriteBatch _spriteBatch;
|
||||
|
||||
private SpriteFont _scoreFont;
|
||||
|
||||
public ScoreBoard(MainGame game, UdpClient client)
|
||||
: base(game)
|
||||
{
|
||||
_game = game;
|
||||
_client = client;
|
||||
|
||||
CurrentScoreBoard = new List<ScoreBoardItem>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game component to perform any initialization it needs to before starting
|
||||
/// to run. This is where it can query for any required services and load content.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
_spriteBatch = new SpriteBatch(_game.GraphicsDevice);
|
||||
|
||||
_scoreFont = _game.Content.Load<SpriteFont>("Fonts\\Default");
|
||||
_scoreBoardTexture = _game.Content.Load<Texture2D>("scoreboard");
|
||||
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
bool requestedScoreBoard;
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game component to update itself.
|
||||
/// </summary>
|
||||
/// <param name="gameTime">Provides a snapshot of timing values.</param>
|
||||
public override void Update(GameTime gameTime)
|
||||
{
|
||||
if (Keyboard.GetState().IsKeyDown(Keys.Tab))
|
||||
{
|
||||
if (!requestedScoreBoard)
|
||||
{
|
||||
_client.RequestScoreBoard();
|
||||
}
|
||||
|
||||
requestedScoreBoard = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
requestedScoreBoard = false;
|
||||
}
|
||||
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
||||
public void Draw(GameTime gameTime)
|
||||
{
|
||||
if (Keyboard.GetState().IsKeyDown(Keys.Tab))
|
||||
{
|
||||
_spriteBatch.Begin();
|
||||
|
||||
_spriteBatch.Draw(_scoreBoardTexture, new Vector2(20, 20), Color.White);
|
||||
|
||||
foreach (ScoreBoardItem item in CurrentScoreBoard)
|
||||
{
|
||||
Player player = ((List<Player>)_client.Players).Find(p => p.Owner == item.Name);
|
||||
|
||||
if (player != null)
|
||||
{
|
||||
Color color = player.Color;
|
||||
|
||||
int yOffset = (CurrentScoreBoard.IndexOf(item) * 15) + 70;
|
||||
|
||||
_spriteBatch.DrawString(_scoreFont, item.Name, new Vector2(35, yOffset), color);
|
||||
_spriteBatch.DrawString(_scoreFont, item.Kills.ToString(CultureInfo.InvariantCulture), new Vector2(185, yOffset), color);
|
||||
_spriteBatch.DrawString(_scoreFont, item.Deaths.ToString(CultureInfo.InvariantCulture), new Vector2(243, yOffset), color);
|
||||
_spriteBatch.DrawString(_scoreFont, (DateTime.Now - item.Joined).Minutes.ToString(CultureInfo.InvariantCulture),
|
||||
new Vector2(314, yOffset), color);
|
||||
_spriteBatch.DrawString(_scoreFont, item.Ping.ToString(CultureInfo.InvariantCulture), new Vector2(373, yOffset), color);
|
||||
}
|
||||
}
|
||||
|
||||
_spriteBatch.End();
|
||||
}
|
||||
}
|
||||
|
||||
public int DrawOrder
|
||||
{
|
||||
get { return 5; }
|
||||
}
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
event EventHandler<EventArgs> IDrawable.DrawOrderChanged
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
event EventHandler<EventArgs> IDrawable.VisibleChanged
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
}
|
||||
}
|
16
SpacePew/Networking/ScoreBoardItem.cs
Normal file
16
SpacePew/Networking/ScoreBoardItem.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace SpacePew.Networking
|
||||
{
|
||||
public class ScoreBoardItem
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Kills { get; set; }
|
||||
public int Deaths { get; set; }
|
||||
public DateTime Joined { get; set; }
|
||||
public long Ping { get; set; }
|
||||
}
|
||||
}
|
64
SpacePew/Networking/StreamingClient.cs
Normal file
64
SpacePew/Networking/StreamingClient.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Diagnostics;
|
||||
using Lidgren.Network;
|
||||
using System.IO;
|
||||
using SpacePew.Common;
|
||||
|
||||
namespace SpacePew.Networking
|
||||
{
|
||||
public class StreamingClient
|
||||
{
|
||||
private FileStream _inputStream;
|
||||
private int _sentOffset;
|
||||
private int _chunkLen;
|
||||
private byte[] _tmpBuffer;
|
||||
private NetConnection _connection;
|
||||
|
||||
public StreamingClient(NetConnection conn, string fileName)
|
||||
{
|
||||
_connection = conn;
|
||||
_inputStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
_chunkLen = _connection.Peer.Configuration.MaximumTransmissionUnit - 20;
|
||||
_tmpBuffer = new byte[_chunkLen];
|
||||
_sentOffset = 0;
|
||||
}
|
||||
|
||||
public void Heartbeat()
|
||||
{
|
||||
if (_inputStream == null)
|
||||
return;
|
||||
|
||||
if (_connection.CanSendImmediately(NetDeliveryMethod.ReliableOrdered, 1))
|
||||
{
|
||||
long remaining = _inputStream.Length - _sentOffset;
|
||||
int sendBytes = (remaining > _chunkLen ? _chunkLen : (int)remaining);
|
||||
|
||||
_inputStream.Read(_tmpBuffer, 0, sendBytes);
|
||||
|
||||
NetOutgoingMessage message;
|
||||
if (_sentOffset == 0)
|
||||
{
|
||||
message = _connection.Peer.CreateMessage(sendBytes + 8);
|
||||
message.Write((int)UdpNetworkPacketType.LevelResponse);
|
||||
message.Write((ulong)_inputStream.Length);
|
||||
message.Write(Path.GetFileName(_inputStream.Name));
|
||||
|
||||
_connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 1);
|
||||
}
|
||||
|
||||
message = _connection.Peer.CreateMessage(sendBytes + 8);
|
||||
message.Write((int)UdpNetworkPacketType.LevelResponse);
|
||||
message.Write(_tmpBuffer, 0, sendBytes);
|
||||
|
||||
_connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 1);
|
||||
_sentOffset += sendBytes;
|
||||
|
||||
if (remaining - sendBytes <= 0)
|
||||
{
|
||||
_inputStream.Close();
|
||||
_inputStream.Dispose();
|
||||
_inputStream = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
62
SpacePew/Networking/UdpBase.cs
Normal file
62
SpacePew/Networking/UdpBase.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Lidgren.Network;
|
||||
using SpacePew.Common;
|
||||
using System.Net;
|
||||
|
||||
namespace SpacePew.Networking
|
||||
{
|
||||
public abstract class UdpBase
|
||||
{
|
||||
protected Color[] _playerColors =
|
||||
{
|
||||
Color.Red,
|
||||
Color.Blue,
|
||||
Color.Green,
|
||||
Color.Yellow,
|
||||
Color.Purple,
|
||||
Color.White,
|
||||
Color.Red,
|
||||
Color.LightBlue,
|
||||
Color.Orange,
|
||||
Color.Gray
|
||||
};
|
||||
|
||||
protected byte[] ObjectToByteArray(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return null;
|
||||
|
||||
var memoryStream = new MemoryStream();
|
||||
var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress);
|
||||
var formatter = new BinaryFormatter();
|
||||
formatter.Serialize(gZipStream, obj);
|
||||
|
||||
gZipStream.Close();
|
||||
memoryStream.Close();
|
||||
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
protected object ByteArrayToObject(byte[] bytes)
|
||||
{
|
||||
var memoryStream = new MemoryStream();
|
||||
var gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress);
|
||||
|
||||
var formatter = new BinaryFormatter();
|
||||
|
||||
memoryStream.Write(bytes, 0, bytes.Length);
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var obj = formatter.Deserialize(gzipStream);
|
||||
|
||||
gzipStream.Close();
|
||||
memoryStream.Close();
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
586
SpacePew/Networking/UdpClient.cs
Normal file
586
SpacePew/Networking/UdpClient.cs
Normal file
@@ -0,0 +1,586 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
using SpacePew.Extensions;
|
||||
using Lidgren.Network;
|
||||
using System.Collections;
|
||||
using SpacePew.Models;
|
||||
using SpacePew.Common;
|
||||
using System.Net;
|
||||
|
||||
namespace SpacePew.Networking
|
||||
{
|
||||
public class UdpClient : UdpBase
|
||||
{
|
||||
private string _playerName;
|
||||
private readonly NetClient _client;
|
||||
private Level _level;
|
||||
|
||||
private readonly MainGame _game;
|
||||
|
||||
private int _colorIndex;
|
||||
|
||||
private IPEndPoint _masterServerEndpoint;
|
||||
|
||||
private UdpClient()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public UdpClient(MainGame game)
|
||||
{
|
||||
_game = game;
|
||||
_masterServerEndpoint = NetUtility.Resolve("spacepew.wodanaz.se", Constants.MasterServerPort); // TODO: Fixa upp masterserver någonstans
|
||||
EntitiesToSend = new List<IEntity>();
|
||||
|
||||
var configuration = new NetPeerConfiguration("SpacePew");
|
||||
|
||||
configuration.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
|
||||
configuration.EnableMessageType(NetIncomingMessageType.DiscoveryResponse);
|
||||
configuration.EnableMessageType(NetIncomingMessageType.UnconnectedData);
|
||||
configuration.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);
|
||||
|
||||
_client = new NetClient(configuration);
|
||||
_client.Start();
|
||||
}
|
||||
|
||||
public List<IEntity> EntitiesToSend { get; set; }
|
||||
|
||||
public NetClient CurrentClient
|
||||
{
|
||||
get { return _client; }
|
||||
}
|
||||
|
||||
private Player _localPlayer;
|
||||
public Player LocalPlayer
|
||||
{
|
||||
get
|
||||
{
|
||||
return _localPlayer;
|
||||
}
|
||||
set
|
||||
{
|
||||
_localPlayer = value;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<Player> _players = new List<Player>();
|
||||
public IList<Player> Players
|
||||
{
|
||||
get
|
||||
{
|
||||
return _players;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSessionAlive
|
||||
{
|
||||
get
|
||||
{
|
||||
return _client != null && _client.ConnectionStatus == NetConnectionStatus.Connected;
|
||||
}
|
||||
}
|
||||
|
||||
public void JoinSession(string host, string playerName)
|
||||
{
|
||||
JoinSession(new IPEndPoint(System.Net.Dns.GetHostAddresses(host)[0], SpacePew.Common.Constants.GameServerPort), playerName);
|
||||
}
|
||||
|
||||
public void JoinSession(IPEndPoint endpoint, string playerName)
|
||||
{
|
||||
_playerName = playerName;
|
||||
|
||||
var hailMessage = _client.CreateMessage(playerName);
|
||||
_client.Connect(endpoint, hailMessage);
|
||||
|
||||
while (_client.ServerConnection == null)
|
||||
{
|
||||
// wait
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(500); // TODO: nya lidgren är dumt i huvet, grotta i vad skiten sätter i någon tråd se'n
|
||||
|
||||
System.Diagnostics.Trace.WriteLine("Got server connection...");
|
||||
WriteLevelRequest();
|
||||
WaitForLevel();
|
||||
WriteJoiningMessage();
|
||||
WaitForJoin();
|
||||
|
||||
if (_level.OggVorbisSong != null)
|
||||
{
|
||||
new Thread(_level.PlayLevelSong).Start();
|
||||
}
|
||||
}
|
||||
|
||||
public void ExitSession(string reason)
|
||||
{
|
||||
var message = _client.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.PlayerDisconnecting);
|
||||
message.Write(_playerName);
|
||||
|
||||
_client.SendMessage(message, NetDeliveryMethod.ReliableOrdered);
|
||||
|
||||
_client.Disconnect(reason);
|
||||
}
|
||||
|
||||
public void SendMessage(NetworkMessage message)
|
||||
{
|
||||
var netMessage = _client.CreateMessage();
|
||||
|
||||
netMessage.Write((int)UdpNetworkPacketType.MessageSent);
|
||||
netMessage.Write(message.Color.ToVector3());
|
||||
netMessage.Write(message.Sent.ToString(CultureInfo.InvariantCulture));
|
||||
netMessage.Write(message.Message);
|
||||
netMessage.Write(message.IsChatMessage);
|
||||
|
||||
_client.SendMessage(netMessage, NetDeliveryMethod.UnreliableSequenced);
|
||||
}
|
||||
|
||||
public void RequestScoreBoard()
|
||||
{
|
||||
var message = _client.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.RequestingScoreboard);
|
||||
|
||||
_client.SendMessage(message, NetDeliveryMethod.UnreliableSequenced);
|
||||
}
|
||||
|
||||
private void ReadMessage(NetIncomingMessage netMessage)
|
||||
{
|
||||
var color = new Color(netMessage.ReadVector3());
|
||||
var sent = DateTime.Parse(netMessage.ReadString(), CultureInfo.InvariantCulture);
|
||||
string message = netMessage.ReadString();
|
||||
bool isChatMessage = netMessage.ReadBoolean();
|
||||
|
||||
NetworkMessenger.DisplayMessage(new NetworkMessage() { Color = color, Sent = sent, Message = message, IsChatMessage = isChatMessage});
|
||||
}
|
||||
|
||||
public void SendDeath(IEntity killedBy)
|
||||
{
|
||||
var message = _client.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.PlayerDying);
|
||||
message.Write(_playerName);
|
||||
message.Write(killedBy.Owner); // TODO: server side score board
|
||||
|
||||
_client.SendMessage(message, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
private void WriteLevelRequest()
|
||||
{
|
||||
Trace.WriteLine("WriteLevelRequest");
|
||||
var message = _client.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.LevelRequest);
|
||||
|
||||
_client.SendMessage(message, NetDeliveryMethod.ReliableUnordered);
|
||||
System.Diagnostics.Trace.WriteLine("Sent level request...");
|
||||
}
|
||||
|
||||
private void WriteJoiningMessage()
|
||||
{
|
||||
Trace.WriteLine("WriteJoiningMessage");
|
||||
|
||||
var message = _client.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.PlayerJoining);
|
||||
message.Write(_playerName);
|
||||
|
||||
_client.SendMessage(message, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
private void WaitForJoin()
|
||||
{
|
||||
System.Diagnostics.Trace.WriteLine("WaitForJoin");
|
||||
bool hasAnswer = false;
|
||||
while (!hasAnswer) // wait for answer
|
||||
{
|
||||
NetIncomingMessage message;
|
||||
while ((message = _client.ReadMessage()) != null)
|
||||
{
|
||||
if (message.MessageType == NetIncomingMessageType.Data)
|
||||
{
|
||||
var packetType = (UdpNetworkPacketType)message.ReadInt32();
|
||||
if (packetType == UdpNetworkPacketType.PlayerJoined)
|
||||
{
|
||||
string owner = message.ReadString();
|
||||
|
||||
int colorIndex = message.ReadInt32();
|
||||
Color color = _playerColors[colorIndex];
|
||||
|
||||
_colorIndex = Array.IndexOf(_playerColors, color);
|
||||
|
||||
Vector2 pos = message.ReadVector2();
|
||||
Vector2 velocity = message.ReadVector2();
|
||||
float angle = message.ReadFloat();
|
||||
int collisionSize = message.ReadInt32();
|
||||
var collisionData = message.ReadBytes(collisionSize);
|
||||
|
||||
_level.CollisionData = (bool[])ByteArrayToObject(collisionData);
|
||||
_level.BuildLevelFromCollisionData();
|
||||
|
||||
Player p = Player.CreatePlayer(pos, owner);
|
||||
p.Color = color;
|
||||
p.Position = pos;
|
||||
p.Velocity = velocity;
|
||||
p.Angle = angle;
|
||||
|
||||
_localPlayer = p;
|
||||
_players.Add(p);
|
||||
|
||||
hasAnswer = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
NetIncomingMessage message;
|
||||
|
||||
while ((message = _client.ReadMessage()) != null)
|
||||
{
|
||||
ReadBuffer(message);
|
||||
}
|
||||
|
||||
if (EntitiesToSend.Count > 0)
|
||||
{
|
||||
WriteServerShots();
|
||||
}
|
||||
|
||||
WritePlayerUpdatePacket();
|
||||
}
|
||||
|
||||
private void WriteServerShots()
|
||||
{
|
||||
SendEntities(EntitiesToSend);
|
||||
}
|
||||
|
||||
private void WritePlayerUpdatePacket()
|
||||
{
|
||||
var message = _client.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.PlayerUpdate);
|
||||
message.Write(_localPlayer.Owner);
|
||||
message.Write(_colorIndex);
|
||||
message.Write(_localPlayer.Position);
|
||||
message.Write(_localPlayer.Velocity);
|
||||
message.Write(_localPlayer.Angle);
|
||||
message.Write(_localPlayer.Health);
|
||||
|
||||
_client.SendMessage(message, NetDeliveryMethod.UnreliableSequenced);
|
||||
}
|
||||
|
||||
private void ReadBuffer(NetIncomingMessage message)
|
||||
{
|
||||
switch (message.MessageType)
|
||||
{
|
||||
case NetIncomingMessageType.Data:
|
||||
{
|
||||
var packetType = (UdpNetworkPacketType)message.ReadInt32();
|
||||
|
||||
switch (packetType)
|
||||
{
|
||||
case UdpNetworkPacketType.PlayerUpdate:
|
||||
ReadPlayers(message);
|
||||
break;
|
||||
case UdpNetworkPacketType.EntitiesCreated:
|
||||
ReadEntities(message);
|
||||
break;
|
||||
case UdpNetworkPacketType.MessageReceived:
|
||||
ReadMessage(message);
|
||||
break;
|
||||
case UdpNetworkPacketType.PlayerDied:
|
||||
ReadPlayerDied(message);
|
||||
break;
|
||||
case UdpNetworkPacketType.SendingScoreBoard:
|
||||
ReadScoreBoard(message);
|
||||
break;
|
||||
case UdpNetworkPacketType.EntityCreated:
|
||||
ReadEntity(message);
|
||||
break;
|
||||
case UdpNetworkPacketType.PlayerDisconnected:
|
||||
RemovePlayer(message);
|
||||
break;
|
||||
case UdpNetworkPacketType.LevelResponse:
|
||||
ReadLevel(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
_client.Recycle(message);
|
||||
}
|
||||
|
||||
private void WaitForLevel()
|
||||
{
|
||||
System.Diagnostics.Trace.WriteLine("WaitForLevel");
|
||||
while (_level == null) // wait for level
|
||||
{
|
||||
NetIncomingMessage message;
|
||||
while ((message = _client.ReadMessage()) != null)
|
||||
{
|
||||
if (message.MessageType == NetIncomingMessageType.Data)
|
||||
{
|
||||
var packetType = (UdpNetworkPacketType)message.ReadInt32();
|
||||
if (packetType == UdpNetworkPacketType.LevelResponse)
|
||||
{
|
||||
ReadLevel(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ulong _levelLength;
|
||||
private static ulong _levelReceived;
|
||||
private static FileStream _levelWriteStream;
|
||||
private static int _levelTimeStarted;
|
||||
string levelPath = string.Empty;
|
||||
|
||||
private void ReadLevel(NetIncomingMessage message)
|
||||
{
|
||||
int chunkLen = message.LengthBytes;
|
||||
if (_levelLength == 0)
|
||||
{
|
||||
_levelLength = message.ReadUInt64();
|
||||
string filename = message.ReadString();
|
||||
|
||||
var downloadLevelFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Downloads\\Levels\\");
|
||||
levelPath = Path.Combine(downloadLevelFolder, filename);
|
||||
|
||||
_levelWriteStream = new FileStream(levelPath, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
_levelTimeStarted = Environment.TickCount;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] all = message.ReadBytes(message.LengthBytes - 4); // offset for UdpNetworkPacketType
|
||||
_levelReceived += (ulong)all.Length;
|
||||
_levelWriteStream.Write(all, 0, all.Length);
|
||||
|
||||
//int v = (int)(((float)_levelReceived / (float)_levelLength) * 100.0f);
|
||||
//int passed = Environment.TickCount - _levelTimeStarted;
|
||||
//double psec = (double)passed / 1000.0;
|
||||
//double bps = (double)_levelReceived / psec;
|
||||
|
||||
//var passedText = NetUtility.ToHumanReadable((long)bps) + " per second";
|
||||
|
||||
if (_levelReceived >= _levelLength)
|
||||
{
|
||||
Trace.WriteLine("Got level");
|
||||
_levelWriteStream.Flush();
|
||||
_levelWriteStream.Close();
|
||||
_levelWriteStream.Dispose();
|
||||
|
||||
_level = LevelLoader.LoadLevel(levelPath, _game.Content, _game.GraphicsDevice);
|
||||
_game.Level = _level;
|
||||
}
|
||||
}
|
||||
|
||||
private void RemovePlayer(NetIncomingMessage message)
|
||||
{
|
||||
string name = message.ReadString();
|
||||
|
||||
Player player = _players.Find(p => p.Owner == name);
|
||||
if (player != null)
|
||||
{
|
||||
EntityFactory.Instance.RemoveEntity(player);
|
||||
|
||||
NetworkMessenger.DisplayMessage(new NetworkMessage()
|
||||
{
|
||||
Color = player.Color,
|
||||
Message = string.Format("{0} has left.", player.Owner),
|
||||
Sent = DateTime.Now
|
||||
});
|
||||
|
||||
_players.Remove(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadScoreBoard(NetIncomingMessage message)
|
||||
{
|
||||
int count = message.ReadInt32();
|
||||
|
||||
var scoreBoard = new List<ScoreBoardItem>();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var item = new ScoreBoardItem
|
||||
{
|
||||
Name = message.ReadString(),
|
||||
Kills = message.ReadInt32(),
|
||||
Deaths = message.ReadInt32(),
|
||||
Joined = DateTime.Parse(message.ReadString(), CultureInfo.InvariantCulture),
|
||||
Ping = message.ReadInt64()
|
||||
};
|
||||
|
||||
scoreBoard.Add(item);
|
||||
}
|
||||
|
||||
ScoreBoard.CurrentScoreBoard = scoreBoard;
|
||||
}
|
||||
|
||||
private void ReadPlayerDied(NetIncomingMessage message)
|
||||
{
|
||||
string playerName = message.ReadString();
|
||||
|
||||
Player player = _players.Find(p => p.Owner == playerName);
|
||||
|
||||
if (player != null)
|
||||
{
|
||||
_game.AddExplosion(player.Position, 1f);
|
||||
player.Kill();
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadEntities(NetIncomingMessage message)
|
||||
{
|
||||
int count = message.ReadInt32();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
string entityType = message.ReadString();
|
||||
string owner = message.ReadString();
|
||||
Vector2 pos = message.ReadVector2();
|
||||
Vector2 velocity = message.ReadVector2();
|
||||
float angle = message.ReadFloat();
|
||||
|
||||
EntityFactory.Instance.CreateEntity<IEntity>(Type.GetType(entityType), owner, pos, velocity, angle);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadEntity(NetIncomingMessage message)
|
||||
{
|
||||
string entityType = message.ReadString();
|
||||
string owner = message.ReadString();
|
||||
Vector2 pos = message.ReadVector2();
|
||||
Vector2 velocity = message.ReadVector2();
|
||||
float angle = message.ReadFloat();
|
||||
|
||||
EntityFactory.Instance.CreateEntity<IEntity>(Type.GetType(entityType), owner, pos, velocity, angle);
|
||||
}
|
||||
|
||||
private void ReadPlayers(NetIncomingMessage message)
|
||||
{
|
||||
string owner = message.ReadString();
|
||||
|
||||
int colorIndex = message.ReadInt32();
|
||||
Color color = _playerColors[colorIndex];
|
||||
|
||||
Vector2 pos = message.ReadVector2();
|
||||
Vector2 velocity = message.ReadVector2();
|
||||
float angle = message.ReadFloat();
|
||||
|
||||
if (owner == LocalPlayer.Owner)
|
||||
return;
|
||||
|
||||
Player player = _players.Find(p => p.Owner == owner);
|
||||
if (player == null)
|
||||
{
|
||||
Player p = Player.CreatePlayer(new Vector2(300, 280), owner);
|
||||
|
||||
p.Position = pos;
|
||||
p.Color = color;
|
||||
p.Velocity = velocity;
|
||||
p.Angle = angle;
|
||||
p.Owner = owner;
|
||||
|
||||
_players.Add(p);
|
||||
|
||||
NetworkMessenger.DisplayMessage(new NetworkMessage()
|
||||
{
|
||||
Color = p.Color,
|
||||
Message = string.Format("{0} has joined.", p.Owner),
|
||||
Sent = DateTime.Now
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = _players.IndexOf(player);
|
||||
player.Owner = owner;
|
||||
player.Color = color;
|
||||
player.Position = pos;
|
||||
player.Velocity = velocity;
|
||||
player.Angle = angle;
|
||||
|
||||
_players[index] = player;
|
||||
}
|
||||
}
|
||||
|
||||
public void SendEntities(List<IEntity> entities)
|
||||
{
|
||||
var message = _client.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.EntitiesCreated);
|
||||
message.Write(entities.Count);
|
||||
|
||||
lock (EntitiesToSend)
|
||||
{
|
||||
for (int i = entities.Count - 1; i >= 0; i--)
|
||||
{
|
||||
message.Write(entities[i].GetType().ToString());
|
||||
message.Write(_localPlayer.Owner);
|
||||
message.Write(entities[i].Position);
|
||||
message.Write(entities[i].Velocity);
|
||||
message.Write(entities[i].Angle);
|
||||
}
|
||||
}
|
||||
|
||||
EntitiesToSend.Clear();
|
||||
|
||||
_client.SendMessage(message, NetDeliveryMethod.UnreliableSequenced);
|
||||
}
|
||||
|
||||
public void SendEntity(IEntity entity)
|
||||
{
|
||||
var message = _client.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.EntityCreated);
|
||||
message.Write(entity.GetType().ToString());
|
||||
message.Write(_localPlayer.Owner);
|
||||
message.Write(entity.Position);
|
||||
message.Write(entity.Velocity);
|
||||
message.Write(entity.Angle);
|
||||
|
||||
_client.SendMessage(message, NetDeliveryMethod.UnreliableSequenced);
|
||||
}
|
||||
|
||||
public void GetServerList()
|
||||
{
|
||||
var listRequest = _client.CreateMessage();
|
||||
listRequest.Write((byte)UdpNetworkPacketType.RequestHostList);
|
||||
_client.SendUnconnectedMessage(listRequest, _masterServerEndpoint);
|
||||
}
|
||||
|
||||
public void RequestNATIntroduction(long hostid)
|
||||
{
|
||||
if (hostid == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_masterServerEndpoint == null)
|
||||
throw new Exception("Must connect to master server first!");
|
||||
|
||||
IPAddress mask;
|
||||
var message = _client.CreateMessage();
|
||||
message.Write((byte)UdpNetworkPacketType.RequestIntroduction);
|
||||
|
||||
message.Write(new IPEndPoint(NetUtility.GetMyAddress(out mask), _client.Port));
|
||||
message.Write(hostid);
|
||||
message.Write(_playerName);
|
||||
|
||||
_client.SendUnconnectedMessage(message, _masterServerEndpoint);
|
||||
}
|
||||
}
|
||||
}
|
361
SpacePew/Networking/UdpNetworkGui.cs
Normal file
361
SpacePew/Networking/UdpNetworkGui.cs
Normal file
@@ -0,0 +1,361 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.GamerServices;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using Microsoft.Xna.Framework.Media;
|
||||
using Microsoft.Xna.Framework.Net;
|
||||
using Microsoft.Xna.Framework.Storage;
|
||||
using System.Threading;
|
||||
using SpacePew.Models;
|
||||
#if WINDOWS
|
||||
using TomShane.Neoforce.Controls;
|
||||
using Lidgren.Network;
|
||||
using System.Net;
|
||||
using System.Diagnostics;
|
||||
#endif
|
||||
|
||||
namespace SpacePew.Networking
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a game component that implements IUpdateable.
|
||||
/// </summary>
|
||||
#if WINDOWS
|
||||
public class UdpNetworkGui : Microsoft.Xna.Framework.DrawableGameComponent
|
||||
{
|
||||
private MainGame _game;
|
||||
|
||||
private UdpClient _client;
|
||||
private UdpServer _server;
|
||||
|
||||
private GraphicsDeviceManager _graphics;
|
||||
|
||||
private Manager _manager;
|
||||
private Window _window;
|
||||
private TabControl _tabControl;
|
||||
private TextBox _nameTextBox;
|
||||
private TextBox _nameTextBox2;
|
||||
private TextBox _ipTextBox;
|
||||
private Label _nameLabel;
|
||||
private Label _nameLabel2;
|
||||
private ListBox _localGamesListBox;
|
||||
|
||||
private Label _joinErrorLabel;
|
||||
|
||||
private Label _ipLabel;
|
||||
private Button _createButton;
|
||||
private Button _joinButton;
|
||||
private Button _refreshButton;
|
||||
|
||||
public UdpNetworkGui(MainGame game, GraphicsDeviceManager graphics, UdpClient client, UdpServer server)
|
||||
: base(game)
|
||||
{
|
||||
_game = game;
|
||||
_graphics = graphics;
|
||||
_client = client;
|
||||
_server = server;
|
||||
|
||||
_client.CurrentClient.Start();
|
||||
|
||||
_manager = new Manager(game, _graphics, "Default");
|
||||
_manager.Skin = new Skin(_manager, "Default");
|
||||
_manager.AutoCreateRenderTarget = true;
|
||||
_manager.TargetFrames = 60;
|
||||
_manager.LogUnhandledExceptions = false;
|
||||
_manager.ShowSoftwareCursor = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game component to perform any initialization it needs to before starting
|
||||
/// to run. This is where it can query for any required services and load content.
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_window = new Window(_manager);
|
||||
_window.Init();
|
||||
_window.Text = "Space, pew pew!";
|
||||
_window.Width = 480;
|
||||
_window.Height = 200;
|
||||
_window.Center();
|
||||
_window.CloseButtonVisible = false;
|
||||
_window.Resizable = false;
|
||||
_window.Visible = true;
|
||||
|
||||
_tabControl = new TabControl(_manager);
|
||||
_tabControl.Width = _window.Width;
|
||||
_tabControl.Height = _window.Height;
|
||||
_tabControl.Parent = _window;
|
||||
|
||||
_nameLabel = new Label(_manager);
|
||||
_nameLabel.Init();
|
||||
_nameLabel.Width = 100;
|
||||
_nameLabel.Height = 24;
|
||||
_nameLabel.Text = "Name";
|
||||
_nameLabel.Left = 10;
|
||||
_nameLabel.Top = 10;
|
||||
|
||||
_nameTextBox = new TextBox(_manager);
|
||||
_nameTextBox.Init();
|
||||
_nameTextBox.Width = 140;
|
||||
_nameTextBox.Height = 24;
|
||||
_nameTextBox.Left = 50;
|
||||
_nameTextBox.Top = 10;
|
||||
|
||||
_nameLabel2 = new Label(_manager);
|
||||
_nameLabel2.Init();
|
||||
_nameLabel2.Width = 100;
|
||||
_nameLabel2.Height = 24;
|
||||
_nameLabel2.Text = "Name";
|
||||
_nameLabel2.Left = 10;
|
||||
_nameLabel2.Top = 10;
|
||||
|
||||
_nameTextBox2 = new TextBox(_manager);
|
||||
_nameTextBox2.Init();
|
||||
_nameTextBox2.Width = 140;
|
||||
_nameTextBox2.Height = 24;
|
||||
_nameTextBox2.Left = 50;
|
||||
_nameTextBox2.Top = 10;
|
||||
|
||||
_createButton = new Button(_manager);
|
||||
_createButton.Init();
|
||||
_createButton.Text = "Create game";
|
||||
_createButton.Width = 140;
|
||||
_createButton.Height = 24;
|
||||
_createButton.Left = 50;
|
||||
_createButton.Top = 40;
|
||||
_createButton.Click += _createButton_Click;
|
||||
|
||||
_ipLabel = new Label(_manager);
|
||||
_ipLabel.Init();
|
||||
_ipLabel.Width = 100;
|
||||
_ipLabel.Height = 24;
|
||||
_ipLabel.Text = "Host";
|
||||
_ipLabel.Left = 10;
|
||||
_ipLabel.Top = 40;
|
||||
|
||||
_ipTextBox = new TextBox(_manager);
|
||||
_ipTextBox.Init();
|
||||
_ipTextBox.Width = 140;
|
||||
_ipTextBox.Height = 24;
|
||||
_ipTextBox.Left = 50;
|
||||
_ipTextBox.Top = 40;
|
||||
|
||||
_joinErrorLabel = new Label(_manager);
|
||||
_joinErrorLabel.Init();
|
||||
_joinErrorLabel.Width = 460;
|
||||
_joinErrorLabel.Height = 24;
|
||||
_joinErrorLabel.Left = 10;
|
||||
_joinErrorLabel.Top = 110;
|
||||
_joinErrorLabel.Text = string.Empty;
|
||||
_joinErrorLabel.TextColor = Color.DarkRed;
|
||||
|
||||
_joinButton = new Button(_manager);
|
||||
_joinButton.Init();
|
||||
_joinButton.Text = "Join game";
|
||||
_joinButton.Width = 140;
|
||||
_joinButton.Height = 24;
|
||||
_joinButton.Left = 50;
|
||||
_joinButton.Top = 70;
|
||||
_joinButton.Anchor = Anchors.Bottom;
|
||||
_joinButton.Click += _joinButton_Click;
|
||||
|
||||
_localGamesListBox = new ListBox(_manager);
|
||||
_localGamesListBox.Init();
|
||||
_localGamesListBox.Left = 200;
|
||||
_localGamesListBox.Top = 10;
|
||||
_localGamesListBox.Height = 84;
|
||||
_localGamesListBox.Width = 254;
|
||||
_localGamesListBox.ItemIndexChanged += new TomShane.Neoforce.Controls.EventHandler(_localGamesListBox_ItemIndexChanged);
|
||||
|
||||
_refreshButton = new Button(_manager);
|
||||
_refreshButton.Init();
|
||||
_refreshButton.Text = "Refresh";
|
||||
_refreshButton.Width = 140;
|
||||
_refreshButton.Height = 24;
|
||||
_refreshButton.Left = 314;
|
||||
_refreshButton.Top = 104;
|
||||
_refreshButton.Click += _refreshButton_Click;
|
||||
|
||||
_nameTextBox.Click += ChangeTextBoxColor;
|
||||
_nameTextBox2.Click += ChangeTextBoxColor;
|
||||
_ipTextBox.Click += ChangeTextBoxColor;
|
||||
|
||||
_tabControl.AddPage();
|
||||
_tabControl.AddPage();
|
||||
_tabControl.TabPages[0].Text = "Create";
|
||||
_tabControl.TabPages[0].Add(_nameLabel);
|
||||
_tabControl.TabPages[0].Add(_nameTextBox);
|
||||
_tabControl.TabPages[0].Add(_createButton);
|
||||
|
||||
_tabControl.TabPages[1].Text = "Join";
|
||||
_tabControl.TabPages[1].Add(_nameLabel2);
|
||||
_tabControl.TabPages[1].Add(_nameTextBox2);
|
||||
_tabControl.TabPages[1].Add(_ipLabel);
|
||||
_tabControl.TabPages[1].Add(_ipTextBox);
|
||||
_tabControl.TabPages[1].Add(_joinButton);
|
||||
_tabControl.TabPages[1].Add(_joinErrorLabel);
|
||||
_tabControl.TabPages[1].Add(_localGamesListBox);
|
||||
_tabControl.TabPages[1].Add(_refreshButton);
|
||||
|
||||
_manager.Add(_window);
|
||||
_manager.Initialize();
|
||||
|
||||
_client.CurrentClient.DiscoverLocalPeers(SpacePew.Common.Constants.GameServerPort);
|
||||
}
|
||||
|
||||
private void _refreshButton_Click(object sender, TomShane.Neoforce.Controls.EventArgs e)
|
||||
{
|
||||
_localGamesListBox.Items.Clear();
|
||||
_client.CurrentClient.DiscoverLocalPeers(SpacePew.Common.Constants.GameServerPort);
|
||||
}
|
||||
|
||||
private void ChangeTextBoxColor(object sender, TomShane.Neoforce.Controls.EventArgs e)
|
||||
{
|
||||
((TomShane.Neoforce.Controls.Control)sender).Color = Color.TransparentBlack;
|
||||
}
|
||||
|
||||
private void _localGamesListBox_ItemIndexChanged(object sender, TomShane.Neoforce.Controls.EventArgs e)
|
||||
{
|
||||
_ipTextBox.Text = _localGamesListBox.Items[_localGamesListBox.ItemIndex].ToString();
|
||||
}
|
||||
|
||||
private void _createButton_Click(object sender, TomShane.Neoforce.Controls.EventArgs e)
|
||||
{
|
||||
_nameTextBox.Color = string.IsNullOrEmpty(_nameTextBox.Text) ? Color.Pink : Color.TransparentBlack;
|
||||
|
||||
if (_nameTextBox.Color == Color.Pink)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string levelPath = AppDomain.CurrentDomain.BaseDirectory + "\\Levels\\hippie.zip"; // TODO: V<>lja
|
||||
var level = LevelLoader.LoadLevel(levelPath, _game.Content, GraphicsDevice);
|
||||
|
||||
_server.SetLevel(level);
|
||||
|
||||
_window.Close();
|
||||
Trace.WriteLine("CreateSession()");
|
||||
_server.CreateSession();
|
||||
|
||||
new Thread(_server.Listen).Start();
|
||||
|
||||
_client.JoinSession("127.0.0.1", _nameTextBox.Text);
|
||||
|
||||
_game.AddGameComponents();
|
||||
_game.Components.Remove(this);
|
||||
}
|
||||
|
||||
private void _joinButton_Click(object sender, TomShane.Neoforce.Controls.EventArgs e)
|
||||
{
|
||||
_ipTextBox.Color = string.IsNullOrEmpty(_ipTextBox.Text) ? Color.Pink : Color.TransparentBlack;
|
||||
_nameTextBox2.Color = string.IsNullOrEmpty(_nameTextBox2.Text) ? Color.Pink : Color.TransparentBlack;
|
||||
|
||||
if (_ipTextBox.Color == Color.Pink || _nameTextBox2.Color == Color.Pink)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var splits = _ipTextBox.Text.Split(' ');
|
||||
if (splits.Count() > 1)
|
||||
{
|
||||
var host = Int64.Parse(splits[0]);
|
||||
_client.RequestNATIntroduction(host);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
_client.JoinSession(_ipTextBox.Text, _nameTextBox2.Text);
|
||||
|
||||
_game.AddGameComponents();
|
||||
_game.Components.Remove(this);
|
||||
}
|
||||
catch (NetException ex)
|
||||
{
|
||||
_joinErrorLabel.Text = ex.Message;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime _lastUpdate = DateTime.Now.AddSeconds(-5);
|
||||
private static Dictionary<long, IPEndPoint[]> _hostList = new Dictionary<long, IPEndPoint[]>();
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game component to update itself.
|
||||
/// </summary>
|
||||
/// <param name="gameTime">Provides a snapshot of timing values.</param>
|
||||
public override void Update(GameTime gameTime)
|
||||
{
|
||||
_manager.Update(gameTime);
|
||||
|
||||
if (_lastUpdate <= DateTime.Now.AddSeconds(-5))
|
||||
{
|
||||
_lastUpdate = DateTime.Now;
|
||||
_client.CurrentClient.DiscoverLocalPeers(SpacePew.Common.Constants.GameServerPort);
|
||||
_client.GetServerList();
|
||||
}
|
||||
NetIncomingMessage message;
|
||||
while ((message = _client.CurrentClient.ReadMessage()) != null)
|
||||
{
|
||||
if (message.MessageType == NetIncomingMessageType.UnconnectedData)
|
||||
{
|
||||
var id = message.ReadInt64();
|
||||
var hostInternal = message.ReadIPEndPoint();
|
||||
var hostExternal = message.ReadIPEndPoint();
|
||||
|
||||
_hostList[id] = new IPEndPoint[] { hostInternal, hostExternal };
|
||||
|
||||
_localGamesListBox.Items.Clear();
|
||||
foreach (var kvp in _hostList)
|
||||
{
|
||||
_localGamesListBox.Items.Add(kvp.Key.ToString() + " (" + kvp.Value[1] + ")");
|
||||
}
|
||||
}
|
||||
else if (message.MessageType == NetIncomingMessageType.DiscoveryResponse)
|
||||
{
|
||||
IPEndPoint ep = message.ReadIPEndPoint();
|
||||
if (!_localGamesListBox.Items.Contains(ep.Address.ToString()))
|
||||
{
|
||||
_localGamesListBox.Items.Add(ep.Address.ToString());
|
||||
}
|
||||
}
|
||||
else if (message.MessageType == NetIncomingMessageType.NatIntroductionSuccess)
|
||||
{
|
||||
try
|
||||
{
|
||||
_client.JoinSession(message.SenderEndPoint, _nameTextBox2.Text);
|
||||
|
||||
_game.AddGameComponents();
|
||||
_game.Components.Remove(this);
|
||||
}
|
||||
catch (NetException ex)
|
||||
{
|
||||
_joinErrorLabel.Text = ex.Message;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
||||
public override void Draw(GameTime gameTime)
|
||||
{
|
||||
_manager.BeginDraw(gameTime);
|
||||
|
||||
GraphicsDevice.Clear(Color.Black);
|
||||
|
||||
_manager.EndDraw();
|
||||
|
||||
base.Draw(gameTime);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
405
SpacePew/Networking/UdpServer.cs
Normal file
405
SpacePew/Networking/UdpServer.cs
Normal file
@@ -0,0 +1,405 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
using SpacePew.Extensions;
|
||||
|
||||
using Lidgren.Network;
|
||||
using System.Net;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Net.NetworkInformation;
|
||||
using SpacePew.Models;
|
||||
using SpacePew.Common;
|
||||
|
||||
namespace SpacePew.Networking
|
||||
{
|
||||
public class UdpServer : UdpBase
|
||||
{
|
||||
private NetPeerConfiguration _configuration;
|
||||
private NetServer _server;
|
||||
private Level _level;
|
||||
|
||||
private readonly List<ScoreBoardItem> _scoreBoard;
|
||||
private readonly List<string> _players;
|
||||
|
||||
private readonly Vector2 _defaultPosition = new Vector2(300, 280);
|
||||
|
||||
private IPEndPoint _masterServerEndpoint;
|
||||
|
||||
public UdpServer()
|
||||
: base()
|
||||
{
|
||||
_masterServerEndpoint = NetUtility.Resolve("spacepew.wodanaz.se", Constants.MasterServerPort); // TODO: Fixa upp masterserver någonstans
|
||||
_scoreBoard = new List<ScoreBoardItem>();
|
||||
_players = new List<string>();
|
||||
}
|
||||
|
||||
public void CreateSession()
|
||||
{
|
||||
if (_server == null)
|
||||
{
|
||||
_configuration = new NetPeerConfiguration("SpacePew")
|
||||
{
|
||||
MaximumConnections = 16,
|
||||
Port = SpacePew.Common.Constants.GameServerPort
|
||||
};
|
||||
|
||||
_configuration.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
|
||||
_configuration.EnableMessageType(NetIncomingMessageType.DiscoveryResponse);
|
||||
_configuration.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);
|
||||
|
||||
_server = new NetServer(_configuration);
|
||||
_server.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLevel(Level level)
|
||||
{
|
||||
_level = level;
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
if (_server != null && _server.Status == NetPeerStatus.Running)
|
||||
{
|
||||
_server.Shutdown("Quitting");
|
||||
}
|
||||
}
|
||||
|
||||
public void Listen()
|
||||
{
|
||||
|
||||
System.Diagnostics.Trace.WriteLine("Server.Listen()");
|
||||
while (_server.Status == NetPeerStatus.Running)
|
||||
{
|
||||
NetIncomingMessage message;
|
||||
while ((message = _server.ReadMessage()) != null)
|
||||
{
|
||||
ReadBuffer(message, message.SenderConnection);
|
||||
}
|
||||
|
||||
if (NetTime.Now > lastRegistered + 60)
|
||||
{
|
||||
RegisterWithMasterServer();
|
||||
}
|
||||
|
||||
StreamLevelToClients();
|
||||
}
|
||||
}
|
||||
|
||||
private void StreamLevelToClients()
|
||||
{
|
||||
foreach (var conn in _server.Connections)
|
||||
{
|
||||
var client = conn.Tag as StreamingClient;
|
||||
if (client != null)
|
||||
client.Heartbeat();
|
||||
}
|
||||
}
|
||||
|
||||
float lastRegistered = -60.0f;
|
||||
private void RegisterWithMasterServer()
|
||||
{
|
||||
IPAddress mask;
|
||||
IPAddress localAddress = NetUtility.GetMyAddress(out mask);
|
||||
var message = _server.CreateMessage();
|
||||
message.Write((byte)UdpNetworkPacketType.RegisterHost);
|
||||
message.Write(_server.UniqueIdentifier);
|
||||
message.Write(new IPEndPoint(localAddress, Constants.GameServerPort));
|
||||
|
||||
_server.SendUnconnectedMessage(message, _masterServerEndpoint);
|
||||
|
||||
lastRegistered = (float)NetTime.Now;
|
||||
}
|
||||
|
||||
private void ReadBuffer(NetIncomingMessage message, NetConnection sender)
|
||||
{
|
||||
switch (message.MessageType)
|
||||
{
|
||||
case NetIncomingMessageType.Data:
|
||||
{
|
||||
var packetType = (UdpNetworkPacketType)message.ReadInt32();
|
||||
switch (packetType)
|
||||
{
|
||||
case UdpNetworkPacketType.PlayerUpdate:
|
||||
WritePlayerUpdate(message, sender);
|
||||
break;
|
||||
case UdpNetworkPacketType.EntitiesCreated:
|
||||
WriteEntities(message, sender);
|
||||
break;
|
||||
case UdpNetworkPacketType.MessageSent:
|
||||
WriteMessage(message, sender);
|
||||
break;
|
||||
case UdpNetworkPacketType.EntityCreated:
|
||||
WriteEntity(message, sender);
|
||||
break;
|
||||
case UdpNetworkPacketType.PlayerDying:
|
||||
WritePlayerDied(message, sender);
|
||||
break;
|
||||
case UdpNetworkPacketType.RequestingScoreboard:
|
||||
WriteScoreBoard(sender);
|
||||
break;
|
||||
case UdpNetworkPacketType.PlayerJoining:
|
||||
{
|
||||
string name = message.ReadString();
|
||||
_players.Add(name);
|
||||
sender.Tag = name;
|
||||
_scoreBoard.Add(new ScoreBoardItem() { Name = name, Joined = DateTime.Now });
|
||||
|
||||
WritePlayerJoinedPacket(sender, name);
|
||||
break;
|
||||
}
|
||||
case UdpNetworkPacketType.PlayerDisconnecting:
|
||||
{
|
||||
string name = message.ReadString();
|
||||
|
||||
WritePlayerDisconnectedPacket(sender, name);
|
||||
break;
|
||||
}
|
||||
case UdpNetworkPacketType.LevelRequest:
|
||||
{
|
||||
WriteLevelResponse(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NetIncomingMessageType.ConnectionApproval:
|
||||
AuthorizeConnection(sender);
|
||||
break;
|
||||
case NetIncomingMessageType.DiscoveryRequest:
|
||||
WriteDiscoveryResponse(sender);
|
||||
break;
|
||||
case NetIncomingMessageType.StatusChanged:
|
||||
{
|
||||
var status = (NetConnectionStatus)message.ReadByte();
|
||||
var msg = message.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_server.Recycle(message);
|
||||
}
|
||||
|
||||
private void WriteLevelResponse(NetIncomingMessage message)
|
||||
{
|
||||
message.SenderConnection.Tag = new StreamingClient(message.SenderConnection, _level.FilePath);
|
||||
}
|
||||
|
||||
private void WriteDiscoveryResponse(NetConnection sender)
|
||||
{
|
||||
if (sender == null)
|
||||
return;
|
||||
|
||||
var message = _server.CreateMessage();
|
||||
|
||||
// TODO: Skicka med lite stats
|
||||
_server.SendDiscoveryResponse(message, sender.RemoteEndPoint);
|
||||
}
|
||||
|
||||
private void WritePlayerDisconnectedPacket(NetConnection sender, string name)
|
||||
{
|
||||
var message = _server.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.PlayerDisconnected);
|
||||
message.Write(name);
|
||||
|
||||
_server.SendToAll(message, sender, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
|
||||
_players.Remove(name);
|
||||
}
|
||||
|
||||
private void WriteScoreBoard(NetConnection sender)
|
||||
{
|
||||
var message = _server.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.SendingScoreBoard);
|
||||
|
||||
int count = _scoreBoard.Count;
|
||||
|
||||
message.Write(count);
|
||||
|
||||
var ping = new Ping();
|
||||
|
||||
foreach (var item in _scoreBoard)
|
||||
{
|
||||
message.Write(item.Name);
|
||||
message.Write(item.Kills);
|
||||
message.Write(item.Deaths);
|
||||
message.Write(item.Joined.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
//TODO: Fixa riktig ping
|
||||
//NetConnection connection = _server.Connections.Find(s => s.Tag.ToString() == item.Name);
|
||||
|
||||
//long pingTime = ping.Send(connection.RemoteEndpoint.Address).RoundtripTime;
|
||||
const long pinglong = 14;
|
||||
message.Write(pinglong);
|
||||
}
|
||||
|
||||
_server.SendMessage(message, sender, NetDeliveryMethod.UnreliableSequenced);
|
||||
}
|
||||
|
||||
private void WriteMessage(NetIncomingMessage incomingMessage, NetConnection sender)
|
||||
{
|
||||
Vector3 colorVector = incomingMessage.ReadVector3();
|
||||
string dateString = incomingMessage.ReadString();
|
||||
string message = incomingMessage.ReadString();
|
||||
bool isChatMessage = incomingMessage.ReadBoolean();
|
||||
|
||||
var outgoingMessage = _server.CreateMessage();
|
||||
|
||||
outgoingMessage.Write((int)UdpNetworkPacketType.MessageReceived);
|
||||
outgoingMessage.Write(colorVector);
|
||||
outgoingMessage.Write(dateString);
|
||||
outgoingMessage.Write(message);
|
||||
outgoingMessage.Write(isChatMessage);
|
||||
|
||||
_server.SendToAll(outgoingMessage, sender, NetDeliveryMethod.UnreliableSequenced, 1);
|
||||
}
|
||||
|
||||
private void WritePlayerDied(NetIncomingMessage incomingMessage, NetConnection sender)
|
||||
{
|
||||
string playerName = incomingMessage.ReadString();
|
||||
string killedBy = incomingMessage.ReadString();
|
||||
|
||||
if (playerName != killedBy)
|
||||
{
|
||||
AddKillScore(killedBy);
|
||||
}
|
||||
|
||||
AddDeathScore(playerName);
|
||||
|
||||
var message = _server.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.PlayerDied);
|
||||
message.Write(playerName);
|
||||
|
||||
_server.SendToAll(message, sender, NetDeliveryMethod.ReliableUnordered, 0);
|
||||
}
|
||||
|
||||
private void AddKillScore(string name)
|
||||
{
|
||||
ScoreBoardItem item = _scoreBoard.Find(i => i.Name == name);
|
||||
item.Kills++;
|
||||
_scoreBoard[_scoreBoard.IndexOf(item)] = item;
|
||||
}
|
||||
|
||||
private void AddDeathScore(string name)
|
||||
{
|
||||
ScoreBoardItem item = _scoreBoard.Find(i => i.Name == name);
|
||||
item.Deaths++;
|
||||
_scoreBoard[_scoreBoard.IndexOf(item)] = item;
|
||||
}
|
||||
|
||||
private void WriteEntities(NetIncomingMessage incomingMessage, NetConnection sender)
|
||||
{
|
||||
int count = incomingMessage.ReadInt32();
|
||||
|
||||
var message = _server.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.EntitiesCreated);
|
||||
message.Write(count);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
message.Write(incomingMessage.ReadString());
|
||||
message.Write(incomingMessage.ReadString());
|
||||
message.Write(incomingMessage.ReadVector2());
|
||||
message.Write(incomingMessage.ReadVector2());
|
||||
message.Write(incomingMessage.ReadFloat());
|
||||
}
|
||||
|
||||
_server.SendToAll(message, sender, NetDeliveryMethod.UnreliableSequenced, 1);
|
||||
}
|
||||
|
||||
private void AuthorizeConnection(NetConnection sender)
|
||||
{
|
||||
string name = Encoding.ASCII.GetString(sender.RemoteHailMessage.Data);
|
||||
if (!string.IsNullOrEmpty(name) && !_players.Contains(name))
|
||||
{
|
||||
sender.Approve();
|
||||
}
|
||||
else
|
||||
{
|
||||
sender.Deny("A player with that name is already playing.");
|
||||
}
|
||||
}
|
||||
|
||||
private void WritePlayerJoinedPacket(NetConnection sender, string name)
|
||||
{
|
||||
System.Diagnostics.Trace.WriteLine("In WritePlayerJoined()...");
|
||||
|
||||
var message = _server.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.PlayerJoined);
|
||||
|
||||
message.Write(name);
|
||||
message.Write(_server.Connections.IndexOf(sender));
|
||||
message.Write(_defaultPosition); // TODO: positions should be stored on the level somehow
|
||||
message.Write(Vector2.Zero);
|
||||
message.Write(0f);
|
||||
|
||||
_level.BuildCollisionDataFromLevel();
|
||||
|
||||
byte[] collisionData = ObjectToByteArray(_level.CollisionData);
|
||||
message.Write(collisionData.Length);
|
||||
message.Write(collisionData);
|
||||
|
||||
_server.SendMessage(message, sender, NetDeliveryMethod.ReliableUnordered);
|
||||
System.Diagnostics.Trace.WriteLine("Sent joined...");
|
||||
}
|
||||
|
||||
private void WriteEntity(NetIncomingMessage message, NetConnection sender)
|
||||
{
|
||||
string entityType = message.ReadString();
|
||||
string owner = message.ReadString();
|
||||
Vector2 pos = message.ReadVector2();
|
||||
Vector2 velocity = message.ReadVector2();
|
||||
float angle = message.ReadFloat();
|
||||
|
||||
WriteEntityPacket(sender, entityType, owner, ref pos, ref velocity, angle);
|
||||
}
|
||||
|
||||
private void WriteEntityPacket(NetConnection connectionToExclude, string entityType, string owner, ref Vector2 pos, ref Vector2 velocity, float angle)
|
||||
{
|
||||
var message = _server.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.EntityCreated);
|
||||
message.Write(entityType);
|
||||
message.Write(owner);
|
||||
message.Write(pos);
|
||||
message.Write(velocity);
|
||||
message.Write(angle);
|
||||
|
||||
_server.SendToAll(message, connectionToExclude, NetDeliveryMethod.UnreliableSequenced, 1);
|
||||
}
|
||||
|
||||
private void WritePlayerUpdate(NetIncomingMessage message, NetConnection sender)
|
||||
{
|
||||
string owner = message.ReadString();
|
||||
int colorIndex = message.ReadInt32();
|
||||
Vector2 pos = message.ReadVector2();
|
||||
Vector2 velocity = message.ReadVector2();
|
||||
float angle = message.ReadFloat();
|
||||
|
||||
WritePlayerUpdatePacket(sender, owner, colorIndex, ref pos, ref velocity, angle);
|
||||
}
|
||||
|
||||
private void WritePlayerUpdatePacket(NetConnection connectionToExclude, string owner, int colorIndex, ref Vector2 pos, ref Vector2 velocity, float angle)
|
||||
{
|
||||
var message = _server.CreateMessage();
|
||||
|
||||
message.Write((int)UdpNetworkPacketType.PlayerUpdate);
|
||||
message.Write(owner);
|
||||
message.Write(colorIndex);
|
||||
message.Write(pos);
|
||||
message.Write(velocity);
|
||||
message.Write(angle);
|
||||
|
||||
_server.SendToAll(message, connectionToExclude, NetDeliveryMethod.UnreliableSequenced, 1);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user