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