Basic multiplayer pong.

This commit is contained in:
Michael 2017-05-03 11:51:56 -04:00
parent 53631ad42d
commit 24f04e3e12
3 changed files with 367 additions and 115 deletions

View file

@ -124,6 +124,7 @@ namespace ShiftOS.WinForms.Applications
this.lblstatscodepoints = new System.Windows.Forms.Label();
this.lblstatsY = new System.Windows.Forms.Label();
this.lblstatsX = new System.Windows.Forms.Label();
this.btnmatchmake = new System.Windows.Forms.Button();
this.pgcontents.SuspendLayout();
this.pnlhighscore.SuspendLayout();
this.flowLayoutPanel1.SuspendLayout();
@ -157,11 +158,11 @@ namespace ShiftOS.WinForms.Applications
// pgcontents
//
this.pgcontents.BackColor = System.Drawing.Color.White;
this.pgcontents.Controls.Add(this.pnlintro);
this.pgcontents.Controls.Add(this.pnlhighscore);
this.pgcontents.Controls.Add(this.pnlgamestats);
this.pgcontents.Controls.Add(this.pnlfinalstats);
this.pgcontents.Controls.Add(this.pnllose);
this.pgcontents.Controls.Add(this.pnlintro);
this.pgcontents.Controls.Add(this.lblbeatai);
this.pgcontents.Controls.Add(this.lblcountdown);
this.pgcontents.Controls.Add(this.ball);
@ -197,6 +198,7 @@ namespace ShiftOS.WinForms.Applications
this.lbhighscore.Name = "lbhighscore";
this.lbhighscore.Size = new System.Drawing.Size(539, 246);
this.lbhighscore.TabIndex = 1;
this.lbhighscore.UseCompatibleStateImageBehavior = false;
//
// flowLayoutPanel1
//
@ -525,10 +527,11 @@ namespace ShiftOS.WinForms.Applications
//
// pnlintro
//
this.pnlintro.Controls.Add(this.btnmatchmake);
this.pnlintro.Controls.Add(this.Label6);
this.pnlintro.Controls.Add(this.btnstartgame);
this.pnlintro.Controls.Add(this.Label8);
this.pnlintro.Location = new System.Drawing.Point(1139, 41);
this.pnlintro.Location = new System.Drawing.Point(0, 0);
this.pnlintro.Name = "pnlintro";
this.pnlintro.Size = new System.Drawing.Size(595, 303);
this.pnlintro.TabIndex = 13;
@ -539,7 +542,7 @@ namespace ShiftOS.WinForms.Applications
this.Label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Label6.Location = new System.Drawing.Point(3, 39);
this.Label6.Name = "Label6";
this.Label6.Size = new System.Drawing.Size(589, 227);
this.Label6.Size = new System.Drawing.Size(589, 159);
this.Label6.TabIndex = 15;
this.Label6.Text = "{PONG_DESC}";
this.Label6.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
@ -548,7 +551,7 @@ namespace ShiftOS.WinForms.Applications
// btnstartgame
//
this.btnstartgame.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnstartgame.Location = new System.Drawing.Point(186, 273);
this.btnstartgame.Location = new System.Drawing.Point(188, 215);
this.btnstartgame.Name = "btnstartgame";
this.btnstartgame.Size = new System.Drawing.Size(242, 28);
this.btnstartgame.TabIndex = 15;
@ -672,6 +675,17 @@ namespace ShiftOS.WinForms.Applications
this.lblstatsX.Text = "Xspeed: ";
this.lblstatsX.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// btnmatchmake
//
this.btnmatchmake.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnmatchmake.Location = new System.Drawing.Point(188, 253);
this.btnmatchmake.Name = "btnmatchmake";
this.btnmatchmake.Size = new System.Drawing.Size(242, 28);
this.btnmatchmake.TabIndex = 16;
this.btnmatchmake.Text = "Or, play against another Shifter!";
this.btnmatchmake.UseVisualStyleBackColor = true;
this.btnmatchmake.Click += new System.EventHandler(this.btnmatchmake_Click);
//
// Pong
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -750,5 +764,6 @@ namespace ShiftOS.WinForms.Applications
internal System.Windows.Forms.Label label12;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.Button button2;
internal System.Windows.Forms.Button btnmatchmake;
}
}

