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.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Storage;
using SpacePew.Models;
namespace SpacePew.Networking
{
///
/// 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)
///
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 _messages;
private const int DefaultMessageLifeTime = 10;
public NetworkMessenger(MainGame game, UdpClient client)
: base(game)
{
_game = game;
_client = client;
_messages = new List();
}
///
/// 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.
///
public override void Initialize()
{
_spriteBatch = new SpriteBatch(_game.GraphicsDevice);
_netFont = _game.Content.Load("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;
///
/// Allows the game component to update itself.
///
/// Provides a snapshot of timing values.
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 IDrawable.DrawOrderChanged
{
add { }
remove { }
}
event EventHandler IDrawable.VisibleChanged
{
add { }
remove { }
}
}
}