X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=Project06%2FCS%203505%20Project%2006%2FCS%203505%20Project%2006%2FNetworkGame.cs;h=c69e2fb71fc6f2beb58cf66f0baed10eec3b2535;hb=d4d977b0086ecf7ac950863cb0ecdd7e42804c43;hp=2386ef60717983e77271ee1aa4a81a16683769c9;hpb=9187849a37e447f2440ef8257e15e8652f0c51e8;p=chaz%2Fcarfire 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 2386ef6..c69e2fb 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 @@ -36,6 +36,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,15 +112,28 @@ 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; - + 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; + } + void GameStartedEvent(object sender, GameStartedEventArgs e) + { + Reset(); } /// @@ -133,10 +161,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; } /// @@ -152,12 +190,20 @@ 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; } @@ -209,8 +255,6 @@ namespace CS_3505_Project_06 { mNetworkSession.StartGame(); mNetworkSession.ResetReady(); - - //Reset(); } @@ -232,31 +276,22 @@ namespace CS_3505_Project_06 if (mNetworkSession.SessionState == NetworkSessionState.Lobby) { mLobby.Update(gameTime, this); - - //if state started as lobby and was changed to playing, call reset. - if (mNetworkSession.SessionState == NetworkSessionState.Playing) - Reset(); } 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()); @@ -266,11 +301,27 @@ namespace CS_3505_Project_06 } else // Stall! { + if (mStallCount == 0) + { + Console.WriteLine("===== STALL ====="); + } + else if (mStallCount % 60 == 0) + { + 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) @@ -317,7 +368,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. @@ -347,6 +398,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); } @@ -380,10 +433,15 @@ namespace CS_3505_Project_06 int mLastMousePositionY; int mLatency; + long mHighestFrameNumber; long mNextLatencyAdjustmentFrame; int mStallCount; + int mLastStallCount; int mAverageOwd; + // DEBUG + bool mDontSendEvents; + TimeSpan mTargetTimeSpan = new TimeSpan(166666); public TimeSpan TargetTimeSpan { @@ -517,9 +575,11 @@ namespace CS_3505_Project_06 class GamerInfo { public NetworkGamer Gamer; - public long HighestFrameNumber = 0; + public long HighestFrameNumber = -1; 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]; @@ -544,8 +604,10 @@ namespace CS_3505_Project_06 void Reset() { mLatency = 1; + mHighestFrameNumber = -1; mNextLatencyAdjustmentFrame = 1; mStallCount = 0; + mLastStallCount = 0; mAverageOwd = CurrentAverageOneWayDelay; mGamers = new Dictionary(); @@ -583,10 +645,10 @@ 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 <= senderInfo.HighestFrameNumber) { @@ -594,20 +656,28 @@ namespace CS_3505_Project_06 break; } - for (byte i = 0; i < numEvents; ++i) + 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; + if (frameNumber <= mNextLatencyAdjustmentFrame) + { + senderInfo.StallCount = stallCount; + senderInfo.AverageOwd = averageOwd; + } + else + { + senderInfo.NextStallCount = stallCount; + senderInfo.NextAverageOwd = averageOwd; + } senderInfo.HighestFrameNumber = frameNumber; break; @@ -617,7 +687,6 @@ namespace CS_3505_Project_06 byte[] stalledPeers = mPacketReader.ReadBytes(numStalledPeers); // TODO - break; default: @@ -629,9 +698,14 @@ namespace CS_3505_Project_06 } - int EventArrayIndex + int CurrentEventArrayIndex + { + get { return GetEventArrayIndexForFrame(mGame.CurrentFrameNumber); } + } + + int GetEventArrayIndexForFrame(long frame) { - get { return (int)(mGame.CurrentFrameNumber % MaximumLatency); } + return (int)(frame % MaximumLatency); } EventInfo ReadEvent(PacketReader packetReader, NetworkGamer sender) @@ -643,23 +717,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: @@ -685,7 +759,7 @@ namespace CS_3505_Project_06 void WriteEventPacket(List events) { 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((byte)events.Count); @@ -739,6 +813,9 @@ 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 @@ -772,6 +849,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(); @@ -790,13 +871,17 @@ 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)); } + // DEBUG + if (pressedKeys.Contains(Keys.Escape)) mDontSendEvents = true; + if (releasedKeys.Contains(Keys.Escape)) mDontSendEvents = false; + // 2. Find the mouse differences. MouseState mouseState = Mouse.GetState(); @@ -804,26 +889,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. @@ -853,12 +938,15 @@ namespace CS_3505_Project_06 void SendLocalEvents(NetworkGamer recipient) { + // DEBUG + if (mDontSendEvents) return; + List events = new List(mLocalEvents); events.AddRange(mLastLocalEvents); WriteEventPacket(events); - if (recipient != null) + if (recipient != null && !recipient.IsDisposed) { LocalGamer.SendData(mPacketWriter, SendDataOptions.Reliable, recipient); } @@ -886,7 +974,7 @@ namespace CS_3505_Project_06 void ApplyEvents() { - int index = EventArrayIndex; + int index = CurrentEventArrayIndex; foreach (GamerInfo gamerInfo in GamerArray) { @@ -897,6 +985,7 @@ namespace CS_3505_Project_06 KeyboardEventInfo keyboardEventInfo = eventInfo as KeyboardEventInfo; if (keyboardEventInfo != null) { + Console.WriteLine(keyboardEventInfo.FrameOfApplication + " KEY: " + keyboardEventInfo.Key + "," + keyboardEventInfo.IsKeyDown); mGame.ApplyKeyInput(gamerInfo, keyboardEventInfo.Key, keyboardEventInfo.IsKeyDown); continue; } @@ -905,6 +994,7 @@ namespace CS_3505_Project_06 if (mouseButtonEventInfo != null) { mGame.ApplyMouseButtonInput(gamerInfo, mouseButtonEventInfo.IsButtonDown); + Console.WriteLine(mouseButtonEventInfo.FrameOfApplication + " BTN: " + mouseButtonEventInfo.IsButtonDown); continue; } @@ -912,6 +1002,7 @@ namespace CS_3505_Project_06 if (mouseMotionEventInfo != null) { mGame.ApplyMouseLocationInput(gamerInfo, mouseMotionEventInfo.X, mouseMotionEventInfo.Y); + Console.WriteLine(mouseMotionEventInfo.FrameOfApplication + " MMV: " + mouseMotionEventInfo.X + "," + mouseMotionEventInfo.Y); continue; } } @@ -936,7 +1027,7 @@ namespace CS_3505_Project_06 averageOwd += timeSpan.TotalMilliseconds; } - return (int)(averageOwd / numRemoteGamersTwice / 16.6666); + return (int)((averageOwd / numRemoteGamersTwice) / 16.6666); } }