View file

@ -82,7 +82,23 @@ namespace ShiftOS.WinForms.Applications
private void pongMain_MouseMove(object sender, MouseEventArgs e)
{
var loc = this.PointToClient(MousePosition);
paddleHuman.Location = new Point(paddleHuman.Location.X, (loc.Y) - (paddleHuman.Height / 2));
if (IsMultiplayerSession)
{
if (IsLeader)
{
paddleHuman.Location = new Point(paddleHuman.Location.X, (loc.Y) - (paddleHuman.Height / 2));
ServerManager.Forward(OpponentGUID, "pong_mp_setopponenty", paddleHuman.Top.ToString());
}
else
{
paddleComputer.Location = new Point(paddleComputer.Location.X, (loc.Y) - (paddleComputer.Height / 2));
ServerManager.Forward(OpponentGUID, "pong_mp_setopponenty", paddleComputer.Top.ToString());
}
}
else
{
paddleHuman.Location = new Point(paddleHuman.Location.X, (loc.Y) - (paddleHuman.Height / 2));
}
}
private void CenterPanels()
@ -104,7 +120,13 @@ namespace ShiftOS.WinForms.Applications
lblstatscodepoints.Top = this.Height - lblstatscodepoints.Height - 5;
lblstatscodepoints.Left = (this.Width - lblstatscodepoints.Width) / 2;
}
int OpponentY = 0;
bool IsLeader = false;
int LeaderX = 0;
int LeaderY = 0;
// ERROR: Handles clauses are not supported in C#
private void gameTimer_Tick(object sender, EventArgs e)
@ -118,39 +140,50 @@ namespace ShiftOS.WinForms.Applications
//Check if paddle upgrade has been bought and change paddles accordingly
//if (ShiftoriumFrontend.UpgradeInstalled("pong_increased_paddle_size"))
//{
// paddleHuman.Height = 150;
// paddleComputer.Height = 150;
// paddleHuman.Height = 150;
// paddleComputer.Height = 150;
//}
//I don't know the point of this but I'm fucking 86ing it. - Michael
//Set the computer player to move according to the ball's position.
if (aiShouldIsbeEnabled)
if (ball.Location.X > (this.Width - (this.Width / 3)) - xVel * 10 && xVel > 0)
{
if (ball.Location.Y > paddleComputer.Location.Y + 50)
{
paddleComputer.Location = new Point(paddleComputer.Location.X, paddleComputer.Location.Y + computerspeed);
}
if (ball.Location.Y < paddleComputer.Location.Y + 50)
{
paddleComputer.Location = new Point(paddleComputer.Location.X, paddleComputer.Location.Y - computerspeed);
}
casualposition = rand.Next(-150, 201);
}
if (IsMultiplayerSession == true)
{
//If we're multiplayer, then we want to set the computer Y to the opponent's Y.
//If we're the leader, we set the AI paddle, else we set the player paddle.
if (IsLeader)
paddleComputer.Top = OpponentY;
else
{
//used to be me.location.y - except it's fucking C# and this comment is misleading as fuck. OH WAIT! I didn't write it! And none of the current devs did either! - Michael
if (paddleComputer.Location.Y > this.Size.Height / 2 - paddleComputer.Height + casualposition)
paddleHuman.Top = OpponentY;
}
else
{
if (aiShouldIsbeEnabled)
if (ball.Location.X > (this.Width - (this.Width / 3)) - xVel * 10 && xVel > 0)
{
paddleComputer.Location = new Point(paddleComputer.Location.X, paddleComputer.Location.Y - computerspeed);
if (ball.Location.Y > paddleComputer.Location.Y + 50)
{
paddleComputer.Location = new Point(paddleComputer.Location.X, paddleComputer.Location.Y + computerspeed);
}
if (ball.Location.Y < paddleComputer.Location.Y + 50)
{
paddleComputer.Location = new Point(paddleComputer.Location.X, paddleComputer.Location.Y - computerspeed);
}
casualposition = rand.Next(-150, 201);
}
//Rylan is hot. Used to be //used to be me.location.y
if (paddleComputer.Location.Y < this.Size.Height / 2 - paddleComputer.Height + casualposition)
else
{
paddleComputer.Location = new Point(paddleComputer.Location.X, paddleComputer.Location.Y + computerspeed);
//used to be me.location.y - except it's fucking C# and this comment is misleading as fuck. OH WAIT! I didn't write it! And none of the current devs did either! - Michael
if (paddleComputer.Location.Y > this.Size.Height / 2 - paddleComputer.Height + casualposition)
{
paddleComputer.Location = new Point(paddleComputer.Location.X, paddleComputer.Location.Y - computerspeed);
}
//Rylan is hot. Used to be //used to be me.location.y
if (paddleComputer.Location.Y < this.Size.Height / 2 - paddleComputer.Height + casualposition)
{
paddleComputer.Location = new Point(paddleComputer.Location.X, paddleComputer.Location.Y + computerspeed);
}
}
}
}
//Set Xvel and Yvel speeds from decimal
if (xVel > 0)
xVel = (int)Math.Round(xveldec);
@ -161,121 +194,292 @@ namespace ShiftOS.WinForms.Applications
if (yVel < 0)
yVel = (int)-Math.Round(yveldec);
// Move the game ball.
ball.Location = new Point(ball.Location.X + xVel, ball.Location.Y + yVel);
bool BallPhysics = true;
// Check for top wall.
if (ball.Location.Y < 0)
if (IsMultiplayerSession)
{
ball.Location = new Point(ball.Location.X, 0);
yVel = -yVel;
ShiftOS.Engine.AudioManager.PlayStream(Properties.Resources.typesound);
}
// Check for bottom wall.
if (ball.Location.Y > pgcontents.Height - ball.Height)
{
ball.Location = new Point(ball.Location.X, pgcontents.Height - ball.Size.Height);
yVel = -yVel;
ShiftOS.Engine.AudioManager.PlayStream(Properties.Resources.typesound);
}
// Check for player paddle.
if (ball.Bounds.IntersectsWith(paddleHuman.Bounds))
{
ball.Location = new Point(paddleHuman.Location.X + ball.Size.Width + 1, ball.Location.Y);
//randomly increase x or y speed of ball
switch (rand.Next(1, 3))
//Logic for moving the ball in Multiplayer.
if (IsLeader)
{
case 1:
xveldec = xveldec + incrementx;
break;
case 2:
if (yveldec > 0)
yveldec = yveldec + incrementy;
if (yveldec < 0)
yveldec = yveldec - incrementy;
break;
ball.Location = new Point(ball.Location.X + xVel, ball.Location.Y + yVel);
}
else
{
//Move it to the leader's ball position.
ball.Location = new Point(LeaderX, LeaderY);
BallPhysics = false;
}
xVel = -xVel;
ShiftOS.Engine.AudioManager.PlayStream(Properties.Resources.writesound);
}
// Check for computer paddle.
if (ball.Bounds.IntersectsWith(paddleComputer.Bounds))
else
{// Move the game ball.
ball.Location = new Point(ball.Location.X + xVel, ball.Location.Y + yVel);
}
if (BallPhysics)
{
ball.Location = new Point(paddleComputer.Location.X - paddleComputer.Size.Width - 1, ball.Location.Y);
xveldec = xveldec + incrementx;
xVel = -xVel;
ShiftOS.Engine.AudioManager.PlayStream(Properties.Resources.writesound);
// Check for top wall.
if (ball.Location.Y < 0)
{
ball.Location = new Point(ball.Location.X, 0);
yVel = -yVel;
ShiftOS.Engine.AudioManager.PlayStream(Properties.Resources.typesound);
}
// Check for bottom wall.
if (ball.Location.Y > pgcontents.Height - ball.Height)
{
ball.Location = new Point(ball.Location.X, pgcontents.Height - ball.Size.Height);
yVel = -yVel;
ShiftOS.Engine.AudioManager.PlayStream(Properties.Resources.typesound);
}
// Check for player paddle.
if (ball.Bounds.IntersectsWith(paddleHuman.Bounds))
{
ball.Location = new Point(paddleHuman.Location.X + ball.Size.Width + 1, ball.Location.Y);
//randomly increase x or y speed of ball
switch (rand.Next(1, 3))
{
case 1:
xveldec = xveldec + incrementx;
break;
case 2:
if (yveldec > 0)
yveldec = yveldec + incrementy;
if (yveldec < 0)
yveldec = yveldec - incrementy;
break;
}
xVel = -xVel;
ShiftOS.Engine.AudioManager.PlayStream(Properties.Resources.writesound);
}
// Check for computer paddle.
if (ball.Bounds.IntersectsWith(paddleComputer.Bounds))
{
ball.Location = new Point(paddleComputer.Location.X - paddleComputer.Size.Width - 1, ball.Location.Y);
xveldec = xveldec + incrementx;
xVel = -xVel;
ShiftOS.Engine.AudioManager.PlayStream(Properties.Resources.writesound);
}
}
// Check for left wall.
if (ball.Location.X < -100)
{
ball.Location = new Point(this.Size.Width / 2 + 200, this.Size.Height / 2);
paddleComputer.Location = new Point(paddleComputer.Location.X, ball.Location.Y);
if (xVel > 0)
xVel = -xVel;
pnllose.Show();
gameTimer.Stop();
counter.Stop();
lblmissedout.Text = Localization.Parse("{YOU_MISSED_OUT_ON}:") + Environment.NewLine + lblstatscodepoints.Text.Replace(Localization.Parse("{CODEPOINTS}: "), "") + Localization.Parse(" {CODEPOINTS}");
if (ShiftoriumFrontend.UpgradeInstalled("pong_upgrade_2"))
//If we are in multiplayer, and not the leader, we won.
if (IsMultiplayerSession)
{
totalreward = levelrewards[level - 1] + beatairewardtotal;
double onePercent = (totalreward / 100);
lblbutyougained.Show();
lblbutyougained.Text = Localization.Parse("{BUT_YOU_GAINED}:") + Environment.NewLine + onePercent.ToString("") + (Localization.Parse(" {CODEPOINTS}"));
SaveSystem.TransferCodepointsFrom("pong", (totalreward / 100));
if (IsLeader)
{
//We lost.
NotifyLoseToTarget();
}
else
{
//We won.
NotifyWinToTarget();
Win();
}
}
else
{
lblbutyougained.Hide();
ball.Location = new Point(this.Size.Width / 2 + 200, this.Size.Height / 2);
paddleComputer.Location = new Point(paddleComputer.Location.X, ball.Location.Y);
if (xVel > 0)
xVel = -xVel;
pnllose.Show();
gameTimer.Stop();
counter.Stop();
lblmissedout.Text = Localization.Parse("{YOU_MISSED_OUT_ON}:") + Environment.NewLine + lblstatscodepoints.Text.Replace(Localization.Parse("{CODEPOINTS}: "), "") + Localization.Parse(" {CODEPOINTS}");
if (ShiftoriumFrontend.UpgradeInstalled("pong_upgrade_2"))
{
totalreward = levelrewards[level - 1] + beatairewardtotal;
double onePercent = (totalreward / 100);
lblbutyougained.Show();
lblbutyougained.Text = Localization.Parse("{BUT_YOU_GAINED}:") + Environment.NewLine + onePercent.ToString("") + (Localization.Parse(" {CODEPOINTS}"));
SaveSystem.TransferCodepointsFrom("pong", (totalreward / 100));
}
else
{
lblbutyougained.Hide();
}
}
}
// Check for right wall.
if (ball.Location.X > this.Width - ball.Size.Width - paddleComputer.Width + 100)
{
ball.Location = new Point(this.Size.Width / 2 + 200, this.Size.Height / 2);
paddleComputer.Location = new Point(paddleComputer.Location.X, ball.Location.Y);
if (xVel > 0)
xVel = -xVel;
beatairewardtotal = beatairewardtotal + beataireward;
lblbeatai.Show();
lblbeatai.Text = Localization.Parse($"{{PONG_BEAT_AI_REWARD_SECONDARY}}: {beataireward}");
tmrcountdown.Start();
gameTimer.Stop();
counter.Stop();
if (IsMultiplayerSession)
{
//If we are the leader we won.
if (IsLeader)
{
NotifyWinToTarget();
Win();
}
else
{
NotifyLoseToTarget();
}
}
else
{
Win();
}
}
//lblstats.Text = "Xspeed: " & Math.Abs(xVel) & " Yspeed: " & Math.Abs(yVel) & " Human Location: " & paddleHuman.Location.ToString & " Computer Location: " & paddleComputer.Location.ToString & Environment.NewLine & " Ball Location: " & ball.Location.ToString & " Xdec: " & xveldec & " Ydec: " & yveldec & " Xinc: " & incrementx & " Yinc: " & incrementy
lblstatsX.Text = Localization.Parse("{H_VEL}: ") + xveldec;
lblstatsY.Text = Localization.Parse("{V_VEL}: ") + yveldec;
lblstatscodepoints.Text = Localization.Parse("{CODEPOINTS}: ") + (levelrewards[level - 1] + beatairewardtotal).ToString();
lbllevelandtime.Text = Localization.Parse("{LEVEL}: " + level + " - " + secondsleft + " {SECONDS_LEFT}");
if (xVel > 20 || xVel < -20)
if (IsMultiplayerSession)
{
paddleHuman.Width = Math.Abs(xVel);
paddleComputer.Width = Math.Abs(xVel);
if (IsLeader)
{
ServerManager.Forward(OpponentGUID, "pong_mp_setballpos", JsonConvert.SerializeObject(ball.Location));
}
}
else
if (IsLeader)
{
paddleHuman.Width = 20;
paddleComputer.Width = 20;
//lblstats.Text = "Xspeed: " & Math.Abs(xVel) & " Yspeed: " & Math.Abs(yVel) & " Human Location: " & paddleHuman.Location.ToString & " Computer Location: " & paddleComputer.Location.ToString & Environment.NewLine & " Ball Location: " & ball.Location.ToString & " Xdec: " & xveldec & " Ydec: " & yveldec & " Xinc: " & incrementx & " Yinc: " & incrementy
lblstatsX.Text = Localization.Parse("{H_VEL}: ") + xveldec;
lblstatsY.Text = Localization.Parse("{V_VEL}: ") + yveldec;
lblstatscodepoints.Text = Localization.Parse("{CODEPOINTS}: ") + (levelrewards[level - 1] + beatairewardtotal).ToString();
lbllevelandtime.Text = Localization.Parse("{LEVEL}: " + level + " - " + secondsleft + " {SECONDS_LEFT}");
if (xVel > 20 || xVel < -20)
{
paddleHuman.Width = Math.Abs(xVel);
paddleComputer.Width = Math.Abs(xVel);
}
else
{
paddleHuman.Width = 20;
paddleComputer.Width = 20;
}
}
if (!IsMultiplayerSession)
{
computerspeed = Math.Abs(yVel);
}
computerspeed = Math.Abs(yVel);
// pgcontents.Refresh()
// pgcontents.CreateGraphics.FillRectangle(Brushes.Black, ball.Location.X, ball.Location.Y, ball.Width, ball.Height)
}
}
public void ServerMessageReceivedHandler(ServerMessage msg)
{
if(msg.Name == "pong_mp_setballpos")
{
var pt = JsonConvert.DeserializeObject<Point>(msg.Contents);
LeaderX = pt.X;
LeaderY = pt.Y;
}
else if(msg.Name == "pong_mp_youlose")
{
LoseMP();
}
else if(msg.Name == "pong_mp_setopponenty")
{
int y = Convert.ToInt32(msg.Contents);
OpponentY = y;
}
else if(msg.Name == "pong_handshake_matchmake")
{
PossibleMatchmakes.Add(msg.Contents);
}
else if(msg.Name == "pong_handshake_complete")
{
LeaveMatchmake();
StartLevel();
}
else if(msg.Name == "pong_handshake_giveleaderid")
{
IsLeader = false;
OpponentGUID = msg.Contents;
YouGUID = ServerManager.thisGuid.ToString();
SendFollowerGUID();
}
else if(msg.Name == "pong_handshake_left")
{
if (this.PossibleMatchmakes.Contains(msg.Contents))
this.PossibleMatchmakes.Remove(msg.Contents);
}
else if(msg.Name == "pong_handshake_setfollowerguid")
{
IsLeader = false;
OpponentGUID = msg.Contents;
}
else if(msg.Name == "pong_mp_youwin")
{
Win();
}
}
public void NotifyLoseToTarget()
{
ServerManager.Forward(OpponentGUID, "pong_mp_youwin", null);
}
public void NotifyWinToTarget()
{
ServerManager.Forward(OpponentGUID, "pong_mp_youlose", null);
}
public void LeaveMatchmake()
{
ServerManager.Forward("all", "pong_handshake_left", YouGUID);
}
List<string> PossibleMatchmakes = new List<string>();
public void SendLeaderGUID()
{
ServerManager.Forward(OpponentGUID, "pong_handshake_giveleaderid", YouGUID);
}
public void StartMultiplayer()
{
IsMultiplayerSession = true;
YouGUID = ServerManager.thisGuid.ToString();
ServerManager.SendMessage("pong_handshake_matchmake", YouGUID);
}
public void SendFollowerGUID()
{
ServerManager.Forward(OpponentGUID, "pong_handshake_setfollowerguid", YouGUID);
}
public void LoseMP()
{
ball.Location = new Point(this.Size.Width / 2 + 200, this.Size.Height / 2);
if(IsLeader)
if (xVel > 0)
xVel = -xVel;
lblbeatai.Show();
lblbeatai.Text = "The opponent has beaten you!";
tmrcountdown.Start();
gameTimer.Stop();
counter.Stop();
}
public void Win()
{
ball.Location = new Point(this.Size.Width / 2 + 200, this.Size.Height / 2);
paddleComputer.Location = new Point(paddleComputer.Location.X, ball.Location.Y);
if (xVel > 0)
xVel = -xVel;
beatairewardtotal = beatairewardtotal + beataireward;
lblbeatai.Show();
lblbeatai.Text = Localization.Parse($"{{PONG_BEAT_AI_REWARD_SECONDARY}}: {beataireward}");
tmrcountdown.Start();
gameTimer.Stop();
counter.Stop();
}
// ERROR: Handles clauses are not supported in C#
private void counter_Tick(object sender, EventArgs e)
{
@ -606,6 +810,11 @@ namespace ShiftOS.WinForms.Applications
SetupHighScores();
}
bool IsMultiplayerSession = false;
string YouGUID = "";
string OpponentGUID = "";
public void SetupHighScores()
{
lbhighscore.Items.Clear();
@ -668,6 +877,11 @@ namespace ShiftOS.WinForms.Applications
newgame();
}
public void StartLevel()
{
newgame();
}
// ERROR: Handles clauses are not supported in C#
private void btnstartgame_Click(object sender, EventArgs e)
{
@ -750,5 +964,14 @@ namespace ShiftOS.WinForms.Applications
{
pnlhighscore.Hide();
}
private void btnmatchmake_Click(object sender, EventArgs e)
{
this.StartMultiplayer();
pnlintro.Hide();
lblbeatai.Text = "Beat the other player to earn Codepoints.";
lblcountdown.Text = "Waiting for another player...";
lblcountdown.Left = (this.Width - lblcountdown.Width) / 2;
}
}
}

View file

@ -172,6 +172,10 @@ namespace ShiftOS.Engine
{
Console.WriteLine(msg.Contents);
}
else if(msg.Name == "forward")
{
MessageReceived?.Invoke(JsonConvert.DeserializeObject<ServerMessage>(msg.Contents));
}
else if (msg.Name == "Error")
{
var ex = JsonConvert.DeserializeObject<Exception>(msg.Contents);
@ -239,6 +243,16 @@ namespace ShiftOS.Engine
public static event ServerMessageReceived MessageReceived;
public static void Forward(string targetGUID, string v, string message)
{
var smsg = new ServerMessage
{
GUID = targetGUID,
Name = v,
Contents = message
};
ServerManager.SendMessage("mud_forward", JsonConvert.SerializeObject(smsg));
}
}
public delegate void ServerMessageReceived(ServerMessage msg);