diff --git a/ShiftOS.WinForms/Applications/Pong.Designer.cs b/ShiftOS.WinForms/Applications/Pong.Designer.cs index aef8911..b1186c6 100644 --- a/ShiftOS.WinForms/Applications/Pong.Designer.cs +++ b/ShiftOS.WinForms/Applications/Pong.Designer.cs @@ -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; } } diff --git a/ShiftOS.WinForms/Applications/Pong.cs b/ShiftOS.WinForms/Applications/Pong.cs index e0fe793..585639a 100644 --- a/ShiftOS.WinForms/Applications/Pong.cs +++ b/ShiftOS.WinForms/Applications/Pong.cs @@ -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(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 PossibleMatchmakes = new List(); + + 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; + } } } diff --git a/ShiftOS_TheReturn/ServerManager.cs b/ShiftOS_TheReturn/ServerManager.cs index d356600..0bdfcd9 100644 --- a/ShiftOS_TheReturn/ServerManager.cs +++ b/ShiftOS_TheReturn/ServerManager.cs @@ -172,6 +172,10 @@ namespace ShiftOS.Engine { Console.WriteLine(msg.Contents); } + else if(msg.Name == "forward") + { + MessageReceived?.Invoke(JsonConvert.DeserializeObject(msg.Contents)); + } else if (msg.Name == "Error") { var ex = JsonConvert.DeserializeObject(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);