From 904f5665bb8ea18a6a32d10632e2a0da2244b494 Mon Sep 17 00:00:00 2001 From: Charles Date: Mon, 29 Mar 2010 22:36:27 +0000 Subject: [PATCH] Some bug fixes, including many synchronization issues. Some sync issues remain. git-svn-id: https://bd85.net/svn/cs3505_group@38 92bb83a3-7c8f-8a45-bc97-515c4e399668 --- .../CS 3505 Project 06/CS 3505/TestHarness.cs | 6 +- .../CS 3505 Project 06/NetworkGame.cs | 136 ++++++++++++------ 2 files changed, 97 insertions(+), 45 deletions(-) diff --git a/Project06/CS 3505 Project 06/CS 3505 Project 06/CS 3505/TestHarness.cs b/Project06/CS 3505 Project 06/CS 3505 Project 06/CS 3505/TestHarness.cs index 1f01f03..b4860a4 100644 --- a/Project06/CS 3505 Project 06/CS 3505 Project 06/CS 3505/TestHarness.cs +++ b/Project06/CS 3505 Project 06/CS 3505 Project 06/CS 3505/TestHarness.cs @@ -294,6 +294,10 @@ namespace CS_3505_Project_06.CS_3505 public long Update(TimeSpan elapsedTime) { + // Draw() can be called multiple times between updates, so moved this here to avoid + // duplicate lines. + Console.WriteLine("Frame: " + state.frameNumber + " Checksum: " + state.Checksum); + state.advanceFrame(inputs, elapsedTime.Milliseconds); // Apply the inputs, advance game state. inputs = new NextInputs(); // Start with inputs cleared on the next frame. @@ -311,8 +315,6 @@ namespace CS_3505_Project_06.CS_3505 nameHexPair(spriteBatch, Color.White, "Checksum:", state.Checksum, 215, 515, 100); nameDecPair(spriteBatch, Color.White, "Elapsed Time:", state.elapsedTime / 1000.0f, 570, 790, 100); - Console.WriteLine("Frame: " + state.frameNumber + " Checksum: " + state.Checksum); - printPlayer(spriteBatch, Color.Turquoise, 0, 10, 190, 170); printPlayer(spriteBatch, Color.Wheat, 1, 210, 390, 170); printPlayer(spriteBatch, Color.Tomato, 2, 410, 590, 170); 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 792d16d..55d8b2e 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 @@ -112,7 +112,7 @@ 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); @@ -121,7 +121,7 @@ namespace CS_3505_Project_06 mNetworkSession = NetworkSession.EndCreate(result); mNetworkSession.AllowHostMigration = true; mNetworkSession.AllowJoinInProgress = false; - mNetworkSession.GameStarted += new EventHandler(mNetworkSession_GameStarted); + mNetworkSession.GameStarted += new EventHandler(GameStartedEvent); } catch (Exception e) { @@ -131,10 +131,7 @@ namespace CS_3505_Project_06 mJoinedSessionDelegate(mNetworkSession, this); mJoinedSessionDelegate = null; } - - - //gamestarted event - void mNetworkSession_GameStarted(object sender, GameStartedEventArgs e) + void GameStartedEvent(object sender, GameStartedEventArgs e) { Reset(); } @@ -164,7 +161,7 @@ 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; try @@ -193,14 +190,14 @@ 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); try { mNetworkSession = NetworkSession.EndJoin(result); - mNetworkSession.GameStarted += new EventHandler(mNetworkSession_GameStarted); + mNetworkSession.GameStarted += new EventHandler(GameStartedEvent); } catch (Exception e) { @@ -258,8 +255,6 @@ namespace CS_3505_Project_06 { mNetworkSession.StartGame(); mNetworkSession.ResetReady(); - - //Reset(); } @@ -296,6 +291,7 @@ namespace CS_3505_Project_06 if (IsLatencyAdjustmentFrame) { AdjustLatency(); + mLastStallCount = mStallCount; mStallCount = 0; } mLocalEvents.AddRange(GetEventsFromInput()); @@ -305,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) @@ -419,10 +431,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 { @@ -556,9 +573,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]; @@ -583,8 +602,10 @@ namespace CS_3505_Project_06 void Reset() { mLatency = 1; + mHighestFrameNumber = -1; mNextLatencyAdjustmentFrame = 1; mStallCount = 0; + mLastStallCount = 0; mAverageOwd = CurrentAverageOneWayDelay; mGamers = new Dictionary(); @@ -622,10 +643,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) { @@ -633,20 +654,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; @@ -656,7 +685,6 @@ namespace CS_3505_Project_06 byte[] stalledPeers = mPacketReader.ReadBytes(numStalledPeers); // TODO - break; default: @@ -668,9 +696,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) @@ -682,23 +715,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: @@ -724,7 +757,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); @@ -778,6 +811,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 @@ -811,6 +847,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(); @@ -829,13 +869,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(); @@ -843,26 +887,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; 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; 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. @@ -892,12 +936,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); } @@ -925,7 +972,7 @@ namespace CS_3505_Project_06 void ApplyEvents() { - int index = EventArrayIndex; + int index = CurrentEventArrayIndex; foreach (GamerInfo gamerInfo in GamerArray) { @@ -936,6 +983,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; } @@ -944,6 +992,7 @@ namespace CS_3505_Project_06 if (mouseButtonEventInfo != null) { mGame.ApplyMouseButtonInput(gamerInfo, mouseButtonEventInfo.IsButtonDown); + Console.WriteLine(mouseButtonEventInfo.FrameOfApplication + " BTN: " + mouseButtonEventInfo.IsButtonDown); continue; } @@ -951,6 +1000,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; } } @@ -975,7 +1025,7 @@ namespace CS_3505_Project_06 averageOwd += timeSpan.TotalMilliseconds; } - return (int)(averageOwd / numRemoteGamersTwice / 16.6666); + return (int)((averageOwd / numRemoteGamersTwice) / 16.6666); } } -- 2.43.0