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