2 using System.Collections.Generic;
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;
13 namespace CS_3505_Project_06
16 /// A manager class to handle network interactions between peers and
17 /// lobby/game switching.
19 public class NetworkGame
21 // Public methods and properties
22 #region Public Methods
25 /// Called when a session has been created or joined using CreateSession() or JoinSession().
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);
32 /// Called when sessions are found as a result of calling FindSessions().
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);
40 /// Called when an exception is thrown during an asynchronous operation.
42 /// <param name="exception">The exception that was thrown.</param>
43 /// <param name="networkGame">The NetworkGame that errored.</param>
44 public delegate void CaughtErrorDelegate(Exception exception, NetworkGame networkGame);
47 /// Get and set the error delegate, called when an exception is thrown during
48 /// and asynchronous operation. This will occur if you try to create or join a
49 /// session without being logged into a profile.
51 public CaughtErrorDelegate ErrorDelegate;
55 /// Construct a NetworkGame with a lobby and a game.
57 /// <param name="lobby">Provides an associated lobby to update and draw.</param>
58 /// <param name="game">Provides a game object to be played over the network.</param>
59 public NetworkGame(ILobby lobby, IDeterministicGame game)
61 Debug.Assert(lobby != null && game != null);
69 /// Get the Gamer object for the local player.
71 public LocalNetworkGamer LocalGamer
75 // TODO: Is this the correct way to get the single local gamer?
76 return mNetworkSession.LocalGamers[0];
81 /// Get all the gamers associated with the active network session.
83 public GamerCollection<NetworkGamer> NetworkGamers
87 return mNetworkSession.AllGamers;
93 /// Begin a new network session with the local gamer as the host. You must not
94 /// call this method or use JoinSession without first using LeaveSession.
96 /// <param name="callback">The delegate/method to call when the session is created.</param>
97 public void CreateSession(JoinedSessionDelegate callback)
99 CreateSession(mGame.MaximumSupportedPlayers, callback);
103 /// Begin a new network session with the local gamer as the host. You must not
104 /// call this method or use JoinSession without first using LeaveSession.
106 /// <param name="maxGamers">Provide the maximum number of players allowed to connect.</param>
107 /// <param name="callback">The delegate/method to call when the session is created.</param>
108 public void CreateSession(int maxGamers, JoinedSessionDelegate callback)
110 Debug.Assert(mNetworkSession == null);
112 mJoinedSessionDelegate = callback;
113 NetworkSession.BeginCreate(NetworkSessionType.SystemLink, 1, maxGamers, CreateSessionEnd, null);
115 void CreateSessionEnd(IAsyncResult result)
117 Debug.Assert(mNetworkSession == null);
121 mNetworkSession = NetworkSession.EndCreate(result);
122 mNetworkSession.AllowHostMigration = true;
123 mNetworkSession.AllowJoinInProgress = false;
124 mNetworkSession.GameStarted += new EventHandler<GameStartedEventArgs>(GameStartedEvent);
128 if (ErrorDelegate != null) ErrorDelegate(e, this);
131 mJoinedSessionDelegate(mNetworkSession, this);
132 mJoinedSessionDelegate = null;
134 void GameStartedEvent(object sender, GameStartedEventArgs e)
140 /// Determine whether or not the network game object is associated with any network session.
142 /// <returns>True if there exists a NetworkSession; false otherwise.</returns>
143 public bool HasActiveSession
147 return mNetworkSession != null;
153 /// Find available sessions to join. You should not already be in a session when
154 /// calling this method; call LeaveSession first.
156 /// <param name="callback">The delegate/method to call when the search finishes.</param>
157 public void FindSessions(FoundSessionsDelegate callback)
159 Debug.Assert(mNetworkSession == null);
161 mFoundSessionsDelegate = callback;
162 NetworkSession.BeginFind(NetworkSessionType.SystemLink, 1, null, new AsyncCallback(FindSessionsEnd), null);
164 void FindSessionsEnd(IAsyncResult result)
166 AvailableNetworkSessionCollection sessions;
169 sessions = NetworkSession.EndFind(result);
173 if (ErrorDelegate != null) ErrorDelegate(e, this);
176 mFoundSessionsDelegate(sessions, this);
177 mFoundSessionsDelegate = null;
181 /// Join a network session found using FindSessions(). This is for joining a game that
182 /// somebody else has already started hosting. You must not already be in a session.
184 /// <param name="availableSession">Pass the session object to try to join.</param>
185 /// <param name="callback">The delegate/method to call when the search finishes.</param>
186 public void JoinSession(AvailableNetworkSession availableSession, JoinedSessionDelegate callback)
188 Debug.Assert(mNetworkSession == null);
190 mJoinedSessionDelegate = callback;
191 NetworkSession.BeginJoin(availableSession, JoinSessionEnd, null);
193 void JoinSessionEnd(IAsyncResult result)
195 Debug.Assert(mNetworkSession == null);
199 mNetworkSession = NetworkSession.EndJoin(result);
200 mNetworkSession.GameStarted += new EventHandler<GameStartedEventArgs>(GameStartedEvent);
204 if (ErrorDelegate != null) ErrorDelegate(e, this);
207 mJoinedSessionDelegate(mNetworkSession, this);
208 mJoinedSessionDelegate = null;
213 /// Leave and dispose of any currently associated network session. You will find yourself
214 /// back in the lobby. You must already be in a session to leave it.
216 public void LeaveSession()
218 Debug.Assert(mNetworkSession != null);
220 mNetworkSession.Dispose();
221 mNetworkSession = null;
226 /// Set up the network session to simulate 200ms latency and 10% packet loss.
228 public void SimulateBadNetwork()
230 Debug.Assert(mNetworkSession != null);
232 mNetworkSession.SimulatedLatency = new TimeSpan(0, 0, 0, 0, 200);
233 mNetworkSession.SimulatedPacketLoss = 0.1f;
238 /// Indicate that the game should begin (moving players from the lobby to the game).
239 /// You must call CreateSession() before calling this.
241 public void StartGame()
243 Debug.Assert(mNetworkSession != null && mNetworkSession.IsHost &&
244 mNetworkSession.AllGamers.Count >= mGame.MinimumSupportedPlayers &&
245 mNetworkSession.IsEveryoneReady);
251 /// Indicate that the game should begin. This is like StartGame() without the sanity
252 /// checks. Use this for debugging.
254 public void ForceStartGame()
256 mNetworkSession.StartGame();
257 mNetworkSession.ResetReady();
262 /// Manages the network session and allows either the lobby or game to update.
264 /// <param name="gameTime">Pass the time away.</param>
265 public void Update(GameTime gameTime)
267 if (mNetworkSession == null)
269 mLobby.Update(gameTime, this);
273 mNetworkSession.Update();
274 HandleIncomingPackets();
276 if (mNetworkSession.SessionState == NetworkSessionState.Lobby)
278 mLobby.Update(gameTime, this);
280 else if (mNetworkSession.SessionState == NetworkSessionState.Playing)
282 if (mGame.IsGameOver(LocalGamerInfo) || mGame.IsTerminated(LocalGamerInfo))
284 // TODO: Should support moving back to the session lobby.
289 if (HaveNeededEvents)
291 if (IsLatencyAdjustmentFrame)
294 mLastStallCount = mStallCount;
297 mLocalEvents.AddRange(GetEventsFromInput());
300 mGame.Update(mTargetTimeSpan);
304 if (mStallCount == 0)
306 Console.WriteLine("===== STALL =====");
308 else if (mStallCount % 60 == 0)
310 Console.WriteLine("Stalled for " + mStallCount + " frames.");
315 // Send a reliable event packet to each stalled gamer.
316 if (mStallCount == 1)
318 foreach (GamerInfo gamerInfo in GamerArray)
320 if (gamerInfo.HighestFrameNumber < mGame.CurrentFrameNumber)
322 SendLocalEvents(gamerInfo.Gamer);
327 /*if (mStallCount > StallTimeout)
332 else if (mStallCount == 1)
336 else if (mStallCount % 60 == 0)
345 /// Allows either the lobby or the game to draw, depending on the state
346 /// of the network connection and whether or not a game is in progress.
348 /// <param name="gameTime">Pass the time away.</param>
349 /// <param name="spriteBatch">The sprite batch.</param>
350 public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
352 if (mNetworkSession == null)
354 mLobby.Draw(spriteBatch);
358 if (mNetworkSession.SessionState == NetworkSessionState.Lobby)
360 mLobby.Draw(spriteBatch);
362 else if (mNetworkSession.SessionState == NetworkSessionState.Playing)
364 mGame.Draw(spriteBatch);
371 /// Get the chat messages that have been receive since the last time this
372 /// method was called.
374 /// <returns>List container of the chat messages.</returns>
375 public List<ChatInfo> ReceiveChats()
377 List<ChatInfo> chats = mChatPackets;
378 mChatPackets = new List<ChatInfo>();
383 /// Send a chat message to all gamers in the session. You should already be
384 /// in a session before calling this method.
386 /// <param name="message">The text of the message.</param>
387 public void SendChat(String message)
389 WriteChatPacket(message);
390 LocalGamer.SendData(mPacketWriter, SendDataOptions.ReliableInOrder);
394 /// Send a chat message to a specific gamer in the session. You should already
395 /// be in a session before calling this method.
397 /// <param name="message">The text of the message.</param>
398 /// <param name="recipient">The gamer to receive the message.</param>
399 public void SendChat(String message, NetworkGamer recipient)
401 WriteChatPacket(message);
402 LocalGamer.SendData(mPacketWriter, SendDataOptions.ReliableInOrder, recipient);
408 // Private class variable members
409 #region Instance Variables
411 NetworkSession mNetworkSession;
412 PacketReader mPacketReader = new PacketReader();
413 PacketWriter mPacketWriter = new PacketWriter();
415 JoinedSessionDelegate mJoinedSessionDelegate;
416 FoundSessionsDelegate mFoundSessionsDelegate;
419 IDeterministicGame mGame;
421 List<ChatInfo> mChatPackets = new List<ChatInfo>();
423 List<EventInfo> mLocalEvents = new List<EventInfo>();
424 List<EventInfo> mLastLocalEvents = new List<EventInfo>();
426 List<Keys> mLastPressedKeys = new List<Keys>();
427 bool mLastLeftButtonPressed;
428 bool mLastRightButtonPressed;
429 bool mLastMiddleButtonPressed;
430 int mLastMousePositionX;
431 int mLastMousePositionY;
434 long mHighestFrameNumber;
435 long mNextLatencyAdjustmentFrame;
441 bool mDontSendEvents;
443 TimeSpan mTargetTimeSpan = new TimeSpan(166666);
444 public TimeSpan TargetTimeSpan
448 return mTargetTimeSpan;
452 Dictionary<byte, GamerInfo> mGamers;
453 GamerInfo[] GamerArray
457 GamerInfo[] gamerList = mGamers.Values.ToArray();
458 Array.Sort(gamerList, delegate(GamerInfo a, GamerInfo b)
460 return a.Gamer.Id.CompareTo(b.Gamer.Id);
465 GamerInfo LocalGamerInfo
469 return mGamers[LocalGamer.Id];
476 // Private types for the implementation of the network protocol
477 #region Private Types
502 abstract class EventInfo
504 public NetworkGamer Gamer;
505 public long FrameOfApplication;
507 public EventInfo(NetworkGamer gamer, long frameNumber)
510 FrameOfApplication = frameNumber;
513 public abstract EventType Id
519 class KeyboardEventInfo : EventInfo
522 public bool IsKeyDown;
524 public KeyboardEventInfo(NetworkGamer gamer, long frameNumber, Keys key, bool isDown)
525 : base(gamer, frameNumber)
531 public override EventType Id
533 get { return IsKeyDown ? EventType.KeyDown : EventType.KeyUp; }
537 class MouseButtonEventInfo : EventInfo
539 public MouseButton Button;
540 public bool IsButtonDown;
542 public MouseButtonEventInfo(NetworkGamer gamer, long frameNumber, MouseButton button, bool isDown)
543 : base(gamer, frameNumber)
546 IsButtonDown = isDown;
549 public override EventType Id
551 get { return IsButtonDown ? EventType.MouseDown : EventType.MouseUp; }
555 class MouseMotionEventInfo : EventInfo
560 public MouseMotionEventInfo(NetworkGamer gamer, long frameNumber, int x, int y)
561 : base(gamer, frameNumber)
567 public override EventType Id
569 get { return EventType.MouseMove; }
575 public NetworkGamer Gamer;
576 public long HighestFrameNumber = -1;
577 public int StallCount = 0;
578 public int AverageOwd = 0;
579 public int NextStallCount = 0;
580 public int NextAverageOwd = 0;
581 public bool IsWaitedOn = false;
582 public List<EventInfo>[] Events = new List<EventInfo>[MaximumLatency];
584 public GamerInfo(NetworkGamer gamer)
590 const int MaximumLatency = 120;
591 const int StallTimeout = 900;
596 // Private implementation methods of the network protocol
597 #region Private Implementation Methods
600 /// Reinitialize the private variables in preparation for a new game to start.
605 mHighestFrameNumber = -1;
606 mNextLatencyAdjustmentFrame = 1;
609 mAverageOwd = CurrentAverageOneWayDelay;
611 mGamers = new Dictionary<byte, GamerInfo>();
612 foreach (NetworkGamer gamer in NetworkGamers)
614 mGamers.Add(gamer.Id, new GamerInfo(gamer));
617 mGame.ResetGame(GamerArray, LocalGamerInfo);
621 void HandleIncomingPackets()
623 LocalNetworkGamer localGamer = LocalGamer;
625 while (localGamer.IsDataAvailable)
629 localGamer.ReceiveData(mPacketReader, out sender);
630 GamerInfo senderInfo = mGamers[sender.Id];
632 PacketType packetId = (PacketType)mPacketReader.ReadByte();
635 case PacketType.Chat:
637 short messageLength = mPacketReader.ReadInt16();
638 char[] message = mPacketReader.ReadChars(messageLength);
640 ChatInfo chatPacket = new ChatInfo(sender, new String(message));
641 mChatPackets.Add(chatPacket);
644 case PacketType.Event:
646 int stallCount = mPacketReader.ReadInt16();
647 int averageOwd = mPacketReader.ReadInt16();
648 int frameNumber = mPacketReader.ReadInt32();
649 int numEvents = mPacketReader.ReadByte();
651 if (frameNumber <= senderInfo.HighestFrameNumber)
653 // we know about all these events, so don't bother reading them
657 for (int i = 0; i < numEvents; i++)
659 EventInfo eventInfo = ReadEvent(mPacketReader, sender);
661 if (eventInfo != null && eventInfo.FrameOfApplication > senderInfo.HighestFrameNumber)
663 int index = GetEventArrayIndexForFrame(eventInfo.FrameOfApplication);
664 if (senderInfo.Events[index] == null) senderInfo.Events[index] = new List<EventInfo>();
665 senderInfo.Events[index].Add(eventInfo);
669 if (frameNumber <= mNextLatencyAdjustmentFrame)
671 senderInfo.StallCount = stallCount;
672 senderInfo.AverageOwd = averageOwd;
676 senderInfo.NextStallCount = stallCount;
677 senderInfo.NextAverageOwd = averageOwd;
679 senderInfo.HighestFrameNumber = frameNumber;
682 case PacketType.Stall:
684 byte numStalledPeers = mPacketReader.ReadByte();
685 byte[] stalledPeers = mPacketReader.ReadBytes(numStalledPeers);
692 Console.WriteLine("Received unknown packet type: " + (int)packetId);
699 int CurrentEventArrayIndex
701 get { return GetEventArrayIndexForFrame(mGame.CurrentFrameNumber); }
704 int GetEventArrayIndexForFrame(long frame)
706 return (int)(frame % MaximumLatency);
709 EventInfo ReadEvent(PacketReader packetReader, NetworkGamer sender)
711 EventType eventId = (EventType)packetReader.ReadByte();
712 long frameNumber = packetReader.ReadInt32();
716 case EventType.KeyDown:
718 Keys keyCode1 = (Keys)packetReader.ReadInt32();
719 return new KeyboardEventInfo(sender, frameNumber, keyCode1, true);
721 case EventType.KeyUp:
723 Keys keyCode2 = (Keys)packetReader.ReadInt32();
724 return new KeyboardEventInfo(sender, frameNumber, keyCode2, false);
726 case EventType.MouseDown:
728 MouseButton buttonId1 = (MouseButton)packetReader.ReadByte();
729 return new MouseButtonEventInfo(sender, frameNumber, buttonId1, true);
731 case EventType.MouseUp:
733 MouseButton buttonId2 = (MouseButton)packetReader.ReadByte();
734 return new MouseButtonEventInfo(sender, frameNumber, buttonId2, false);
736 case EventType.MouseMove:
738 short x = packetReader.ReadInt16();
739 short y = packetReader.ReadInt16();
740 return new MouseMotionEventInfo(sender, frameNumber, x, y);
744 Console.WriteLine("Received unknown event type: " + (int)eventId);
750 void WriteChatPacket(String message)
752 mPacketWriter.Write((byte)PacketType.Chat);
753 mPacketWriter.Write((short)message.Length);
754 mPacketWriter.Write(message.ToCharArray());
757 void WriteEventPacket(List<EventInfo> events)
759 mPacketWriter.Write((byte)PacketType.Event);
760 mPacketWriter.Write((short)mLastStallCount);
761 mPacketWriter.Write((short)mAverageOwd);
762 mPacketWriter.Write((int)(mGame.CurrentFrameNumber + mLatency));
763 mPacketWriter.Write((byte)events.Count);
765 foreach (EventInfo eventInfo in events)
767 mPacketWriter.Write((byte)eventInfo.Id);
768 mPacketWriter.Write((int)eventInfo.FrameOfApplication);
770 KeyboardEventInfo keyboardEventInfo = eventInfo as KeyboardEventInfo;
771 if (keyboardEventInfo != null)
773 mPacketWriter.Write((int)keyboardEventInfo.Key);
777 MouseButtonEventInfo mouseButtonEventInfo = eventInfo as MouseButtonEventInfo;
778 if (mouseButtonEventInfo != null)
780 mPacketWriter.Write((byte)mouseButtonEventInfo.Button);
784 MouseMotionEventInfo mouseMotionEventInfo = eventInfo as MouseMotionEventInfo;
785 if (mouseMotionEventInfo != null)
787 mPacketWriter.Write((short)mouseMotionEventInfo.X);
788 mPacketWriter.Write((short)mouseMotionEventInfo.Y);
795 bool IsLatencyAdjustmentFrame
799 return mNextLatencyAdjustmentFrame == mGame.CurrentFrameNumber;
805 Debug.Assert(IsLatencyAdjustmentFrame);
807 int maxStallCount = 0;
808 int maxAverageOwd = 0;
810 foreach (GamerInfo gamerInfo in GamerArray)
812 if (gamerInfo.StallCount > maxStallCount) maxStallCount = gamerInfo.StallCount;
813 if (gamerInfo.AverageOwd > maxAverageOwd) maxAverageOwd = gamerInfo.AverageOwd;
815 gamerInfo.StallCount = gamerInfo.NextStallCount;
816 gamerInfo.AverageOwd = gamerInfo.NextAverageOwd;
820 int prevLatency = mLatency;
822 if (maxStallCount > 0)
824 mLatency += maxStallCount;
828 mLatency = (int)(0.6 * (double)(mLatency - maxAverageOwd) + 1.0);
832 if (prevLatency != mLatency) Console.WriteLine("Latency readjusted to " + mLatency);
834 if (mLatency < 1) mLatency = 1;
835 if (mLatency > MaximumLatency) mLatency = MaximumLatency;
837 mNextLatencyAdjustmentFrame = mGame.CurrentFrameNumber + mLatency;
838 mAverageOwd = CurrentAverageOneWayDelay;
840 mLastLocalEvents = mLocalEvents;
841 mLocalEvents = new List<EventInfo>();
846 List<EventInfo> GetEventsFromInput()
848 List<EventInfo> events = new List<EventInfo>();
850 long frameOfApplication = mGame.CurrentFrameNumber + mLatency;
851 if (frameOfApplication <= mHighestFrameNumber) return events;
852 else mHighestFrameNumber = frameOfApplication;
854 // 1. Find the keyboard differences; written by Peter.
856 KeyboardState keyState = Keyboard.GetState();
858 List<Keys> pressedKeys = new List<Keys>();
859 List<Keys> releasedKeys = new List<Keys>();
861 Keys[] pressedKeysArray = keyState.GetPressedKeys();
862 foreach (Keys k in pressedKeysArray)
864 if (!mLastPressedKeys.Contains(k)) pressedKeys.Add(k);
865 else mLastPressedKeys.Remove(k);
868 releasedKeys = mLastPressedKeys;
870 foreach (Keys key in pressedKeys)
872 events.Add(new KeyboardEventInfo(LocalGamer, frameOfApplication, key, true));
874 foreach (Keys key in releasedKeys)
876 events.Add(new KeyboardEventInfo(LocalGamer, frameOfApplication, key, false));
880 if (pressedKeys.Contains(Keys.Escape)) mDontSendEvents = true;
881 if (releasedKeys.Contains(Keys.Escape)) mDontSendEvents = false;
883 // 2. Find the mouse differences.
885 MouseState mouseState = Mouse.GetState();
887 bool leftButtonPressed = mouseState.LeftButton == ButtonState.Pressed;
888 if (leftButtonPressed != mLastLeftButtonPressed)
890 events.Add(new MouseButtonEventInfo(LocalGamer, frameOfApplication, MouseButton.Left, leftButtonPressed));
893 bool rightButtonPressed = mouseState.LeftButton == ButtonState.Pressed;
894 if (rightButtonPressed != mLastRightButtonPressed)
896 events.Add(new MouseButtonEventInfo(LocalGamer, frameOfApplication, MouseButton.Right, rightButtonPressed));
899 bool middleButtonPressed = mouseState.LeftButton == ButtonState.Pressed;
900 if (middleButtonPressed != mLastMiddleButtonPressed)
902 events.Add(new MouseButtonEventInfo(LocalGamer, frameOfApplication, MouseButton.Middle, middleButtonPressed));
905 int mousePositionX = mouseState.X;
906 int mousePositionY = mouseState.Y;
907 if (mousePositionX != mLastMousePositionX || mousePositionY != mLastMousePositionY)
909 events.Add(new MouseMotionEventInfo(LocalGamer, frameOfApplication, mousePositionX, mousePositionY));
912 // 3. Save the current peripheral state.
914 mLastPressedKeys = new List<Keys>(pressedKeysArray);
915 mLastLeftButtonPressed = leftButtonPressed;
916 mLastRightButtonPressed = rightButtonPressed;
917 mLastMiddleButtonPressed = middleButtonPressed;
918 mLastMousePositionX = mousePositionX;
919 mLastMousePositionY = mousePositionY;
924 void SendLocalEvents()
926 SendLocalEvents((NetworkGamer)null);
929 void SendLocalEvents(List<NetworkGamer> recipicents)
931 foreach (NetworkGamer gamer in recipicents)
933 SendLocalEvents(gamer);
937 void SendLocalEvents(NetworkGamer recipient)
940 if (mDontSendEvents) return;
942 List<EventInfo> events = new List<EventInfo>(mLocalEvents);
943 events.AddRange(mLastLocalEvents);
945 WriteEventPacket(events);
947 if (recipient != null && !recipient.IsDisposed)
949 LocalGamer.SendData(mPacketWriter, SendDataOptions.Reliable, recipient);
953 LocalGamer.SendData(mPacketWriter, SendDataOptions.None);
958 bool HaveNeededEvents
962 long currentFrame = mGame.CurrentFrameNumber;
964 foreach (GamerInfo gamerInfo in mGamers.Values)
966 if (gamerInfo.HighestFrameNumber < currentFrame) return false;
975 int index = CurrentEventArrayIndex;
977 foreach (GamerInfo gamerInfo in GamerArray)
979 if (gamerInfo.Events[index] == null) continue;
981 foreach (EventInfo eventInfo in gamerInfo.Events[index])
983 KeyboardEventInfo keyboardEventInfo = eventInfo as KeyboardEventInfo;
984 if (keyboardEventInfo != null)
986 Console.WriteLine(keyboardEventInfo.FrameOfApplication + " KEY: " + keyboardEventInfo.Key + "," + keyboardEventInfo.IsKeyDown);
987 mGame.ApplyKeyInput(gamerInfo, keyboardEventInfo.Key, keyboardEventInfo.IsKeyDown);
991 MouseButtonEventInfo mouseButtonEventInfo = eventInfo as MouseButtonEventInfo;
992 if (mouseButtonEventInfo != null)
994 mGame.ApplyMouseButtonInput(gamerInfo, mouseButtonEventInfo.IsButtonDown);
995 Console.WriteLine(mouseButtonEventInfo.FrameOfApplication + " BTN: " + mouseButtonEventInfo.IsButtonDown);
999 MouseMotionEventInfo mouseMotionEventInfo = eventInfo as MouseMotionEventInfo;
1000 if (mouseMotionEventInfo != null)
1002 mGame.ApplyMouseLocationInput(gamerInfo, mouseMotionEventInfo.X, mouseMotionEventInfo.Y);
1003 Console.WriteLine(mouseMotionEventInfo.FrameOfApplication + " MMV: " + mouseMotionEventInfo.X + "," + mouseMotionEventInfo.Y);
1008 gamerInfo.Events[index] = null;
1013 int CurrentAverageOneWayDelay
1017 Debug.Assert(mNetworkSession != null);
1019 double numRemoteGamersTwice = 2 * mNetworkSession.RemoteGamers.Count;
1020 double averageOwd = 0;
1022 foreach (NetworkGamer gamer in mNetworkSession.RemoteGamers)
1024 TimeSpan timeSpan = gamer.RoundtripTime;
1025 averageOwd += timeSpan.TotalMilliseconds;
1028 return (int)((averageOwd / numRemoteGamersTwice) / 16.6666);