X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fcarfire;a=blobdiff_plain;f=Project06%2FCS%203505%20Project%2006%2FCS%203505%20Project%2006%2FNetworkGame.cs;h=45c5d0a498fdd5a1ce9de1445b85cdbd309a6187;hp=2265329d31dc76b6aa60b32dcfd9d1535e64da6e;hb=b98320a31a73dc18d6ef83cb440a5304930af161;hpb=d0f378bf29a27149c71f114e1c148ef05d01c782
diff --git a/Project06/CS 3505 Project 06/CS 3505 Project 06/NetworkGame.cs b/Project06/CS 3505 Project 06/CS 3505 Project 06/NetworkGame.cs
index 2265329..45c5d0a 100644
--- a/Project06/CS 3505 Project 06/CS 3505 Project 06/NetworkGame.cs
+++ b/Project06/CS 3505 Project 06/CS 3505 Project 06/NetworkGame.cs
@@ -1,4 +1,7 @@
-using System;
+
+#undef DEBUG
+
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -36,6 +39,21 @@ namespace CS_3505_Project_06
public delegate void FoundSessionsDelegate(AvailableNetworkSessionCollection sessions, NetworkGame networkGame);
+ ///
+ /// Called when an exception is thrown during an asynchronous operation.
+ ///
+ /// The exception that was thrown.
+ /// The NetworkGame that errored.
+ public delegate void CaughtErrorDelegate(Exception exception, NetworkGame networkGame);
+
+ ///
+ /// Get and set the error delegate, called when an exception is thrown during
+ /// and asynchronous operation. This will occur if you try to create or join a
+ /// session without being logged into a profile.
+ ///
+ public CaughtErrorDelegate ErrorDelegate;
+
+
///
/// Construct a NetworkGame with a lobby and a game.
///
@@ -97,20 +115,26 @@ namespace CS_3505_Project_06
mJoinedSessionDelegate = callback;
NetworkSession.BeginCreate(NetworkSessionType.SystemLink, 1, maxGamers, CreateSessionEnd, null);
}
- private void CreateSessionEnd(IAsyncResult result)
+ void CreateSessionEnd(IAsyncResult result)
{
Debug.Assert(mNetworkSession == null);
- mNetworkSession = NetworkSession.EndCreate(result);
- mNetworkSession.AllowHostMigration = true;
- mNetworkSession.AllowJoinInProgress = false;
- mNetworkSession.GameStarted += new EventHandler(mNetworkSession_GameStarted);
+ try
+ {
+ mNetworkSession = NetworkSession.EndCreate(result);
+ mNetworkSession.AllowHostMigration = true;
+ mNetworkSession.AllowJoinInProgress = false;
+ mNetworkSession.GameStarted += new EventHandler(GameStartedEvent);
+ }
+ catch (Exception e)
+ {
+ if (ErrorDelegate != null) ErrorDelegate(e, this);
+ return;
+ }
mJoinedSessionDelegate(mNetworkSession, this);
+ mJoinedSessionDelegate = null;
}
-
-
- //gamestarted event
- void mNetworkSession_GameStarted(object sender, GameStartedEventArgs e)
+ void GameStartedEvent(object sender, GameStartedEventArgs e)
{
Reset();
}
@@ -140,10 +164,20 @@ namespace CS_3505_Project_06
mFoundSessionsDelegate = callback;
NetworkSession.BeginFind(NetworkSessionType.SystemLink, 1, null, new AsyncCallback(FindSessionsEnd), null);
}
- private void FindSessionsEnd(IAsyncResult result)
+ void FindSessionsEnd(IAsyncResult result)
{
- AvailableNetworkSessionCollection sessions = NetworkSession.EndFind(result);
+ AvailableNetworkSessionCollection sessions;
+ try
+ {
+ sessions = NetworkSession.EndFind(result);
+ }
+ catch (Exception e)
+ {
+ if (ErrorDelegate != null) ErrorDelegate(e, this);
+ return;
+ }
mFoundSessionsDelegate(sessions, this);
+ mFoundSessionsDelegate = null;
}
///
@@ -159,16 +193,22 @@ namespace CS_3505_Project_06
mJoinedSessionDelegate = callback;
NetworkSession.BeginJoin(availableSession, JoinSessionEnd, null);
}
- private void JoinSessionEnd(IAsyncResult result)
+ void JoinSessionEnd(IAsyncResult result)
{
Debug.Assert(mNetworkSession == null);
- mNetworkSession = NetworkSession.EndJoin(result);
-
+ try
+ {
+ mNetworkSession = NetworkSession.EndJoin(result);
+ mNetworkSession.GameStarted += new EventHandler(GameStartedEvent);
+ }
+ catch (Exception e)
+ {
+ if (ErrorDelegate != null) ErrorDelegate(e, this);
+ return;
+ }
mJoinedSessionDelegate(mNetworkSession, this);
mJoinedSessionDelegate = null;
-
- mNetworkSession.GameStarted += new EventHandler(mNetworkSession_GameStarted);
}
@@ -218,8 +258,6 @@ namespace CS_3505_Project_06
{
mNetworkSession.StartGame();
mNetworkSession.ResetReady();
-
- //Reset();
}
@@ -244,38 +282,57 @@ namespace CS_3505_Project_06
}
else if (mNetworkSession.SessionState == NetworkSessionState.Playing)
{
- //TODO reset needs to be called for all players, currently LocalGamerInfo throughs exception for all nonhosts
- // because in start game reset is only called on hosts games thus other clients never get an updated list
- // gamers.
-
-
-//thoughs exeption see TODO above
- //if (mGame.IsGameOver(LocalGamerInfo) || mGame.IsTerminated(LocalGamerInfo))
- //{
- // // TODO: Should support moving back to the session lobby.
- // LeaveSession();
- // return;
- //}
+ if (mGame.IsGameOver(LocalGamerInfo) || mGame.IsTerminated(LocalGamerInfo))
+ {
+ // TODO: Should support moving back to the session lobby.
+ LeaveSession();
+ return;
+ }
if (HaveNeededEvents)
{
if (IsLatencyAdjustmentFrame)
{
AdjustLatency();
+ mLastStallCount = mStallCount;
mStallCount = 0;
}
mLocalEvents.AddRange(GetEventsFromInput());
SendLocalEvents();
ApplyEvents();
+
+#if DEBUG
+ Console.WriteLine("HASH: " + mGame.CurrentFrameNumber + "\t" + mGame.CurrentChecksum);
+#endif
+
mGame.Update(mTargetTimeSpan);
}
else // Stall!
{
+ if (mStallCount == 0)
+ {
+#if DEBUG
+ Console.WriteLine("STAL: ====");
+#endif
+ }
+ else if (mStallCount % 60 == 0)
+ {
+ // DEBUG
+ //Console.WriteLine("Stalled for " + mStallCount + " frames.");
+ }
+
mStallCount++;
- if (mStallCount % 60 == 0)
+ // Send a reliable event packet to each stalled gamer.
+ if (mStallCount == 1)
{
- Console.WriteLine("Stalled for " + mStallCount + " frames.");
+ foreach (GamerInfo gamerInfo in GamerArray)
+ {
+ if (gamerInfo.HighestFrameNumber < mGame.CurrentFrameNumber)
+ {
+ SendLocalEvents(gamerInfo.Gamer);
+ }
+ }
}
/*if (mStallCount > StallTimeout)
@@ -322,7 +379,7 @@ namespace CS_3505_Project_06
///
- /// Get the chat messages that have been receive since the last time this
+ /// Get the chat messages that have been received since the last time this
/// method was called.
///
/// List container of the chat messages.
@@ -352,6 +409,8 @@ namespace CS_3505_Project_06
/// The gamer to receive the message.
public void SendChat(String message, NetworkGamer recipient)
{
+ Debug.Assert(recipient != null && !recipient.IsDisposed);
+
WriteChatPacket(message);
LocalGamer.SendData(mPacketWriter, SendDataOptions.ReliableInOrder, recipient);
}
@@ -385,10 +444,16 @@ namespace CS_3505_Project_06
int mLastMousePositionY;
int mLatency;
+ long mHighestFrameNumber;
long mNextLatencyAdjustmentFrame;
int mStallCount;
+ int mLastStallCount;
int mAverageOwd;
+#if DEBUG
+ bool mDontSendEvents;
+#endif
+
TimeSpan mTargetTimeSpan = new TimeSpan(166666);
public TimeSpan TargetTimeSpan
{
@@ -525,6 +590,8 @@ namespace CS_3505_Project_06
public long HighestFrameNumber = 0;
public int StallCount = 0;
public int AverageOwd = 0;
+ public int NextStallCount = 0;
+ public int NextAverageOwd = 0;
public bool IsWaitedOn = false;
public List[] Events = new List[MaximumLatency];
@@ -549,8 +616,10 @@ namespace CS_3505_Project_06
void Reset()
{
mLatency = 1;
+ mHighestFrameNumber = 0;
mNextLatencyAdjustmentFrame = 1;
mStallCount = 0;
+ mLastStallCount = 0;
mAverageOwd = CurrentAverageOneWayDelay;
mGamers = new Dictionary();
@@ -572,6 +641,7 @@ namespace CS_3505_Project_06
NetworkGamer sender;
localGamer.ReceiveData(mPacketReader, out sender);
+ if (sender == null || sender.IsDisposed) continue;
GamerInfo senderInfo = mGamers[sender.Id];
PacketType packetId = (PacketType)mPacketReader.ReadByte();
@@ -588,31 +658,48 @@ namespace CS_3505_Project_06
case PacketType.Event:
- short stallCount = mPacketReader.ReadInt16();
- short averageOwd = mPacketReader.ReadInt16();
+ int stallCount = mPacketReader.ReadInt16();
+ int averageOwd = mPacketReader.ReadInt16();
int frameNumber = mPacketReader.ReadInt32();
- byte numEvents = mPacketReader.ReadByte();
+ int numEvents = mPacketReader.ReadByte();
+
+ if (frameNumber <= mNextLatencyAdjustmentFrame)
+ {
+ senderInfo.StallCount = stallCount;
+ senderInfo.AverageOwd = averageOwd;
+ }
+ else
+ {
+ senderInfo.NextStallCount = stallCount;
+ senderInfo.NextAverageOwd = averageOwd;
+ }
if (frameNumber <= senderInfo.HighestFrameNumber)
{
+#if DEBUG
+ Console.WriteLine("SKP" + (char)sender.Id + ": " + mGame.CurrentFrameNumber + "\t" + frameNumber + "\t<=\t" + senderInfo.HighestFrameNumber + "\t#" + numEvents);
+#endif
+
// we know about all these events, so don't bother reading them
break;
}
- for (byte i = 0; i < numEvents; ++i)
+#if DEBUG
+ Console.WriteLine(" GOT" + (char)sender.Id + ": " + mGame.CurrentFrameNumber + "\t" + frameNumber + "\t>\t" + senderInfo.HighestFrameNumber + "\t#" + numEvents);
+#endif
+
+ for (int i = 0; i < numEvents; i++)
{
EventInfo eventInfo = ReadEvent(mPacketReader, sender);
- if (eventInfo != null && eventInfo.FrameOfApplication < senderInfo.HighestFrameNumber)
+ if (eventInfo != null && eventInfo.FrameOfApplication > senderInfo.HighestFrameNumber)
{
- int index = EventArrayIndex;
+ int index = GetEventArrayIndexForFrame(eventInfo.FrameOfApplication);
if (senderInfo.Events[index] == null) senderInfo.Events[index] = new List();
senderInfo.Events[index].Add(eventInfo);
}
}
- senderInfo.StallCount = stallCount;
- senderInfo.AverageOwd = averageOwd;
senderInfo.HighestFrameNumber = frameNumber;
break;
@@ -622,7 +709,6 @@ namespace CS_3505_Project_06
byte[] stalledPeers = mPacketReader.ReadBytes(numStalledPeers);
// TODO
-
break;
default:
@@ -634,9 +720,14 @@ namespace CS_3505_Project_06
}
- int EventArrayIndex
+ int CurrentEventArrayIndex
{
- get { return (int)(mGame.CurrentFrameNumber % MaximumLatency); }
+ get { return GetEventArrayIndexForFrame(mGame.CurrentFrameNumber); }
+ }
+
+ int GetEventArrayIndexForFrame(long frame)
+ {
+ return (int)(frame % MaximumLatency);
}
EventInfo ReadEvent(PacketReader packetReader, NetworkGamer sender)
@@ -648,23 +739,23 @@ namespace CS_3505_Project_06
{
case EventType.KeyDown:
- int keyCode1 = packetReader.ReadInt32();
- return new KeyboardEventInfo(sender, frameNumber, (Keys)keyCode1, true);
+ Keys keyCode1 = (Keys)packetReader.ReadInt32();
+ return new KeyboardEventInfo(sender, frameNumber, keyCode1, true);
case EventType.KeyUp:
- int keyCode2 = packetReader.ReadInt32();
- return new KeyboardEventInfo(sender, frameNumber, (Keys)keyCode2, false);
+ Keys keyCode2 = (Keys)packetReader.ReadInt32();
+ return new KeyboardEventInfo(sender, frameNumber, keyCode2, false);
case EventType.MouseDown:
- byte buttonId1 = packetReader.ReadByte();
- return new MouseButtonEventInfo(sender, frameNumber, (MouseButton)buttonId1, true);
+ MouseButton buttonId1 = (MouseButton)packetReader.ReadByte();
+ return new MouseButtonEventInfo(sender, frameNumber, buttonId1, true);
case EventType.MouseUp:
- byte buttonId2 = packetReader.ReadByte();
- return new MouseButtonEventInfo(sender, frameNumber, (MouseButton)buttonId2, false);
+ MouseButton buttonId2 = (MouseButton)packetReader.ReadByte();
+ return new MouseButtonEventInfo(sender, frameNumber, buttonId2, false);
case EventType.MouseMove:
@@ -687,12 +778,12 @@ namespace CS_3505_Project_06
mPacketWriter.Write(message.ToCharArray());
}
- void WriteEventPacket(List events)
+ void WriteEventPacket(List events, long highestFrameNumber)
{
mPacketWriter.Write((byte)PacketType.Event);
- mPacketWriter.Write((short)mStallCount);
+ mPacketWriter.Write((short)mLastStallCount);
mPacketWriter.Write((short)mAverageOwd);
- mPacketWriter.Write((int)(mGame.CurrentFrameNumber + mLatency));
+ mPacketWriter.Write((int)highestFrameNumber);
mPacketWriter.Write((byte)events.Count);
foreach (EventInfo eventInfo in events)
@@ -737,6 +828,13 @@ namespace CS_3505_Project_06
{
Debug.Assert(IsLatencyAdjustmentFrame);
+#if DEBUG
+ if (mStallCount > 0)
+ {
+ Console.WriteLine("STL#: " + mGame.CurrentFrameNumber + "\t" + mStallCount);
+ }
+#endif
+
int maxStallCount = 0;
int maxAverageOwd = 0;
@@ -744,10 +842,14 @@ namespace CS_3505_Project_06
{
if (gamerInfo.StallCount > maxStallCount) maxStallCount = gamerInfo.StallCount;
if (gamerInfo.AverageOwd > maxAverageOwd) maxAverageOwd = gamerInfo.AverageOwd;
+
+ gamerInfo.StallCount = gamerInfo.NextStallCount;
+ gamerInfo.AverageOwd = gamerInfo.NextAverageOwd;
}
- // DEBUG
+#if DEBUG
int prevLatency = mLatency;
+#endif
if (maxStallCount > 0)
{
@@ -755,15 +857,16 @@ namespace CS_3505_Project_06
}
else
{
- mLatency = (int)(0.6 * (double)(mLatency - maxAverageOwd) + 1.0);
+ mLatency -= (int)(0.6 * (double)(mLatency - maxAverageOwd) + 1.0);
}
- // DEBUG OUTPUT
- if (prevLatency != mLatency) Console.WriteLine("Latency readjusted to " + mLatency);
-
if (mLatency < 1) mLatency = 1;
if (mLatency > MaximumLatency) mLatency = MaximumLatency;
+#if DEBUG
+ if (prevLatency != mLatency) Console.WriteLine("NLAG: " + mLatency);
+#endif
+
mNextLatencyAdjustmentFrame = mGame.CurrentFrameNumber + mLatency;
mAverageOwd = CurrentAverageOneWayDelay;
@@ -777,6 +880,10 @@ namespace CS_3505_Project_06
{
List events = new List();
+ long frameOfApplication = mGame.CurrentFrameNumber + mLatency;
+ if (frameOfApplication <= mHighestFrameNumber) return events;
+ else mHighestFrameNumber = frameOfApplication;
+
// 1. Find the keyboard differences; written by Peter.
KeyboardState keyState = Keyboard.GetState();
@@ -795,13 +902,18 @@ namespace CS_3505_Project_06
foreach (Keys key in pressedKeys)
{
- events.Add(new KeyboardEventInfo(LocalGamer, mGame.CurrentFrameNumber, key, true));
+ events.Add(new KeyboardEventInfo(LocalGamer, frameOfApplication, key, true));
}
foreach (Keys key in releasedKeys)
{
- events.Add(new KeyboardEventInfo(LocalGamer, mGame.CurrentFrameNumber, key, false));
+ events.Add(new KeyboardEventInfo(LocalGamer, frameOfApplication, key, false));
}
+#if DEBUG
+ if (pressedKeys.Contains(Keys.Escape)) mDontSendEvents = true;
+ if (releasedKeys.Contains(Keys.Escape)) mDontSendEvents = false;
+#endif
+
// 2. Find the mouse differences.
MouseState mouseState = Mouse.GetState();
@@ -809,26 +921,26 @@ namespace CS_3505_Project_06
bool leftButtonPressed = mouseState.LeftButton == ButtonState.Pressed;
if (leftButtonPressed != mLastLeftButtonPressed)
{
- events.Add(new MouseButtonEventInfo(LocalGamer, mGame.CurrentFrameNumber, MouseButton.Left, leftButtonPressed));
+ events.Add(new MouseButtonEventInfo(LocalGamer, frameOfApplication, MouseButton.Left, leftButtonPressed));
}
- bool rightButtonPressed = mouseState.LeftButton == ButtonState.Pressed;
+ bool rightButtonPressed = mouseState.RightButton == ButtonState.Pressed;
if (rightButtonPressed != mLastRightButtonPressed)
{
- events.Add(new MouseButtonEventInfo(LocalGamer, mGame.CurrentFrameNumber, MouseButton.Right, rightButtonPressed));
+ events.Add(new MouseButtonEventInfo(LocalGamer, frameOfApplication, MouseButton.Right, rightButtonPressed));
}
- bool middleButtonPressed = mouseState.LeftButton == ButtonState.Pressed;
+ bool middleButtonPressed = mouseState.MiddleButton == ButtonState.Pressed;
if (middleButtonPressed != mLastMiddleButtonPressed)
{
- events.Add(new MouseButtonEventInfo(LocalGamer, mGame.CurrentFrameNumber, MouseButton.Middle, middleButtonPressed));
+ events.Add(new MouseButtonEventInfo(LocalGamer, frameOfApplication, MouseButton.Middle, middleButtonPressed));
}
int mousePositionX = mouseState.X;
int mousePositionY = mouseState.Y;
if (mousePositionX != mLastMousePositionX || mousePositionY != mLastMousePositionY)
{
- events.Add(new MouseMotionEventInfo(LocalGamer, mGame.CurrentFrameNumber, mousePositionX, mousePositionY));
+ events.Add(new MouseMotionEventInfo(LocalGamer, frameOfApplication, mousePositionX, mousePositionY));
}
// 3. Save the current peripheral state.
@@ -858,17 +970,22 @@ namespace CS_3505_Project_06
void SendLocalEvents(NetworkGamer recipient)
{
+#if DEBUG
+ if (mDontSendEvents) return;
+#endif
+
List events = new List(mLocalEvents);
events.AddRange(mLastLocalEvents);
- WriteEventPacket(events);
-
- if (recipient != null)
+ if (recipient != null && !recipient.IsDisposed)
{
+ // if there is a recipient, we are resending old events
+ WriteEventPacket(events, mGame.CurrentFrameNumber - 1);
LocalGamer.SendData(mPacketWriter, SendDataOptions.Reliable, recipient);
}
else
{
+ WriteEventPacket(events, mGame.CurrentFrameNumber + mLatency);
LocalGamer.SendData(mPacketWriter, SendDataOptions.None);
}
}
@@ -891,7 +1008,7 @@ namespace CS_3505_Project_06
void ApplyEvents()
{
- int index = EventArrayIndex;
+ int index = CurrentEventArrayIndex;
foreach (GamerInfo gamerInfo in GamerArray)
{
@@ -902,6 +1019,10 @@ namespace CS_3505_Project_06
KeyboardEventInfo keyboardEventInfo = eventInfo as KeyboardEventInfo;
if (keyboardEventInfo != null)
{
+#if DEBUG
+ Console.WriteLine(" KEY: " + keyboardEventInfo.FrameOfApplication + "\t" + keyboardEventInfo.Key + "," + keyboardEventInfo.IsKeyDown);
+#endif
+
mGame.ApplyKeyInput(gamerInfo, keyboardEventInfo.Key, keyboardEventInfo.IsKeyDown);
continue;
}
@@ -909,6 +1030,10 @@ namespace CS_3505_Project_06
MouseButtonEventInfo mouseButtonEventInfo = eventInfo as MouseButtonEventInfo;
if (mouseButtonEventInfo != null)
{
+#if DEBUG
+ Console.WriteLine(" BTN: " + mouseButtonEventInfo.FrameOfApplication + "\t" + mouseButtonEventInfo.IsButtonDown);
+#endif
+
mGame.ApplyMouseButtonInput(gamerInfo, mouseButtonEventInfo.IsButtonDown);
continue;
}
@@ -916,6 +1041,10 @@ namespace CS_3505_Project_06
MouseMotionEventInfo mouseMotionEventInfo = eventInfo as MouseMotionEventInfo;
if (mouseMotionEventInfo != null)
{
+#if DEBUG
+ Console.WriteLine(" MMV: " + mouseMotionEventInfo.FrameOfApplication + "\t" + mouseMotionEventInfo.X + "," + mouseMotionEventInfo.Y);
+#endif
+
mGame.ApplyMouseLocationInput(gamerInfo, mouseMotionEventInfo.X, mouseMotionEventInfo.Y);
continue;
}
@@ -941,7 +1070,7 @@ namespace CS_3505_Project_06
averageOwd += timeSpan.TotalMilliseconds;
}
- return (int)(averageOwd / numRemoteGamersTwice / 16.6666);
+ return (int)((averageOwd / numRemoteGamersTwice) / 16.6666);
}
}