5 using System.Collections.Generic;
8 using Microsoft.Xna.Framework.Net;
9 using System.Diagnostics;
10 using Microsoft.Xna.Framework.GamerServices;
11 using Microsoft.Xna.Framework.Graphics;
12 using Microsoft.Xna.Framework;
13 using Microsoft.Xna.Framework.Input;
14 using System.Collections;
16 namespace CS_3505_Project_06
19 /// A manager class to handle network interactions between peers and
20 /// lobby/game switching.
22 public class NetworkGame
24 // Public methods and properties
25 #region Public Methods
28 /// Called when a session has been created or joined using CreateSession() or JoinSession().
30 /// <param name="session">The new session that was created or joined.</param>
31 /// <param name="networkGame">The NetworkGame that joined the session.</param>
32 public delegate void JoinedSessionDelegate(NetworkSession session, NetworkGame networkGame);
35 /// Called when sessions are found as a result of calling FindSessions().
37 /// <param name="sessions">A container of the available sessions.</param>
38 /// <param name="networkGame">The NetworkGame that searched for the sessions.</param>
39 public delegate void FoundSessionsDelegate(AvailableNetworkSessionCollection sessions, NetworkGame networkGame);
43 /// Called when an exception is thrown during an asynchronous operation.
45 /// <param name="exception">The exception that was thrown.</param>
46 /// <param name="networkGame">The NetworkGame that errored.</param>
47 public delegate void CaughtErrorDelegate(Exception exception, NetworkGame networkGame);
50 /// Get and set the error delegate, called when an exception is thrown during
51 /// and asynchronous operation. This will occur if you try to create or join a
52 /// session without being logged into a profile.
54 public CaughtErrorDelegate ErrorDelegate;
58 /// Construct a NetworkGame with a lobby and a game.
60 /// <param name="lobby">Provides an associated lobby to update and draw.</param>
61 /// <param name="game">Provides a game object to be played over the network.</param>
62 public NetworkGame(ILobby lobby, IDeterministicGame game)
64 Debug.Assert(lobby != null && game != null);
72 /// Get the Gamer object for the local player.
74 public LocalNetworkGamer LocalGamer
78 // TODO: Is this the correct way to get the single local gamer?
79 return mNetworkSession.LocalGamers[0];
84 /// Get all the gamers associated with the active network session.
86 public GamerCollection<NetworkGamer> NetworkGamers
90 return mNetworkSession.AllGamers;
96 /// Begin a new network session with the local gamer as the host. You must not
97 /// call this method or use JoinSession without first using LeaveSession.
99 /// <param name="callback">The delegate/method to call when the session is created.</param>
100 public void CreateSession(JoinedSessionDelegate callback)
102 CreateSession(mGame.MaximumSupportedPlayers, callback);
106 /// Begin a new network session with the local gamer as the host. You must not
107 /// call this method or use JoinSession without first using LeaveSession.
109 /// <param name="maxGamers">Provide the maximum number of players allowed to connect.</param>
110 /// <param name="callback">The delegate/method to call when the session is created.</param>
111 public void CreateSession(int maxGamers, JoinedSessionDelegate callback)
113 Debug.Assert(mNetworkSession == null);
115 mJoinedSessionDelegate = callback;
116 NetworkSession.BeginCreate(NetworkSessionType.SystemLink, 1, maxGamers, CreateSessionEnd, null);
118 void CreateSessionEnd(IAsyncResult result)
120 Debug.Assert(mNetworkSession == null);
124 mNetworkSession = NetworkSession.EndCreate(result);
125 mNetworkSession.AllowHostMigration = true;
126 mNetworkSession.AllowJoinInProgress = false;
127 mNetworkSession.GameStarted += new EventHandler<GameStartedEventArgs>(GameStartedEvent);
131 if (ErrorDelegate != null) ErrorDelegate(e, this);
134 mJoinedSessionDelegate(mNetworkSession, this);
135 mJoinedSessionDelegate = null;
137 void GameStartedEvent(object sender, GameStartedEventArgs e)
143 /// Determine whether or not the network game object is associated with any network session.
145 /// <returns>True if there exists a NetworkSession; false otherwise.</returns>
146 public bool HasActiveSession
150 return mNetworkSession != null;
156 /// Find available sessions to join. You should not already be in a session when
157 /// calling this method; call LeaveSession first.
159 /// <param name="callback">The delegate/method to call when the search finishes.</param>
160 public void FindSessions(FoundSessionsDelegate callback)
162 Debug.Assert(mNetworkSession == null);
164 mFoundSessionsDelegate = callback;
165 NetworkSession.BeginFind(NetworkSessionType.SystemLink, 1, null, new AsyncCallback(FindSessionsEnd), null);
167 void FindSessionsEnd(IAsyncResult result)
169 AvailableNetworkSessionCollection sessions;
172 sessions = NetworkSession.EndFind(result);
176 if (ErrorDelegate != null) ErrorDelegate(e, this);
179 mFoundSessionsDelegate(sessions, this);
180 mFoundSessionsDelegate = null;
184 /// Join a network session found using FindSessions(). This is for joining a game that
185 /// somebody else has already started hosting. You must not already be in a session.
187 /// <param name="availableSession">Pass the session object to try to join.</param>
188 /// <param name="callback">The delegate/method to call when the search finishes.</param>
189 public void JoinSession(AvailableNetworkSession availableSession, JoinedSessionDelegate callback)
191 Debug.Assert(mNetworkSession == null);
193 mJoinedSessionDelegate = callback;
194 NetworkSession.BeginJoin(availableSession, JoinSessionEnd, null);
196 void JoinSessionEnd(IAsyncResult result)
198 Debug.Assert(mNetworkSession == null);
202 mNetworkSession = NetworkSession.EndJoin(result);
203 mNetworkSession.GameStarted += new EventHandler<GameStartedEventArgs>(GameStartedEvent);
207 if (ErrorDelegate != null) ErrorDelegate(e, this);
210 mJoinedSessionDelegate(mNetworkSession, this);
211 mJoinedSessionDelegate = null;
216 /// Leave and dispose of any currently associated network session. You will find yourself
217 /// back in the lobby. You must already be in a session to leave it.
219 public void LeaveSession()
221 Debug.Assert(mNetworkSession != null);
223 mNetworkSession.Dispose();
224 mNetworkSession = null;
229 /// Set up the network session to simulate 200ms latency and 10% packet loss.
231 public void SimulateBadNetwork()
233 Debug.Assert(mNetworkSession != null);
235 mNetworkSession.SimulatedLatency = new TimeSpan(0, 0, 0, 0, 200);
236 mNetworkSession.SimulatedPacketLoss = 0.1f;
241 /// Indicate that the game should begin (moving players from the lobby to the game).
242 /// You must call CreateSession() before calling this.
244 public void StartGame()
246 Debug.Assert(mNetworkSession != null && mNetworkSession.IsHost &&
247 mNetworkSession.AllGamers.Count >= mGame.MinimumSupportedPlayers &&
248 mNetworkSession.IsEveryoneReady);
254 /// Indicate that the game should begin. This is like StartGame() without the sanity
255 /// checks. Use this for debugging.
257 public void ForceStartGame()
259 mNetworkSession.StartGame();
260 mNetworkSession.ResetReady();
265 /// Manages the network session and allows either the lobby or game to update.
267 /// <param name="gameTime">Pass the time away.</param>
268 public void Update(GameTime gameTime)
270 if (mNetworkSession == null)
272 mLobby.Update(gameTime, this);
276 mNetworkSession.Update();
277 HandleIncomingPackets();
279 if (mNetworkSession.SessionState == NetworkSessionState.Lobby)
281 mLobby.Update(gameTime, this);
283 else if (mNetworkSession.SessionState == NetworkSessionState.Playing)
285 if (mGame.IsGameOver(LocalGamerInfo) || mGame.IsTerminated(LocalGamerInfo))
287 // TODO: Should support moving back to the session lobby.
292 if (HaveNeededEvents)
294 if (IsLatencyAdjustmentFrame)
297 mLastStallCount = mStallCount;
300 mLocalEvents.AddRange(GetEventsFromInput());
305 Console.WriteLine("HASH: " + mGame.CurrentFrameNumber + "\t" + mGame.CurrentChecksum);
308 mGame.Update(mTargetTimeSpan);
312 if (mStallCount == 0)
315 Console.WriteLine("STAL: ====");
318 else if (mStallCount % 60 == 0)
321 //Console.WriteLine("Stalled for " + mStallCount + " frames.");
326 // Send a reliable event packet to each stalled gamer.
327 if (mStallCount == 1)
329 foreach (GamerInfo gamerInfo in GamerArray)
331 if (gamerInfo.HighestFrameNumber < mGame.CurrentFrameNumber)
333 SendLocalEvents(gamerInfo.Gamer);
338 /*if (mStallCount > StallTimeout)
343 else if (mStallCount == 1)
347 else if (mStallCount % 60 == 0)
356 /// Allows either the lobby or the game to draw, depending on the state
357 /// of the network connection and whether or not a game is in progress.
359 /// <param name="gameTime">Pass the time away.</param>
360 /// <param name="spriteBatch">The sprite batch.</param>
361 public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
363 if (mNetworkSession == null)
365 mLobby.Draw(spriteBatch);
369 if (mNetworkSession.SessionState == NetworkSessionState.Lobby)
371 mLobby.Draw(spriteBatch);
373 else if (mNetworkSession.SessionState == NetworkSessionState.Playing)
375 mGame.Draw(spriteBatch);
382 /// Get the chat messages that have been received since the last time this
383 /// method was called.
385 /// <returns>List container of the chat messages.</returns>
386 public List<ChatInfo> ReceiveChats()
388 List<ChatInfo> chats = mChatPackets;
389 mChatPackets = new List<ChatInfo>();
394 /// Send a chat message to all gamers in the session. You should already be
395 /// in a session before calling this method.
397 /// <param name="message">The text of the message.</param>
398 public void SendChat(String message)
400 WriteChatPacket(message);
401 LocalGamer.SendData(mPacketWriter, SendDataOptions.ReliableInOrder);
405 /// Send a chat message to a specific gamer in the session. You should already
406 /// be in a session before calling this method.
408 /// <param name="message">The text of the message.</param>
409 /// <param name="recipient">The gamer to receive the message.</param>
410 public void SendChat(String message, NetworkGamer recipient)
412 Debug.Assert(recipient != null && !recipient.IsDisposed);
414 WriteChatPacket(message);
415 LocalGamer.SendData(mPacketWriter, SendDataOptions.ReliableInOrder, recipient);
421 // Private class variable members
422 #region Instance Variables
424 NetworkSession mNetworkSession;
425 PacketReader mPacketReader = new PacketReader();
426 PacketWriter mPacketWriter = new PacketWriter();
428 JoinedSessionDelegate mJoinedSessionDelegate;
429 FoundSessionsDelegate mFoundSessionsDelegate;
432 IDeterministicGame mGame;
434 List<ChatInfo> mChatPackets = new List<ChatInfo>();
436 List<EventInfo> mLocalEvents = new List<EventInfo>();
437 List<EventInfo> mLastLocalEvents = new List<EventInfo>();
439 List<Keys> mLastPressedKeys = new List<Keys>();
440 bool mLastLeftButtonPressed;
441 bool mLastRightButtonPressed;
442 bool mLastMiddleButtonPressed;
443 int mLastMousePositionX;
444 int mLastMousePositionY;
447 long mHighestFrameNumber;
448 long mNextLatencyAdjustmentFrame;
454 bool mDontSendEvents;
457 TimeSpan mTargetTimeSpan = new TimeSpan(166666);
458 public TimeSpan TargetTimeSpan
462 return mTargetTimeSpan;
466 Dictionary<byte, GamerInfo> mGamers;
467 GamerInfo[] GamerArray
471 GamerInfo[] gamerList = mGamers.Values.ToArray();
472 Array.Sort(gamerList, delegate(GamerInfo a, GamerInfo b)
474 return a.Gamer.Id.CompareTo(b.Gamer.Id);
479 GamerInfo LocalGamerInfo
483 return mGamers[LocalGamer.Id];
490 // Private types for the implementation of the network protocol
491 #region Private Types
516 abstract class EventInfo
518 public NetworkGamer Gamer;
519 public long FrameOfApplication;
521 public EventInfo(NetworkGamer gamer, long frameNumber)
524 FrameOfApplication = frameNumber;
527 public abstract EventType Id
533 class KeyboardEventInfo : EventInfo
536 public bool IsKeyDown;
538 public KeyboardEventInfo(NetworkGamer gamer, long frameNumber, Keys key, bool isDown)
539 : base(gamer, frameNumber)
545 public override EventType Id
547 get { return IsKeyDown ? EventType.KeyDown : EventType.KeyUp; }
551 class MouseButtonEventInfo : EventInfo
553 public MouseButton Button;
554 public bool IsButtonDown;
556 public MouseButtonEventInfo(NetworkGamer gamer, long frameNumber, MouseButton button, bool isDown)
557 : base(gamer, frameNumber)
560 IsButtonDown = isDown;
563 public override EventType Id
565 get { return IsButtonDown ? EventType.MouseDown : EventType.MouseUp; }
569 class MouseMotionEventInfo : EventInfo
574 public MouseMotionEventInfo(NetworkGamer gamer, long frameNumber, int x, int y)
575 : base(gamer, frameNumber)
581 public override EventType Id
583 get { return EventType.MouseMove; }
589 public NetworkGamer Gamer;
590 public long HighestFrameNumber = 0;
591 public int StallCount = 0;
592 public int AverageOwd = 0;
593 public int NextStallCount = 0;
594 public int NextAverageOwd = 0;
595 public bool IsWaitedOn = false;
596 public List<EventInfo>[] Events = new List<EventInfo>[MaximumLatency];
598 public GamerInfo(NetworkGamer gamer)
604 const int MaximumLatency = 120;
605 const int StallTimeout = 900;
610 // Private implementation methods of the network protocol
611 #region Private Implementation Methods
614 /// Reinitialize the private variables in preparation for a new game to start.
619 mHighestFrameNumber = 0;
620 mNextLatencyAdjustmentFrame = 1;
623 mAverageOwd = CurrentAverageOneWayDelay;
625 mGamers = new Dictionary<byte, GamerInfo>();
626 foreach (NetworkGamer gamer in NetworkGamers)
628 mGamers.Add(gamer.Id, new GamerInfo(gamer));
631 mGame.ResetGame(GamerArray, LocalGamerInfo);
635 void HandleIncomingPackets()
637 LocalNetworkGamer localGamer = LocalGamer;
639 while (localGamer.IsDataAvailable)
643 localGamer.ReceiveData(mPacketReader, out sender);
644 if (sender == null || sender.IsDisposed) continue;
645 GamerInfo senderInfo = mGamers[sender.Id];
647 PacketType packetId = (PacketType)mPacketReader.ReadByte();
650 case PacketType.Chat:
652 short messageLength = mPacketReader.ReadInt16();
653 char[] message = mPacketReader.ReadChars(messageLength);
655 ChatInfo chatPacket = new ChatInfo(sender, new String(message));
656 mChatPackets.Add(chatPacket);
659 case PacketType.Event:
661 int stallCount = mPacketReader.ReadInt16();
662 int averageOwd = mPacketReader.ReadInt16();
663 int frameNumber = mPacketReader.ReadInt32();
664 int numEvents = mPacketReader.ReadByte();
666 if (frameNumber <= mNextLatencyAdjustmentFrame)
668 senderInfo.StallCount = stallCount;
669 senderInfo.AverageOwd = averageOwd;
673 senderInfo.NextStallCount = stallCount;
674 senderInfo.NextAverageOwd = averageOwd;
677 if (frameNumber <= senderInfo.HighestFrameNumber)
680 Console.WriteLine("SKP" + (char)sender.Id + ": " + mGame.CurrentFrameNumber + "\t" + frameNumber + "\t<=\t" + senderInfo.HighestFrameNumber + "\t#" + numEvents);
683 // we know about all these events, so don't bother reading them
688 Console.WriteLine(" GOT" + (char)sender.Id + ": " + mGame.CurrentFrameNumber + "\t" + frameNumber + "\t>\t" + senderInfo.HighestFrameNumber + "\t#" + numEvents);
691 for (int i = 0; i < numEvents; i++)
693 EventInfo eventInfo = ReadEvent(mPacketReader, sender);
695 if (eventInfo != null && eventInfo.FrameOfApplication > senderInfo.HighestFrameNumber)
697 int index = GetEventArrayIndexForFrame(eventInfo.FrameOfApplication);
698 if (senderInfo.Events[index] == null) senderInfo.Events[index] = new List<EventInfo>();
699 senderInfo.Events[index].Add(eventInfo);
703 senderInfo.HighestFrameNumber = frameNumber;
706 case PacketType.Stall:
708 byte numStalledPeers = mPacketReader.ReadByte();
709 byte[] stalledPeers = mPacketReader.ReadBytes(numStalledPeers);
716 Console.WriteLine("Received unknown packet type: " + (int)packetId);
723 int CurrentEventArrayIndex
725 get { return GetEventArrayIndexForFrame(mGame.CurrentFrameNumber); }
728 int GetEventArrayIndexForFrame(long frame)
730 return (int)(frame % MaximumLatency);
733 EventInfo ReadEvent(PacketReader packetReader, NetworkGamer sender)
735 EventType eventId = (EventType)packetReader.ReadByte();
736 long frameNumber = packetReader.ReadInt32();
740 case EventType.KeyDown:
742 Keys keyCode1 = (Keys)packetReader.ReadInt32();
743 return new KeyboardEventInfo(sender, frameNumber, keyCode1, true);
745 case EventType.KeyUp:
747 Keys keyCode2 = (Keys)packetReader.ReadInt32();
748 return new KeyboardEventInfo(sender, frameNumber, keyCode2, false);
750 case EventType.MouseDown:
752 MouseButton buttonId1 = (MouseButton)packetReader.ReadByte();
753 return new MouseButtonEventInfo(sender, frameNumber, buttonId1, true);
755 case EventType.MouseUp:
757 MouseButton buttonId2 = (MouseButton)packetReader.ReadByte();
758 return new MouseButtonEventInfo(sender, frameNumber, buttonId2, false);
760 case EventType.MouseMove:
762 short x = packetReader.ReadInt16();
763 short y = packetReader.ReadInt16();
764 return new MouseMotionEventInfo(sender, frameNumber, x, y);
768 Console.WriteLine("Received unknown event type: " + (int)eventId);
774 void WriteChatPacket(String message)
776 mPacketWriter.Write((byte)PacketType.Chat);
777 mPacketWriter.Write((short)message.Length);
778 mPacketWriter.Write(message.ToCharArray());
781 void WriteEventPacket(List<EventInfo> events, long highestFrameNumber)
783 mPacketWriter.Write((byte)PacketType.Event);
784 mPacketWriter.Write((short)mLastStallCount);
785 mPacketWriter.Write((short)mAverageOwd);
786 mPacketWriter.Write((int)highestFrameNumber);
787 mPacketWriter.Write((byte)events.Count);
789 foreach (EventInfo eventInfo in events)
791 mPacketWriter.Write((byte)eventInfo.Id);
792 mPacketWriter.Write((int)eventInfo.FrameOfApplication);
794 KeyboardEventInfo keyboardEventInfo = eventInfo as KeyboardEventInfo;
795 if (keyboardEventInfo != null)
797 mPacketWriter.Write((int)keyboardEventInfo.Key);
801 MouseButtonEventInfo mouseButtonEventInfo = eventInfo as MouseButtonEventInfo;
802 if (mouseButtonEventInfo != null)
804 mPacketWriter.Write((byte)mouseButtonEventInfo.Button);
808 MouseMotionEventInfo mouseMotionEventInfo = eventInfo as MouseMotionEventInfo;
809 if (mouseMotionEventInfo != null)
811 mPacketWriter.Write((short)mouseMotionEventInfo.X);
812 mPacketWriter.Write((short)mouseMotionEventInfo.Y);
819 bool IsLatencyAdjustmentFrame
823 return mNextLatencyAdjustmentFrame == mGame.CurrentFrameNumber;
829 Debug.Assert(IsLatencyAdjustmentFrame);
834 Console.WriteLine("STL#: " + mGame.CurrentFrameNumber + "\t" + mStallCount);
838 int maxStallCount = 0;
839 int maxAverageOwd = 0;
841 foreach (GamerInfo gamerInfo in GamerArray)
843 if (gamerInfo.StallCount > maxStallCount) maxStallCount = gamerInfo.StallCount;
844 if (gamerInfo.AverageOwd > maxAverageOwd) maxAverageOwd = gamerInfo.AverageOwd;
846 gamerInfo.StallCount = gamerInfo.NextStallCount;
847 gamerInfo.AverageOwd = gamerInfo.NextAverageOwd;
851 int prevLatency = mLatency;
854 if (maxStallCount > 0)
856 mLatency += maxStallCount;
860 mLatency -= (int)(0.6 * (double)(mLatency - maxAverageOwd) + 1.0);
863 if (mLatency < 1) mLatency = 1;
864 if (mLatency > MaximumLatency) mLatency = MaximumLatency;
867 if (prevLatency != mLatency) Console.WriteLine("NLAG: " + mLatency);
870 mNextLatencyAdjustmentFrame = mGame.CurrentFrameNumber + mLatency;
871 mAverageOwd = CurrentAverageOneWayDelay;
873 mLastLocalEvents = mLocalEvents;
874 mLocalEvents = new List<EventInfo>();
879 List<EventInfo> GetEventsFromInput()
881 List<EventInfo> events = new List<EventInfo>();
883 long frameOfApplication = mGame.CurrentFrameNumber + mLatency;
884 if (frameOfApplication <= mHighestFrameNumber) return events;
885 else mHighestFrameNumber = frameOfApplication;
887 // 1. Find the keyboard differences; written by Peter.
889 KeyboardState keyState = Keyboard.GetState();
891 List<Keys> pressedKeys = new List<Keys>();
892 List<Keys> releasedKeys = new List<Keys>();
894 Keys[] pressedKeysArray = keyState.GetPressedKeys();
895 foreach (Keys k in pressedKeysArray)
897 if (!mLastPressedKeys.Contains(k)) pressedKeys.Add(k);
898 else mLastPressedKeys.Remove(k);
901 releasedKeys = mLastPressedKeys;
903 foreach (Keys key in pressedKeys)
905 events.Add(new KeyboardEventInfo(LocalGamer, frameOfApplication, key, true));
907 foreach (Keys key in releasedKeys)
909 events.Add(new KeyboardEventInfo(LocalGamer, frameOfApplication, key, false));
913 if (pressedKeys.Contains(Keys.Escape)) mDontSendEvents = true;
914 if (releasedKeys.Contains(Keys.Escape)) mDontSendEvents = false;
917 // 2. Find the mouse differences.
919 MouseState mouseState = Mouse.GetState();
921 bool leftButtonPressed = mouseState.LeftButton == ButtonState.Pressed;
922 if (leftButtonPressed != mLastLeftButtonPressed)
924 events.Add(new MouseButtonEventInfo(LocalGamer, frameOfApplication, MouseButton.Left, leftButtonPressed));
927 bool rightButtonPressed = mouseState.RightButton == ButtonState.Pressed;
928 if (rightButtonPressed != mLastRightButtonPressed)
930 events.Add(new MouseButtonEventInfo(LocalGamer, frameOfApplication, MouseButton.Right, rightButtonPressed));
933 bool middleButtonPressed = mouseState.MiddleButton == ButtonState.Pressed;
934 if (middleButtonPressed != mLastMiddleButtonPressed)
936 events.Add(new MouseButtonEventInfo(LocalGamer, frameOfApplication, MouseButton.Middle, middleButtonPressed));
939 int mousePositionX = mouseState.X;
940 int mousePositionY = mouseState.Y;
941 if (mousePositionX != mLastMousePositionX || mousePositionY != mLastMousePositionY)
943 events.Add(new MouseMotionEventInfo(LocalGamer, frameOfApplication, mousePositionX, mousePositionY));
946 // 3. Save the current peripheral state.
948 mLastPressedKeys = new List<Keys>(pressedKeysArray);
949 mLastLeftButtonPressed = leftButtonPressed;
950 mLastRightButtonPressed = rightButtonPressed;
951 mLastMiddleButtonPressed = middleButtonPressed;
952 mLastMousePositionX = mousePositionX;
953 mLastMousePositionY = mousePositionY;
958 void SendLocalEvents()
960 SendLocalEvents((NetworkGamer)null);
963 void SendLocalEvents(List<NetworkGamer> recipicents)
965 foreach (NetworkGamer gamer in recipicents)
967 SendLocalEvents(gamer);
971 void SendLocalEvents(NetworkGamer recipient)
974 if (mDontSendEvents) return;
977 List<EventInfo> events = new List<EventInfo>(mLocalEvents);
978 events.AddRange(mLastLocalEvents);
980 if (recipient != null && !recipient.IsDisposed)
982 // if there is a recipient, we are resending old events
983 WriteEventPacket(events, mGame.CurrentFrameNumber - 1);
984 LocalGamer.SendData(mPacketWriter, SendDataOptions.Reliable, recipient);
988 WriteEventPacket(events, mGame.CurrentFrameNumber + mLatency);
989 LocalGamer.SendData(mPacketWriter, SendDataOptions.None);
994 bool HaveNeededEvents
998 long currentFrame = mGame.CurrentFrameNumber;
1000 foreach (GamerInfo gamerInfo in mGamers.Values)
1002 if (gamerInfo.HighestFrameNumber < currentFrame) return false;
1011 int index = CurrentEventArrayIndex;
1013 foreach (GamerInfo gamerInfo in GamerArray)
1015 if (gamerInfo.Events[index] == null) continue;
1017 foreach (EventInfo eventInfo in gamerInfo.Events[index])
1019 KeyboardEventInfo keyboardEventInfo = eventInfo as KeyboardEventInfo;
1020 if (keyboardEventInfo != null)
1023 Console.WriteLine(" KEY: " + keyboardEventInfo.FrameOfApplication + "\t" + keyboardEventInfo.Key + "," + keyboardEventInfo.IsKeyDown);
1026 mGame.ApplyKeyInput(gamerInfo, keyboardEventInfo.Key, keyboardEventInfo.IsKeyDown);
1030 MouseButtonEventInfo mouseButtonEventInfo = eventInfo as MouseButtonEventInfo;
1031 if (mouseButtonEventInfo != null)
1034 Console.WriteLine(" BTN: " + mouseButtonEventInfo.FrameOfApplication + "\t" + mouseButtonEventInfo.IsButtonDown);
1037 mGame.ApplyMouseButtonInput(gamerInfo, mouseButtonEventInfo.IsButtonDown);
1041 MouseMotionEventInfo mouseMotionEventInfo = eventInfo as MouseMotionEventInfo;
1042 if (mouseMotionEventInfo != null)
1045 Console.WriteLine(" MMV: " + mouseMotionEventInfo.FrameOfApplication + "\t" + mouseMotionEventInfo.X + "," + mouseMotionEventInfo.Y);
1048 mGame.ApplyMouseLocationInput(gamerInfo, mouseMotionEventInfo.X, mouseMotionEventInfo.Y);
1053 gamerInfo.Events[index] = null;
1058 int CurrentAverageOneWayDelay
1062 Debug.Assert(mNetworkSession != null);
1064 double numRemoteGamersTwice = 2 * mNetworkSession.RemoteGamers.Count;
1065 double averageOwd = 0;
1067 foreach (NetworkGamer gamer in mNetworkSession.RemoteGamers)
1069 TimeSpan timeSpan = gamer.RoundtripTime;
1070 averageOwd += timeSpan.TotalMilliseconds;
1073 return (int)((averageOwd / numRemoteGamersTwice) / 16.6666);