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