]> Dogcows Code - chaz/carfire/blob - Project06/CS 3505 Project 06/CS 3505 Project 06/NetworkGame.cs
cleaned up some comments I was making during testing
[chaz/carfire] / Project06 / CS 3505 Project 06 / CS 3505 Project 06 / NetworkGame.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using Microsoft.Xna.Framework.Net;
6 using System.Diagnostics;
7 using Microsoft.Xna.Framework.GamerServices;
8 using Microsoft.Xna.Framework.Graphics;
9 using Microsoft.Xna.Framework;
10 using Microsoft.Xna.Framework.Input;
11 using System.Collections;
12
13 namespace CS_3505_Project_06
14 {
15 /// <summary>
16 /// A manager class to handle network interactions between peers and
17 /// lobby/game switching.
18 /// </summary>
19 public class NetworkGame
20 {
21 // Public methods and properties
22 #region Public Methods
23
24 /// <summary>
25 /// Called when a session has been created or joined using CreateSession() or JoinSession().
26 /// </summary>
27 /// <param name="session">The new session that was created or joined.</param>
28 /// <param name="networkGame">The NetworkGame that joined the session.</param>
29 public delegate void JoinedSessionDelegate(NetworkSession session, NetworkGame networkGame);
30
31 /// <summary>
32 /// Called when sessions are found as a result of calling FindSessions().
33 /// </summary>
34 /// <param name="sessions">A container of the available sessions.</param>
35 /// <param name="networkGame">The NetworkGame that searched for the sessions.</param>
36 public delegate void FoundSessionsDelegate(AvailableNetworkSessionCollection sessions, NetworkGame networkGame);
37
38
39 /// <summary>
40 /// Construct a NetworkGame with a lobby and a game.
41 /// </summary>
42 /// <param name="lobby">Provides an associated lobby to update and draw.</param>
43 /// <param name="game">Provides a game object to be played over the network.</param>
44 public NetworkGame(ILobby lobby, IDeterministicGame game)
45 {
46 Debug.Assert(lobby != null && game != null);
47
48 mLobby = lobby;
49 mGame = game;
50 }
51
52
53 /// <summary>
54 /// Get the Gamer object for the local player.
55 /// </summary>
56 public LocalNetworkGamer LocalGamer
57 {
58 get
59 {
60 // TODO: Is this the correct way to get the single local gamer?
61 return mNetworkSession.LocalGamers[0];
62 }
63 }
64
65 /// <summary>
66 /// Get all the gamers associated with the active network session.
67 /// </summary>
68 public GamerCollection<NetworkGamer> NetworkGamers
69 {
70 get
71 {
72 return mNetworkSession.AllGamers;
73 }
74 }
75
76
77 /// <summary>
78 /// Begin a new network session with the local gamer as the host. You must not
79 /// call this method or use JoinSession without first using LeaveSession.
80 /// </summary>
81 /// <param name="callback">The delegate/method to call when the session is created.</param>
82 public void CreateSession(JoinedSessionDelegate callback)
83 {
84 CreateSession(mGame.MaximumSupportedPlayers, callback);
85 }
86
87 /// <summary>
88 /// Begin a new network session with the local gamer as the host. You must not
89 /// call this method or use JoinSession without first using LeaveSession.
90 /// </summary>
91 /// <param name="maxGamers">Provide the maximum number of players allowed to connect.</param>
92 /// <param name="callback">The delegate/method to call when the session is created.</param>
93 public void CreateSession(int maxGamers, JoinedSessionDelegate callback)
94 {
95 Debug.Assert(mNetworkSession == null);
96
97 mJoinedSessionDelegate = callback;
98 NetworkSession.BeginCreate(NetworkSessionType.SystemLink, 1, maxGamers, CreateSessionEnd, null);
99 }
100 private void CreateSessionEnd(IAsyncResult result)
101 {
102 Debug.Assert(mNetworkSession == null);
103
104 mNetworkSession = NetworkSession.EndCreate(result);
105 mNetworkSession.AllowHostMigration = true;
106 mNetworkSession.AllowJoinInProgress = false;
107 mNetworkSession.GameStarted += new EventHandler<GameStartedEventArgs>(mNetworkSession_GameStarted);
108 mJoinedSessionDelegate(mNetworkSession, this);
109 }
110
111
112 //gamestarted event
113 void mNetworkSession_GameStarted(object sender, GameStartedEventArgs e)
114 {
115 Reset();
116 }
117
118 /// <summary>
119 /// Determine whether or not the network game object is associated with any network session.
120 /// </summary>
121 /// <returns>True if there exists a NetworkSession; false otherwise.</returns>
122 public bool HasActiveSession
123 {
124 get
125 {
126 return mNetworkSession != null;
127 }
128 }
129
130
131 /// <summary>
132 /// Find available sessions to join. You should not already be in a session when
133 /// calling this method; call LeaveSession first.
134 /// </summary>
135 /// <param name="callback">The delegate/method to call when the search finishes.</param>
136 public void FindSessions(FoundSessionsDelegate callback)
137 {
138 Debug.Assert(mNetworkSession == null);
139
140 mFoundSessionsDelegate = callback;
141 NetworkSession.BeginFind(NetworkSessionType.SystemLink, 1, null, new AsyncCallback(FindSessionsEnd), null);
142 }
143 private void FindSessionsEnd(IAsyncResult result)
144 {
145 AvailableNetworkSessionCollection sessions = NetworkSession.EndFind(result);
146 mFoundSessionsDelegate(sessions, this);
147 }
148
149 /// <summary>
150 /// Join a network session found using FindSessions(). This is for joining a game that
151 /// somebody else has already started hosting. You must not already be in a session.
152 /// </summary>
153 /// <param name="availableSession">Pass the session object to try to join.</param>
154 /// <param name="callback">The delegate/method to call when the search finishes.</param>
155 public void JoinSession(AvailableNetworkSession availableSession, JoinedSessionDelegate callback)
156 {
157 Debug.Assert(mNetworkSession == null);
158
159 mJoinedSessionDelegate = callback;
160 NetworkSession.BeginJoin(availableSession, JoinSessionEnd, null);
161 }
162 private void JoinSessionEnd(IAsyncResult result)
163 {
164 Debug.Assert(mNetworkSession == null);
165
166 mNetworkSession = NetworkSession.EndJoin(result);
167
168 mJoinedSessionDelegate(mNetworkSession, this);
169 mJoinedSessionDelegate = null;
170
171 mNetworkSession.GameStarted += new EventHandler<GameStartedEventArgs>(mNetworkSession_GameStarted);
172 }
173
174
175 /// <summary>
176 /// Leave and dispose of any currently associated network session. You will find yourself
177 /// back in the lobby. You must already be in a session to leave it.
178 /// </summary>
179 public void LeaveSession()
180 {
181 Debug.Assert(mNetworkSession != null);
182
183 mNetworkSession.Dispose();
184 mNetworkSession = null;
185 }
186
187
188 /// <summary>
189 /// Set up the network session to simulate 200ms latency and 10% packet loss.
190 /// </summary>
191 public void SimulateBadNetwork()
192 {
193 Debug.Assert(mNetworkSession != null);
194
195 mNetworkSession.SimulatedLatency = new TimeSpan(0, 0, 0, 0, 200);
196 mNetworkSession.SimulatedPacketLoss = 0.1f;
197 }
198
199
200 /// <summary>
201 /// Indicate that the game should begin (moving players from the lobby to the game).
202 /// You must call CreateSession() before calling this.
203 /// </summary>
204 public void StartGame()
205 {
206 Debug.Assert(mNetworkSession != null && mNetworkSession.IsHost &&
207 mNetworkSession.AllGamers.Count >= mGame.MinimumSupportedPlayers &&
208 mNetworkSession.IsEveryoneReady);
209
210 ForceStartGame();
211 }
212
213 /// <summary>
214 /// Indicate that the game should begin. This is like StartGame() without the sanity
215 /// checks. Use this for debugging.
216 /// </summary>
217 public void ForceStartGame()
218 {
219 mNetworkSession.StartGame();
220 mNetworkSession.ResetReady();
221
222 //Reset();
223 }
224
225
226 /// <summary>
227 /// Manages the network session and allows either the lobby or game to update.
228 /// </summary>
229 /// <param name="gameTime">Pass the time away.</param>
230 public void Update(GameTime gameTime)
231 {
232 if (mNetworkSession == null)
233 {
234 mLobby.Update(gameTime, this);
235 }
236 else
237 {
238 mNetworkSession.Update();
239 HandleIncomingPackets();
240
241 if (mNetworkSession.SessionState == NetworkSessionState.Lobby)
242 {
243 mLobby.Update(gameTime, this);
244 }
245 else if (mNetworkSession.SessionState == NetworkSessionState.Playing)
246 {
247 if (mGame.IsGameOver(LocalGamerInfo) || mGame.IsTerminated(LocalGamerInfo))
248 {
249 // TODO: Should support moving back to the session lobby.
250 LeaveSession();
251 return;
252 }
253
254 if (HaveNeededEvents)
255 {
256 if (IsLatencyAdjustmentFrame)
257 {
258 AdjustLatency();
259 mStallCount = 0;
260 }
261 mLocalEvents.AddRange(GetEventsFromInput());
262 SendLocalEvents();
263 ApplyEvents();
264 mGame.Update(mTargetTimeSpan);
265 }
266 else // Stall!
267 {
268 mStallCount++;
269
270 if (mStallCount % 60 == 0)
271 {
272 Console.WriteLine("Stalled for " + mStallCount + " frames.");
273 }
274
275 /*if (mStallCount > StallTimeout)
276 {
277 DropLostGamers();
278 mStallCount = 0;
279 }
280 else if (mStallCount == 1)
281 {
282 SendLocalEvents
283 }
284 else if (mStallCount % 60 == 0)
285 {
286 } TODO */
287 }
288 }
289 }
290 }
291
292 /// <summary>
293 /// Allows either the lobby or the game to draw, depending on the state
294 /// of the network connection and whether or not a game is in progress.
295 /// </summary>
296 /// <param name="gameTime">Pass the time away.</param>
297 /// <param name="spriteBatch">The sprite batch.</param>
298 public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
299 {
300 if (mNetworkSession == null)
301 {
302 mLobby.Draw(spriteBatch);
303 }
304 else
305 {
306 if (mNetworkSession.SessionState == NetworkSessionState.Lobby)
307 {
308 mLobby.Draw(spriteBatch);
309 }
310 else if (mNetworkSession.SessionState == NetworkSessionState.Playing)
311 {
312 mGame.Draw(spriteBatch);
313 }
314 }
315 }
316
317
318 /// <summary>
319 /// Get the chat messages that have been receive since the last time this
320 /// method was called.
321 /// </summary>
322 /// <returns>List container of the chat messages.</returns>
323 public List<ChatInfo> ReceiveChats()
324 {
325 List<ChatInfo> chats = mChatPackets;
326 mChatPackets = new List<ChatInfo>();
327 return chats;
328 }
329
330 /// <summary>
331 /// Send a chat message to all gamers in the session. You should already be
332 /// in a session before calling this method.
333 /// </summary>
334 /// <param name="message">The text of the message.</param>
335 public void SendChat(String message)
336 {
337 WriteChatPacket(message);
338 LocalGamer.SendData(mPacketWriter, SendDataOptions.ReliableInOrder);
339 }
340
341 /// <summary>
342 /// Send a chat message to a specific gamer in the session. You should already
343 /// be in a session before calling this method.
344 /// </summary>
345 /// <param name="message">The text of the message.</param>
346 /// <param name="recipient">The gamer to receive the message.</param>
347 public void SendChat(String message, NetworkGamer recipient)
348 {
349 WriteChatPacket(message);
350 LocalGamer.SendData(mPacketWriter, SendDataOptions.ReliableInOrder, recipient);
351 }
352
353 #endregion
354
355
356 // Private class variable members
357 #region Instance Variables
358
359 NetworkSession mNetworkSession;
360 PacketReader mPacketReader = new PacketReader();
361 PacketWriter mPacketWriter = new PacketWriter();
362
363 JoinedSessionDelegate mJoinedSessionDelegate;
364 FoundSessionsDelegate mFoundSessionsDelegate;
365
366 ILobby mLobby;
367 IDeterministicGame mGame;
368
369 List<ChatInfo> mChatPackets = new List<ChatInfo>();
370
371 List<EventInfo> mLocalEvents = new List<EventInfo>();
372 List<EventInfo> mLastLocalEvents = new List<EventInfo>();
373
374 List<Keys> mLastPressedKeys = new List<Keys>();
375 bool mLastLeftButtonPressed;
376 bool mLastRightButtonPressed;
377 bool mLastMiddleButtonPressed;
378 int mLastMousePositionX;
379 int mLastMousePositionY;
380
381 int mLatency;
382 long mNextLatencyAdjustmentFrame;
383 int mStallCount;
384 int mAverageOwd;
385
386 TimeSpan mTargetTimeSpan = new TimeSpan(166666);
387 public TimeSpan TargetTimeSpan
388 {
389 get
390 {
391 return mTargetTimeSpan;
392 }
393 }
394
395 Dictionary<byte, GamerInfo> mGamers;
396 GamerInfo[] GamerArray
397 {
398 get
399 {
400 GamerInfo[] gamerList = mGamers.Values.ToArray();
401 Array.Sort(gamerList, delegate(GamerInfo a, GamerInfo b)
402 {
403 return a.Gamer.Id.CompareTo(b.Gamer.Id);
404 });
405 return gamerList;
406 }
407 }
408 GamerInfo LocalGamerInfo
409 {
410 get
411 {
412 return mGamers[LocalGamer.Id];
413 }
414 }
415
416 #endregion
417
418
419 // Private types for the implementation of the network protocol
420 #region Private Types
421
422 enum PacketType
423 {
424 Chat = 1,
425 Event = 2,
426 Stall = 3
427 }
428
429 enum EventType
430 {
431 KeyDown = 1,
432 KeyUp = 2,
433 MouseDown = 3,
434 MouseUp = 4,
435 MouseMove = 5
436 }
437
438 enum MouseButton
439 {
440 Left = 1,
441 Right = 2,
442 Middle = 3
443 }
444
445 abstract class EventInfo
446 {
447 public NetworkGamer Gamer;
448 public long FrameOfApplication;
449
450 public EventInfo(NetworkGamer gamer, long frameNumber)
451 {
452 Gamer = gamer;
453 FrameOfApplication = frameNumber;
454 }
455
456 public abstract EventType Id
457 {
458 get;
459 }
460 }
461
462 class KeyboardEventInfo : EventInfo
463 {
464 public Keys Key;
465 public bool IsKeyDown;
466
467 public KeyboardEventInfo(NetworkGamer gamer, long frameNumber, Keys key, bool isDown)
468 : base(gamer, frameNumber)
469 {
470 Key = key;
471 IsKeyDown = isDown;
472 }
473
474 public override EventType Id
475 {
476 get { return IsKeyDown ? EventType.KeyDown : EventType.KeyUp; }
477 }
478 }
479
480 class MouseButtonEventInfo : EventInfo
481 {
482 public MouseButton Button;
483 public bool IsButtonDown;
484
485 public MouseButtonEventInfo(NetworkGamer gamer, long frameNumber, MouseButton button, bool isDown)
486 : base(gamer, frameNumber)
487 {
488 Button = button;
489 IsButtonDown = isDown;
490 }
491
492 public override EventType Id
493 {
494 get { return IsButtonDown ? EventType.MouseDown : EventType.MouseUp; }
495 }
496 }
497
498 class MouseMotionEventInfo : EventInfo
499 {
500 public int X;
501 public int Y;
502
503 public MouseMotionEventInfo(NetworkGamer gamer, long frameNumber, int x, int y)
504 : base(gamer, frameNumber)
505 {
506 X = x;
507 Y = y;
508 }
509
510 public override EventType Id
511 {
512 get { return EventType.MouseMove; }
513 }
514 }
515
516 class GamerInfo
517 {
518 public NetworkGamer Gamer;
519 public long HighestFrameNumber = 0;
520 public int StallCount = 0;
521 public int AverageOwd = 0;
522 public bool IsWaitedOn = false;
523 public List<EventInfo>[] Events = new List<EventInfo>[MaximumLatency];
524
525 public GamerInfo(NetworkGamer gamer)
526 {
527 Gamer = gamer;
528 }
529 }
530
531 const int MaximumLatency = 120;
532 const int StallTimeout = 900;
533
534 #endregion
535
536
537 // Private implementation methods of the network protocol
538 #region Private Implementation Methods
539
540 /// <summary>
541 /// Reinitialize the private variables in preparation for a new game to start.
542 /// </summary>
543 void Reset()
544 {
545 mLatency = 1;
546 mNextLatencyAdjustmentFrame = 1;
547 mStallCount = 0;
548 mAverageOwd = CurrentAverageOneWayDelay;
549
550 mGamers = new Dictionary<byte, GamerInfo>();
551 foreach (NetworkGamer gamer in NetworkGamers)
552 {
553 mGamers.Add(gamer.Id, new GamerInfo(gamer));
554 }
555
556 mGame.ResetGame(GamerArray, LocalGamerInfo);
557 }
558
559
560 void HandleIncomingPackets()
561 {
562 LocalNetworkGamer localGamer = LocalGamer;
563
564 while (localGamer.IsDataAvailable)
565 {
566 NetworkGamer sender;
567
568 localGamer.ReceiveData(mPacketReader, out sender);
569 GamerInfo senderInfo = mGamers[sender.Id];
570
571 PacketType packetId = (PacketType)mPacketReader.ReadByte();
572 switch (packetId)
573 {
574 case PacketType.Chat:
575
576 short messageLength = mPacketReader.ReadInt16();
577 char[] message = mPacketReader.ReadChars(messageLength);
578
579 ChatInfo chatPacket = new ChatInfo(sender, new String(message));
580 mChatPackets.Add(chatPacket);
581 break;
582
583 case PacketType.Event:
584
585 short stallCount = mPacketReader.ReadInt16();
586 short averageOwd = mPacketReader.ReadInt16();
587 int frameNumber = mPacketReader.ReadInt32();
588 byte numEvents = mPacketReader.ReadByte();
589
590 if (frameNumber <= senderInfo.HighestFrameNumber)
591 {
592 // we know about all these events, so don't bother reading them
593 break;
594 }
595
596 for (byte i = 0; i < numEvents; ++i)
597 {
598 EventInfo eventInfo = ReadEvent(mPacketReader, sender);
599
600 if (eventInfo != null && eventInfo.FrameOfApplication < senderInfo.HighestFrameNumber)
601 {
602 int index = EventArrayIndex;
603 if (senderInfo.Events[index] == null) senderInfo.Events[index] = new List<EventInfo>();
604 senderInfo.Events[index].Add(eventInfo);
605 }
606 }
607
608 senderInfo.StallCount = stallCount;
609 senderInfo.AverageOwd = averageOwd;
610 senderInfo.HighestFrameNumber = frameNumber;
611 break;
612
613 case PacketType.Stall:
614
615 byte numStalledPeers = mPacketReader.ReadByte();
616 byte[] stalledPeers = mPacketReader.ReadBytes(numStalledPeers);
617
618 // TODO
619
620 break;
621
622 default:
623
624 Console.WriteLine("Received unknown packet type: " + (int)packetId);
625 break;
626 }
627 }
628 }
629
630
631 int EventArrayIndex
632 {
633 get { return (int)(mGame.CurrentFrameNumber % MaximumLatency); }
634 }
635
636 EventInfo ReadEvent(PacketReader packetReader, NetworkGamer sender)
637 {
638 EventType eventId = (EventType)packetReader.ReadByte();
639 long frameNumber = packetReader.ReadInt32();
640
641 switch (eventId)
642 {
643 case EventType.KeyDown:
644
645 int keyCode1 = packetReader.ReadInt32();
646 return new KeyboardEventInfo(sender, frameNumber, (Keys)keyCode1, true);
647
648 case EventType.KeyUp:
649
650 int keyCode2 = packetReader.ReadInt32();
651 return new KeyboardEventInfo(sender, frameNumber, (Keys)keyCode2, false);
652
653 case EventType.MouseDown:
654
655 byte buttonId1 = packetReader.ReadByte();
656 return new MouseButtonEventInfo(sender, frameNumber, (MouseButton)buttonId1, true);
657
658 case EventType.MouseUp:
659
660 byte buttonId2 = packetReader.ReadByte();
661 return new MouseButtonEventInfo(sender, frameNumber, (MouseButton)buttonId2, false);
662
663 case EventType.MouseMove:
664
665 short x = packetReader.ReadInt16();
666 short y = packetReader.ReadInt16();
667 return new MouseMotionEventInfo(sender, frameNumber, x, y);
668
669 default:
670
671 Console.WriteLine("Received unknown event type: " + (int)eventId);
672 return null;
673 }
674 }
675
676
677 void WriteChatPacket(String message)
678 {
679 mPacketWriter.Write((byte)PacketType.Chat);
680 mPacketWriter.Write((short)message.Length);
681 mPacketWriter.Write(message.ToCharArray());
682 }
683
684 void WriteEventPacket(List<EventInfo> events)
685 {
686 mPacketWriter.Write((byte)PacketType.Event);
687 mPacketWriter.Write((short)mStallCount);
688 mPacketWriter.Write((short)mAverageOwd);
689 mPacketWriter.Write((int)(mGame.CurrentFrameNumber + mLatency));
690 mPacketWriter.Write((byte)events.Count);
691
692 foreach (EventInfo eventInfo in events)
693 {
694 mPacketWriter.Write((byte)eventInfo.Id);
695 mPacketWriter.Write((int)eventInfo.FrameOfApplication);
696
697 KeyboardEventInfo keyboardEventInfo = eventInfo as KeyboardEventInfo;
698 if (keyboardEventInfo != null)
699 {
700 mPacketWriter.Write((int)keyboardEventInfo.Key);
701 continue;
702 }
703
704 MouseButtonEventInfo mouseButtonEventInfo = eventInfo as MouseButtonEventInfo;
705 if (mouseButtonEventInfo != null)
706 {
707 mPacketWriter.Write((byte)mouseButtonEventInfo.Button);
708 continue;
709 }
710
711 MouseMotionEventInfo mouseMotionEventInfo = eventInfo as MouseMotionEventInfo;
712 if (mouseMotionEventInfo != null)
713 {
714 mPacketWriter.Write((short)mouseMotionEventInfo.X);
715 mPacketWriter.Write((short)mouseMotionEventInfo.Y);
716 continue;
717 }
718 }
719 }
720
721
722 bool IsLatencyAdjustmentFrame
723 {
724 get
725 {
726 return mNextLatencyAdjustmentFrame == mGame.CurrentFrameNumber;
727 }
728 }
729
730 void AdjustLatency()
731 {
732 Debug.Assert(IsLatencyAdjustmentFrame);
733
734 int maxStallCount = 0;
735 int maxAverageOwd = 0;
736
737 foreach (GamerInfo gamerInfo in GamerArray)
738 {
739 if (gamerInfo.StallCount > maxStallCount) maxStallCount = gamerInfo.StallCount;
740 if (gamerInfo.AverageOwd > maxAverageOwd) maxAverageOwd = gamerInfo.AverageOwd;
741 }
742
743 // DEBUG
744 int prevLatency = mLatency;
745
746 if (maxStallCount > 0)
747 {
748 mLatency += maxStallCount;
749 }
750 else
751 {
752 mLatency = (int)(0.6 * (double)(mLatency - maxAverageOwd) + 1.0);
753 }
754
755 // DEBUG OUTPUT
756 if (prevLatency != mLatency) Console.WriteLine("Latency readjusted to " + mLatency);
757
758 if (mLatency < 1) mLatency = 1;
759 if (mLatency > MaximumLatency) mLatency = MaximumLatency;
760
761 mNextLatencyAdjustmentFrame = mGame.CurrentFrameNumber + mLatency;
762 mAverageOwd = CurrentAverageOneWayDelay;
763
764 mLastLocalEvents = mLocalEvents;
765 mLocalEvents = new List<EventInfo>();
766 }
767
768
769
770 List<EventInfo> GetEventsFromInput()
771 {
772 List<EventInfo> events = new List<EventInfo>();
773
774 // 1. Find the keyboard differences; written by Peter.
775
776 KeyboardState keyState = Keyboard.GetState();
777
778 List<Keys> pressedKeys = new List<Keys>();
779 List<Keys> releasedKeys = new List<Keys>();
780
781 Keys[] pressedKeysArray = keyState.GetPressedKeys();
782 foreach (Keys k in pressedKeysArray)
783 {
784 if (!mLastPressedKeys.Contains(k)) pressedKeys.Add(k);
785 else mLastPressedKeys.Remove(k);
786 }
787
788 releasedKeys = mLastPressedKeys;
789
790 foreach (Keys key in pressedKeys)
791 {
792 events.Add(new KeyboardEventInfo(LocalGamer, mGame.CurrentFrameNumber, key, true));
793 }
794 foreach (Keys key in releasedKeys)
795 {
796 events.Add(new KeyboardEventInfo(LocalGamer, mGame.CurrentFrameNumber, key, false));
797 }
798
799 // 2. Find the mouse differences.
800
801 MouseState mouseState = Mouse.GetState();
802
803 bool leftButtonPressed = mouseState.LeftButton == ButtonState.Pressed;
804 if (leftButtonPressed != mLastLeftButtonPressed)
805 {
806 events.Add(new MouseButtonEventInfo(LocalGamer, mGame.CurrentFrameNumber, MouseButton.Left, leftButtonPressed));
807 }
808
809 bool rightButtonPressed = mouseState.LeftButton == ButtonState.Pressed;
810 if (rightButtonPressed != mLastRightButtonPressed)
811 {
812 events.Add(new MouseButtonEventInfo(LocalGamer, mGame.CurrentFrameNumber, MouseButton.Right, rightButtonPressed));
813 }
814
815 bool middleButtonPressed = mouseState.LeftButton == ButtonState.Pressed;
816 if (middleButtonPressed != mLastMiddleButtonPressed)
817 {
818 events.Add(new MouseButtonEventInfo(LocalGamer, mGame.CurrentFrameNumber, MouseButton.Middle, middleButtonPressed));
819 }
820
821 int mousePositionX = mouseState.X;
822 int mousePositionY = mouseState.Y;
823 if (mousePositionX != mLastMousePositionX || mousePositionY != mLastMousePositionY)
824 {
825 events.Add(new MouseMotionEventInfo(LocalGamer, mGame.CurrentFrameNumber, mousePositionX, mousePositionY));
826 }
827
828 // 3. Save the current peripheral state.
829
830 mLastPressedKeys = new List<Keys>(pressedKeysArray);
831 mLastLeftButtonPressed = leftButtonPressed;
832 mLastRightButtonPressed = rightButtonPressed;
833 mLastMiddleButtonPressed = middleButtonPressed;
834 mLastMousePositionX = mousePositionX;
835 mLastMousePositionY = mousePositionY;
836
837 return events;
838 }
839
840 void SendLocalEvents()
841 {
842 SendLocalEvents((NetworkGamer)null);
843 }
844
845 void SendLocalEvents(List<NetworkGamer> recipicents)
846 {
847 foreach (NetworkGamer gamer in recipicents)
848 {
849 SendLocalEvents(gamer);
850 }
851 }
852
853 void SendLocalEvents(NetworkGamer recipient)
854 {
855 List<EventInfo> events = new List<EventInfo>(mLocalEvents);
856 events.AddRange(mLastLocalEvents);
857
858 WriteEventPacket(events);
859
860 if (recipient != null)
861 {
862 LocalGamer.SendData(mPacketWriter, SendDataOptions.Reliable, recipient);
863 }
864 else
865 {
866 LocalGamer.SendData(mPacketWriter, SendDataOptions.None);
867 }
868 }
869
870
871 bool HaveNeededEvents
872 {
873 get
874 {
875 long currentFrame = mGame.CurrentFrameNumber;
876
877 foreach (GamerInfo gamerInfo in mGamers.Values)
878 {
879 if (gamerInfo.HighestFrameNumber < currentFrame) return false;
880 }
881
882 return true;
883 }
884 }
885
886 void ApplyEvents()
887 {
888 int index = EventArrayIndex;
889
890 foreach (GamerInfo gamerInfo in GamerArray)
891 {
892 if (gamerInfo.Events[index] == null) continue;
893
894 foreach (EventInfo eventInfo in gamerInfo.Events[index])
895 {
896 KeyboardEventInfo keyboardEventInfo = eventInfo as KeyboardEventInfo;
897 if (keyboardEventInfo != null)
898 {
899 mGame.ApplyKeyInput(gamerInfo, keyboardEventInfo.Key, keyboardEventInfo.IsKeyDown);
900 continue;
901 }
902
903 MouseButtonEventInfo mouseButtonEventInfo = eventInfo as MouseButtonEventInfo;
904 if (mouseButtonEventInfo != null)
905 {
906 mGame.ApplyMouseButtonInput(gamerInfo, mouseButtonEventInfo.IsButtonDown);
907 continue;
908 }
909
910 MouseMotionEventInfo mouseMotionEventInfo = eventInfo as MouseMotionEventInfo;
911 if (mouseMotionEventInfo != null)
912 {
913 mGame.ApplyMouseLocationInput(gamerInfo, mouseMotionEventInfo.X, mouseMotionEventInfo.Y);
914 continue;
915 }
916 }
917
918 gamerInfo.Events[index] = null;
919 }
920 }
921
922
923 int CurrentAverageOneWayDelay
924 {
925 get
926 {
927 Debug.Assert(mNetworkSession != null);
928
929 double numRemoteGamersTwice = 2 * mNetworkSession.RemoteGamers.Count;
930 double averageOwd = 0;
931
932 foreach (NetworkGamer gamer in mNetworkSession.RemoteGamers)
933 {
934 TimeSpan timeSpan = gamer.RoundtripTime;
935 averageOwd += timeSpan.TotalMilliseconds;
936 }
937
938 return (int)(averageOwd / numRemoteGamersTwice / 16.6666);
939 }
940 }
941
942 #endregion
943 }
944 }
This page took 0.083256 seconds and 4 git commands to generate.