]> Dogcows Code - chaz/carfire/blob - Project06/CS 3505 Project 06/CS 3505 Project 06/NetworkGame.cs
95d843ec0b851cdec0efe96de456e6bbfe1f8b93
[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
12 namespace CS_3505_Project_06
13 {
14 /// <summary>
15 /// A manager class to handle network interactions between peers and
16 /// lobby/game switching.
17 /// </summary>
18 public class NetworkGame
19 {
20 // Private class variable members
21 #region Instance Variables
22
23 NetworkSession mNetworkSession;
24
25 JoinedSessionDelegate mJoinedSessionDelegate;
26 FoundSessionsDelegate mFoundSessionsDelegate;
27
28 ILobby mLobby;
29 IDeterministicGame mGame;
30
31 List<Keys> mLastPressedKeys = new List<Keys>();
32 bool mLastButtonPressed;
33
34 int mLatency;
35 long mNextLatencyAdjustmentFrame;
36 int mStallCount;
37 int mAverageOwd;
38
39 TimeSpan mTargetTimeSpan = new TimeSpan(166666);
40 public TimeSpan TargetTimeSpan
41 {
42 get
43 {
44 return mTargetTimeSpan;
45 }
46 }
47
48 #endregion
49
50
51 /// <summary>
52 /// Called when a session has been created or joined using CreateSession() or JoinSession().
53 /// </summary>
54 /// <param name="session">The new session that was created or joined.</param>
55 /// <param name="networkGame">The NetworkGame that joined the session.</param>
56 public delegate void JoinedSessionDelegate(NetworkSession session, NetworkGame networkGame);
57
58 /// <summary>
59 /// Called when sessions are found as a result of calling FindSessions().
60 /// </summary>
61 /// <param name="sessions">A container of the available sessions.</param>
62 /// <param name="networkGame">The NetworkGame that searched for the sessions.</param>
63 public delegate void FoundSessionsDelegate(AvailableNetworkSessionCollection sessions, NetworkGame networkGame);
64
65
66 /// <summary>
67 /// Construct a NetworkGame with a lobby and a game.
68 /// </summary>
69 /// <param name="lobby">Provides an associated lobby to update and draw.</param>
70 /// <param name="game">Provides a game object to be played over the network.</param>
71 public NetworkGame(ILobby lobby, IDeterministicGame game)
72 {
73 Debug.Assert(lobby != null && game != null);
74
75 mLobby = lobby;
76 mGame = game;
77 }
78
79
80 /// <summary>
81 /// Get the Gamer object for the local player.
82 /// </summary>
83 public LocalNetworkGamer LocalGamer
84 {
85 get
86 {
87 // TODO: Is this the correct way to get the single local gamer?
88 return mNetworkSession.LocalGamers[0];
89 }
90 }
91
92 /// <summary>
93 /// Get all the gamers associated with the active network session.
94 /// </summary>
95 public GamerCollection<NetworkGamer> NetworkGamers
96 {
97 get
98 {
99 return mNetworkSession.AllGamers;
100 }
101 }
102
103
104 /// <summary>
105 /// Begin a new network session with the local gamer as the host. You must not
106 /// call this method or use JoinSession without first using LeaveSession.
107 /// </summary>
108 /// <param name="callback">The delegate/method to call when the session is created.</param>
109 public void CreateSession(JoinedSessionDelegate callback)
110 {
111 CreateSession(mGame.MaximumSupportedPlayers, callback);
112 }
113
114 /// <summary>
115 /// Begin a new network session with the local gamer as the host. You must not
116 /// call this method or use JoinSession without first using LeaveSession.
117 /// </summary>
118 /// <param name="maxGamers">Provide the maximum number of players allowed to connect.</param>
119 /// <param name="callback">The delegate/method to call when the session is created.</param>
120 public void CreateSession(int maxGamers, JoinedSessionDelegate callback)
121 {
122 Debug.Assert(mNetworkSession == null);
123
124 mJoinedSessionDelegate = callback;
125 NetworkSession.BeginCreate(NetworkSessionType.SystemLink, 1, maxGamers, CreateSessionEnd, null);
126 }
127 private void CreateSessionEnd(IAsyncResult result)
128 {
129 Debug.Assert(mNetworkSession == null);
130
131 mNetworkSession = NetworkSession.EndCreate(result);
132 mNetworkSession.AllowHostMigration = true;
133 mNetworkSession.AllowJoinInProgress = false;
134
135 mJoinedSessionDelegate(mNetworkSession, this);
136 }
137
138 /// <summary>
139 /// Determine whether or not the network game object is associated with any network session.
140 /// </summary>
141 /// <returns>True if there exists a NetworkSession; false otherwise.</returns>
142 public bool HasActiveSession
143 {
144 get
145 {
146 return mNetworkSession != null;
147 }
148 }
149
150
151 /// <summary>
152 /// Find available sessions to join.
153 /// </summary>
154 /// <param name="callback">The delegate/method to call when the search finishes.</param>
155 public void FindSessions(FoundSessionsDelegate callback)
156 {
157 Debug.Assert(mNetworkSession == null);
158
159 mFoundSessionsDelegate = callback;
160 NetworkSession.BeginFind(NetworkSessionType.SystemLink, 1, null, new AsyncCallback(FindSessionsEnd), null);
161 }
162 private void FindSessionsEnd(IAsyncResult result)
163 {
164 AvailableNetworkSessionCollection sessions = NetworkSession.EndFind(result);
165 mFoundSessionsDelegate(sessions, this);
166 }
167
168 /// <summary>
169 /// Join a network session found using FindSessions(). This is for joining a game that
170 /// somebody else has already started hosting.
171 /// </summary>
172 /// <param name="availableSession">Pass the session object to try to join.</param>
173 /// <param name="callback">The delegate/method to call when the search finishes.</param>
174 public void JoinSession(AvailableNetworkSession availableSession, JoinedSessionDelegate callback)
175 {
176 Debug.Assert(mNetworkSession == null);
177
178 mJoinedSessionDelegate = callback;
179 NetworkSession.BeginJoin(availableSession, JoinSessionEnd, null);
180 }
181 private void JoinSessionEnd(IAsyncResult result)
182 {
183 Debug.Assert(mNetworkSession == null);
184
185 mNetworkSession = NetworkSession.EndJoin(result);
186
187 mJoinedSessionDelegate(mNetworkSession, this);
188 mJoinedSessionDelegate = null;
189 }
190
191
192 /// <summary>
193 /// Leave and dispose of any currently associated network session. You will find yourself
194 /// back in the lobby.
195 /// </summary>
196 public void LeaveSession()
197 {
198 Debug.Assert(mNetworkSession != null);
199
200 mNetworkSession.Dispose();
201 mNetworkSession = null;
202 }
203
204
205 /// <summary>
206 /// Set up the network session to simulate 200ms latency and 10% packet loss.
207 /// </summary>
208 public void SimulateBadNetwork()
209 {
210 Debug.Assert(mNetworkSession != null);
211
212 mNetworkSession.SimulatedLatency = new TimeSpan(0, 0, 0, 0, 200);
213 mNetworkSession.SimulatedPacketLoss = 0.1f;
214 }
215
216
217 /// <summary>
218 /// Indicate that the game should begin (moving players from the lobby to the game).
219 /// You must call CreateSession() before calling this.
220 /// </summary>
221 public void StartGame()
222 {
223 Debug.Assert(mNetworkSession != null && mNetworkSession.IsHost);
224
225 mNetworkSession.StartGame();
226 mNetworkSession.ResetReady();
227 }
228
229
230 /// <summary>
231 /// Manages the network session and allows either the lobby or game to update.
232 /// </summary>
233 /// <param name="gameTime">Pass the time away.</param>
234 public void Update(GameTime gameTime)
235 {
236 if (mNetworkSession == null)
237 {
238 mLobby.Update(gameTime, this);
239 }
240 else
241 {
242 mNetworkSession.Update();
243 ReadPackets();
244
245 if (mNetworkSession.SessionState == NetworkSessionState.Lobby)
246 {
247 if (mNetworkSession.IsHost &&
248 mNetworkSession.AllGamers.Count >= mGame.MinimumSupportedPlayers &&
249 mNetworkSession.IsEveryoneReady)
250 {
251 mNetworkSession.StartGame();
252 mNetworkSession.ResetReady();
253 }
254 else
255 {
256 mLobby.Update(gameTime, this);
257 }
258 }
259 else if (mNetworkSession.SessionState == NetworkSessionState.Playing)
260 {
261 if (HaveNeededEvents)
262 {
263 if (IsLatencyAdjustmentFrame) AdjustLatency();
264 mStallCount = 0;
265 SendLocalEvents();
266 ApplyEvents();
267 mGame.Update(mTargetTimeSpan);
268 }
269 else // Stall!
270 {
271 }
272 }
273 }
274 }
275
276 /// <summary>
277 /// Allows either the lobby or the game to draw, depending on the state
278 /// of the network connection and whether or not a game is in progress.
279 /// </summary>
280 /// <param name="gameTime">Pass the time away.</param>
281 /// <param name="spriteBatch">The sprite batch.</param>
282 public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
283 {
284 if (mNetworkSession == null)
285 {
286 mLobby.Draw(spriteBatch);
287 }
288 else
289 {
290 if (mNetworkSession.SessionState == NetworkSessionState.Lobby)
291 {
292 mLobby.Draw(spriteBatch);
293 }
294 else if (mNetworkSession.SessionState == NetworkSessionState.Playing)
295 {
296 mLobby.Draw(spriteBatch);
297 }
298 }
299 }
300
301
302 // Private implementation methods of the network protocol
303 #region Private Implementation Methods
304
305 /// <summary>
306 /// Reinitialize the private variables in preparation for new game to start.
307 /// </summary>
308 private void Reset()
309 {
310 mLatency = 1;
311 mNextLatencyAdjustmentFrame = 1;
312 mStallCount = 0;
313 mAverageOwd = AverageOneWayDelay;
314
315 // TODO: The game object needs to be reset, too.
316 //mGame.ResetGame(playerIdentifiers, playerIdentifiers[0]);
317 }
318
319
320 /// <summary>
321 /// Allows either the lobby or the game to draw, depending on the state
322 /// of the network connection and whether or not a game is in progress.
323 /// </summary>
324 /// <param name="gameTime">Pass the time away.</param>
325 /// <param name="spriteBatch">The sprite batch.</param>
326 private void ReadPackets()
327 {
328 PacketReader packetReader = new PacketReader();
329
330 foreach (LocalNetworkGamer gamer in mNetworkSession.LocalGamers)
331 {
332 while (gamer.IsDataAvailable)
333 {
334 NetworkGamer sender;
335
336 gamer.ReceiveData(packetReader, out sender);
337 byte packetId = packetReader.ReadByte();
338
339 switch (packetId)
340 {
341 // Chat Packet
342 case 1:
343 short messageLength = packetReader.ReadInt16();
344 char[] message = packetReader.ReadChars(messageLength);
345
346 ChatPacket chatPacket;
347 chatPacket.sender = sender;
348 chatPacket.message = new String(message);
349 break;
350
351 // Event Packet
352 case 2:
353 short stallCount = packetReader.ReadInt16();
354 short averageOwd = packetReader.ReadInt16();
355 int frameNumber = packetReader.ReadInt32();
356 byte numEvents = packetReader.ReadByte();
357
358 for (byte i = 0; i < numEvents; ++i)
359 {
360 ReadEvent(packetReader, sender);
361 }
362
363 break;
364
365 // Stall Packet
366 case 3:
367 byte numStalledPeers = packetReader.ReadByte();
368 byte[] stalledPeers = packetReader.ReadBytes(numStalledPeers);
369
370 break;
371 }
372 }
373 }
374 }
375
376 private void ReadEvent(PacketReader packetReader, NetworkGamer sender)
377 {
378 byte eventId = packetReader.ReadByte();
379 long applicationFrame = packetReader.ReadInt32();
380
381 switch (eventId)
382 {
383 // Key Down
384 case 1:
385 int keyCode1 = packetReader.ReadInt32();
386
387 break;
388
389 // Key Up
390 case 2:
391 int keyCode2 = packetReader.ReadInt32();
392
393 break;
394
395 // Mouse Down
396 case 3:
397 byte buttonId1 = packetReader.ReadByte();
398
399 break;
400
401 // Mouse Up
402 case 4:
403 byte buttonId2 = packetReader.ReadByte();
404
405 break;
406
407 // Mouse Move
408 case 5:
409 short x = packetReader.ReadInt16();
410 short y = packetReader.ReadInt16();
411
412 break;
413 }
414 }
415
416
417 private bool IsLatencyAdjustmentFrame
418 {
419 get
420 {
421 // TODO
422 return false;
423 }
424 }
425
426 private void AdjustLatency()
427 {
428 // TODO
429 }
430
431
432 private void SendLocalEvents()
433 {
434 // TODO: Not finished.
435
436 KeyboardState keyState = Keyboard.GetState();
437 MouseState mouseState = Mouse.GetState();
438
439 // Make a list of the keys pressed or released this frame.
440
441 List<Keys> pressedKeys = new List<Keys>();
442 List<Keys> releasedKeys = new List<Keys>();
443
444 Keys[] pressedKeysArray = keyState.GetPressedKeys();
445 foreach (Keys k in pressedKeysArray)
446 if (!mLastPressedKeys.Contains(k))
447 pressedKeys.Add(k);
448 else
449 mLastPressedKeys.Remove(k);
450
451 releasedKeys = mLastPressedKeys;
452 mLastPressedKeys = new List<Keys>(pressedKeysArray);
453
454 bool buttonPressed = mouseState.LeftButton == ButtonState.Pressed;
455 }
456
457
458 private bool HaveNeededEvents
459 {
460 get
461 {
462 // TODO
463 return true;
464 }
465 }
466
467 private void ApplyEvents()
468 {
469 // TODO
470 }
471
472
473 private int AverageOneWayDelay
474 {
475 get
476 {
477 // TODO
478 return 12;
479 }
480 }
481
482 #endregion
483 }
484 }
This page took 0.060967 seconds and 3 git commands to generate.