// TODO: honour the timeoutInMilliseconds setting public bool TrySetActions(int playerIndex, TankAction tankAction1, TankAction tankAction2, ICommunicatorCallback callback, int timeoutInMilliseconds) { ChallengeClient client = new ChallengeClient(EndPointConfigurationName, Url); client.Open(); try { try { client.setActions(tankAction1.Convert(), tankAction2.Convert()); return(true); } catch (FaultException <EndOfGameException> endOfGameFault) { LogDebugError(endOfGameFault, endOfGameFault.Message); callback.UpdateGameOutcomeToLoseDueToError(playerIndex, endOfGameFault.Message); return(false); } catch (FaultException <NoBlameException> noBlameFault) { LogDebugError(noBlameFault, noBlameFault.Message); callback.UpdateGameOutcomeDueToNoBlameCrash(noBlameFault.Message); #if THROW_HARNESS_ERRORS throw; #else return(false); #endif } catch (EndpointNotFoundException endpointException) { LogDebugError(endpointException, endpointException.Message); callback.UpdateGameOutcomeDueToServerUnavailable(endpointException.Message); #if THROW_HARNESS_ERRORS throw; #else return(false); #endif } catch (CommunicationException commsException) { LogDebugError(commsException, commsException.Message); callback.UpdateGameOutcomeDueToServerUnavailable(commsException.Message); #if THROW_HARNESS_ERRORS throw; #else return(false); #endif } } finally { client.Close(); } }
public bool TryGetNewGameState(int playerIndex, int currentTickOnClient, ICommunicatorCallback callback) { ChallengeClient client = new ChallengeClient(EndPointConfigurationName, Url); client.Open(); try { try { callback.DoBeforeCheckingForANewState(); try { DateTime localTimeBeforeGetStatusCall = DateTime.Now; game wsGame = client.getStatus(); DateTime localTimeAfterGetStatusCall = DateTime.Now; int currentTick = wsGame.currentTick; if (currentTick == currentTickOnClient) { #if DEBUG // We don't want to lose important events. // Check that the harness only sends them when the current tick changes: if (wsGame.events != null) { if (wsGame.events.blockEvents != null && wsGame.events.blockEvents.Length > 0) { LogDebugMessage("RACE CONDITION! block events in the middle of a turn"); #if THROW_HARNESS_ERRORS throw new InvalidOperationException( "There are block events on a game object that is not the new game object"); #endif } if (wsGame.events.unitEvents != null && wsGame.events.unitEvents.Length > 0) { LogDebugMessage("RACE CONDITION! unit events in the middle of a turn"); #if THROW_HARNESS_ERRORS throw new InvalidOperationException( "There are unit events on a game object that is not the new game object"); #endif } } #endif return(false); } callback.DoBeforeUpdatingTheState(wsGame.currentTick, wsGame.nextTickTime, TimeSpan.FromMilliseconds(wsGame.millisecondsToNextTick), localTimeBeforeGetStatusCall, localTimeAfterGetStatusCall); bool stateUpdateCompletedSuccessfully = false; try { // Remove any walls that have been shot: List <Point> wallsRemovedAfterPreviousTick = new List <Point>(); List <Point> outOfBoundsBlocksAfterPreviousTick = new List <Point>(); events evts = wsGame.events; if (evts != null && evts.blockEvents != null) { foreach (blockEvent blockEv in evts.blockEvents) { if (blockEv.newStateSpecified) { switch (blockEv.newState) { case state.EMPTY: case state.NONE: Point wallPoint = blockEv.point.Convert(); wallsRemovedAfterPreviousTick.Add(wallPoint); break; #if DEBUG case state.OUT_OF_BOUNDS: outOfBoundsBlocksAfterPreviousTick.Add(blockEv.point.Convert()); break; case state.FULL: throw new InvalidOperationException( String.Format( "A 'FULL' block event was found at ({0}, {1}) contrary to expectation", blockEv.point.x, blockEv.point.y) ); break; #endif } } } } callback.UpdateWalls(wallsRemovedAfterPreviousTick, outOfBoundsBlocksAfterPreviousTick); // Update states of tanks and bullets which were destroyed: if (evts != null && evts.unitEvents != null) { foreach (unitEvent unitEv in evts.unitEvents) { unit u = unitEv.unit; if (u != null) { Point newPos = new Point((short)u.x, (short)u.y); TankAction tankAction = u.actionSpecified ? u.action.Convert() : TankAction.NONE; callback.UpdateTankState(u.id, tankAction, newPos, u.direction.Convert(), isActive: false); } bullet blt = unitEv.bullet; if (blt != null) { Point bulletPos = new Point((short)blt.x, (short)blt.y); callback.UpdateBulletState(blt.id, bulletPos, blt.direction.Convert(), isActive: false); } } } foreach (player plyr in wsGame.players) { if (plyr.units != null) { foreach (unit u in plyr.units) { if (u != null) { Point newPos = new Point((short)u.x, (short)u.y); TankAction tankAction = u.actionSpecified ? u.action.Convert() : TankAction.NONE; callback.UpdateTankState(u.id, tankAction, newPos, u.direction.Convert(), isActive: true); } } } if (plyr.bullets != null) { foreach (bullet blt in plyr.bullets) { Point bulletPos = new Point((short)blt.x, (short)blt.y); callback.UpdateBulletState(blt.id, bulletPos, blt.direction.Convert(), isActive: true); } } } stateUpdateCompletedSuccessfully = true; } finally { callback.DoAfterUpdatingTheState(stateUpdateCompletedSuccessfully); } return(true); } finally { callback.DoBeforeReturningFromCheckingForANewState(); } } catch (FaultException <EndOfGameException> endOfGameFault) { LogDebugError(endOfGameFault, endOfGameFault.Message); callback.UpdateGameOutcomeToLoseDueToError(playerIndex, endOfGameFault.Message); #if THROW_HARNESS_ERRORS throw; #else return(false); #endif } catch (FaultException <NoBlameException> noBlameFault) { LogDebugError(noBlameFault, noBlameFault.Message); callback.UpdateGameOutcomeDueToNoBlameCrash(noBlameFault.Message); #if THROW_HARNESS_ERRORS throw; #else return(false); #endif } catch (EndpointNotFoundException endpointException) { LogDebugError(endpointException, endpointException.Message); callback.UpdateGameOutcomeDueToServerUnavailable(endpointException.Message); #if THROW_HARNESS_ERRORS throw; #else return(false); #endif } catch (CommunicationException commsException) { LogDebugError(commsException, commsException.Message); callback.UpdateGameOutcomeDueToServerUnavailable(commsException.Message); #if THROW_HARNESS_ERRORS throw; #else return(false); #endif } } finally { client.Close(); } }