public override void LookUp(ServerAction action) { // default degree increment to 30 if (action.degrees == 0) { action.degrees = 30f; } else { errorMessage = "Must have degrees == 0 for now."; actionFinished(false); return; } // force the degree increment to the nearest tenths place // this is to prevent too small of a degree increment change that could cause float imprecision action.degrees = Mathf.Round(action.degrees * 10.0f) / 10.0f; if (!checkForUpDownAngleLimit("up", action.degrees)) { errorMessage = "can't look up beyond " + maxUpwardLookAngle + " degrees above the forward horizon"; errorCode = ServerActionErrorCode.LookDownCantExceedMin; actionFinished(false); return; } base.LookUp(action); }
protected void ProcessControlCommand(string msg) { Debug.Log("Procssing control commands: " + msg); errorMessage = ""; collisionsInAction = new List <string> (); ServerAction controlCommand = JsonUtility.FromJson <ServerAction>(msg); this.currentSequenceId = controlCommand.sequenceId; lastAction = controlCommand.action; lastActionSuccess = false; lastPosition = new Vector3(transform.position.x, transform.position.y, transform.position.z); Debug.Log("sending message: " + this.name); System.Reflection.MethodInfo method = this.GetType().GetMethod(controlCommand.action); try { method.Invoke(this, new object[] { controlCommand }); } catch (Exception e) { Debug.LogError("caught error with invoke"); Debug.LogError(e); errorMessage += e.ToString(); actionFinished(false); } }
private void btnSave_Click(object sender, EventArgs e) { if (Credential.IsEmailValid(tbEmail.Text) && !DbAction.IsUsernameInDatabase(tbEmail.Text) && !ServerAction.IsUsernameInServer(tbEmail.Text)) { try { var serverSidePass = cbBackUpPassword.Checked ? tbPassword.Text : string.Empty; if (ServerAction.RegisterNewUser(tbEmail.Text, serverSidePass)) { DbAction.AddNewUser(tbEmail.Text, Crypto.MakeHash(tbPassword.Text)); Close(); } else { lblInvalidRegistration.Text = "Could not Register user. Please try again"; lblInvalidRegistration.Visible = true; } } catch (Exception ex) { lblInvalidRegistration.Text = ex.Message; } } else { lblInvalidRegistration.Visible = true; } }
private void btnSave_Click(object sender, EventArgs e) { if (tbNewPassword.Text == tbNewPassword2.Text) { try { if (Crypto.CompareHash(tbOldPassword.Text, DbAction.GetPasswordByUser(credentials.email))) { var serverSidePass = cbBackUpPassword.Checked ? tbNewPassword2.Text : string.Empty; var hushPuppy = Crypto.MakeHash(tbNewPassword2.Text); ServerAction.ChangePassword(credentials.email, tbOldPassword.Text, serverSidePass); DbAction.ChangePassword(credentials.email, hushPuppy); credentials.password = hushPuppy; Close(); } else { throw new Internals.UnauthorizedAccessException("Wrong Username/Password"); } } catch (Exception ex) { lblError.Text = ex.Message; lblError.Visible = true; } } else { lblError.Text = "Passwords don't match"; lblError.Visible = true; } }
public void PutObject(ServerAction response) { bool success = false; if (inventory.ContainsKey(response.objectId)) { foreach (SimObj rso in VisibleSimObjs(response.forceVisible)) { if (rso.IsReceptacle && (rso.UniqueID == response.receptacleObjectId || rso.Type == response.ReceptableSimObjType())) { SimObj so = removeObjectInventory(response.objectId); if ((!IsOpenable(rso) || IsOpen(rso)) && ((response.forceVisible && SimUtil.AddItemToReceptacle(so, rso.Receptacle)) || SimUtil.AddItemToVisibleReceptacle(so, rso.Receptacle, m_Camera))) { success = true; } else { addObjectInventory(so); } break; } } } actionFinished(success); }
public void Initialize(ServerAction action) { this.gridSize = action.gridSize; Debug.Log("grid size " + this.gridSize); Debug.Log("openable types" + OpenableTypes.Length); StartCoroutine(checkInitializeAgentLocationAction()); }
public void PickupHandObject(ServerAction action) { GameObject hand = getHand(); bool success = false; foreach (SimObj so in VisibleSimObjs(action)) { // XXX CHECK IF OPEN if (!so.IsReceptacle && !IsOpenable(so)) { if (inventory.Count == 0) { addObjectInventory(so); currentHandSimObj = so; Rigidbody rb = so.GetComponentInChildren(typeof(Rigidbody)) as Rigidbody; rb.freezeRotation = true; rb.constraints = RigidbodyConstraints.FreezeAll; rb.useGravity = false; so.transform.position = hand.transform.position; // so.transform.parent = this.transform; // so.transform.parent = m_CharacterController.transform; so.transform.parent = hand.transform; so.ResetScale(); so.transform.localPosition = new Vector3(); so.hasCollision = false; success = true; } break; } } actionFinished(success); }
public override void RotateLeft(ServerAction action) { Rotate(new ServerAction() { rotation = new Vector3(0, -1.0f * this.rotateStepDegrees, 0) }); }
public void Initialize(ServerAction action) { if (action.agentType != null && action.agentType.ToLower() == "stochastic") { this.agents.Clear(); // stochastic must have these set to work properly action.continuous = true; action.snapToGrid = false; GameObject fpsController = GameObject.FindObjectOfType <BaseFPSAgentController>().gameObject; primaryAgent.enabled = false; primaryAgent = fpsController.GetComponent <StochasticRemoteFPSAgentController>(); primaryAgent.agentManager = this; primaryAgent.enabled = true; // must manually call start here since it this only gets called before Update() is called primaryAgent.Start(); this.agents.Add(primaryAgent); } primaryAgent.ProcessControlCommand(action); primaryAgent.IsVisible = action.makeAgentsVisible; this.renderClassImage = action.renderClassImage; this.renderDepthImage = action.renderDepthImage; this.renderNormalsImage = action.renderNormalsImage; this.renderObjectImage = action.renderObjectImage; this.renderFlowImage = action.renderFlowImage; if (action.alwaysReturnVisibleRange) { ((PhysicsRemoteFPSAgentController)primaryAgent).alwaysReturnVisibleRange = action.alwaysReturnVisibleRange; } StartCoroutine(addAgents(action)); }
protected float GetMoveMagnitudeWithNoise(ServerAction action) { System.Random random = new System.Random(); float internalNoise = applyActionNoise ? (float)random.NextGaussian(movementGaussianMu, movementGaussianSigma) : 0; return(action.moveMagnitude + action.noise + (float)internalNoise); }
//Flying Drone Agent Controls public void FlyDown(ServerAction action) { //Vector3 targetPosition = transform.position + -transform.up * action.moveMagnitude; //transform.position = targetPosition; thrust += new Vector3(0, -action.moveMagnitude, 0); actionFinished(true); }
// currently not finished action. New logic needs to account for the // hierarchy of rigidbodies of each arm joint and how to detect collision // between a given arm joint an other arm joints. public void RotateMidLevelHand(ServerAction action) { IK_Robot_Arm_Controller arm = getArm(); Quaternion target = new Quaternion(); // rotate around axis aliged x, y, z with magnitude based on vector3 if (action.degrees == 0) { // use euler angles target = Quaternion.Euler(action.rotation); } else { // rotate action.degrees about axis target = Quaternion.AngleAxis(action.degrees, action.rotation); } arm.rotateHand( controller: this, targetQuat: target, degreesPerSecond: action.speed, disableRendering: action.disableRendering, fixedDeltaTime: action.fixedDeltaTime.GetValueOrDefault(Time.fixedDeltaTime), returnToStartPositionIfFailed: action.returnToStart ); }
//Flying Drone Agent Controls public Vector3 GetFlyingOrientation(ServerAction action, int targetOrientation) { Vector3 m; int currentRotation = (int)Math.Round(transform.rotation.eulerAngles.y, 0); Dictionary <int, Vector3> actionOrientation = new Dictionary <int, Vector3>(); actionOrientation.Add(0, new Vector3(0f, 0f, 1.0f)); actionOrientation.Add(90, new Vector3(1.0f, 0.0f, 0.0f)); actionOrientation.Add(180, new Vector3(0f, 0f, -1.0f)); actionOrientation.Add(270, new Vector3(-1.0f, 0.0f, 0.0f)); int delta = (currentRotation + targetOrientation) % 360; if (actionOrientation.ContainsKey(delta)) { m = actionOrientation[delta]; } else { actionOrientation = new Dictionary <int, Vector3>(); actionOrientation.Add(0, transform.forward); actionOrientation.Add(90, transform.right); actionOrientation.Add(180, transform.forward * -1); actionOrientation.Add(270, transform.right * -1); m = actionOrientation[targetOrientation]; } m *= action.moveMagnitude; return(m); }
//Flying Drone Agent Controls public void FlyTo(ServerAction action) { transform.rotation = Quaternion.Euler(new Vector3(0.0f, action.rotation.y, 0.0f)); m_Camera.transform.localEulerAngles = new Vector3(action.horizon, 0.0f, 0.0f); thrust += new Vector3(action.x, action.y, action.z); actionFinished(true); }
public void AddThirdPartyCamera(ServerAction action) { GameObject gameObject = new GameObject("ThirdPartyCamera" + thirdPartyCameras.Count); gameObject.AddComponent(typeof(Camera)); Camera camera = gameObject.GetComponentInChildren <Camera>(); if (this.renderDepthImage || this.renderClassImage || this.renderObjectImage || this.renderNormalsImage || this.renderFlowImage) { gameObject.AddComponent(typeof(ImageSynthesis)); } this.thirdPartyCameras.Add(camera); gameObject.transform.eulerAngles = action.rotation; gameObject.transform.position = action.position; float fov; if (action.fieldOfView <= 0 || action.fieldOfView > 180) { //default to 90 fov on third party camera if nothing passed in, or if value is too large fov = 90f; } else { fov = action.fieldOfView; } camera.fieldOfView = fov; readyToEmit = true; }
private static string FormatContent(ServerAction serverAction, object[] args) { Func<object[], string> formatter; if (!Formatters.TryGetValue(serverAction, out formatter)) formatter = DefaultFormat; return formatter(args); }
private void ProcessControlCommand(string msg) { ServerAction controlCommand = new ServerAction(); JsonUtility.FromJsonOverwrite(msg, controlCommand); this.currentSequenceId = controlCommand.sequenceId; this.renderImage = controlCommand.renderImage; activeAgentId = controlCommand.agentId; if (controlCommand.action == "Reset") { this.Reset(controlCommand); } else if (controlCommand.action == "Initialize") { this.Initialize(controlCommand); } else if (controlCommand.action == "AddThirdPartyCamera") { this.AddThirdPartyCamera(controlCommand); } else if (controlCommand.action == "UpdateThirdPartyCamera") { this.UpdateThirdPartyCamera(controlCommand); } else { this.activeAgent().ProcessControlCommand(controlCommand); readyToEmit = true; } }
private void moveCharacterGrid(ServerAction action, int targetOrientation) { moveMagnitude = action.moveMagnitude; int currentRotation = (int)Math.Round(transform.rotation.eulerAngles.y, 0); Dictionary <int, Vector3> actionOrientation = new Dictionary <int, Vector3> (); actionOrientation.Add(0, new Vector3(0f, 0f, 1.0f * moveMagnitude)); actionOrientation.Add(90, new Vector3(1.0f * moveMagnitude, 0.0f, 0.0f)); actionOrientation.Add(180, new Vector3(0f, 0f, -1.0f * moveMagnitude)); actionOrientation.Add(270, new Vector3(-1.0f * moveMagnitude, 0.0f, 0.0f)); int delta = (currentRotation + targetOrientation) % 360; GridPoint[] gridPoints = sceneConfig.gridPoints; Vector3 currentPoint = nearestGridPoint(gridPoints, transform.position); targetTeleport = nearestGridPoint(gridPoints, (new Vector3(currentPoint.x, currentPoint.y, currentPoint.z)) + actionOrientation [delta]); //we don't move the agent if it is to a point that moves agent upwards if (targetTeleport == new Vector3() || targetTeleport.y > 1.35) { lastActionSuccess = false; } else { m_CharacterController.transform.position = targetTeleport; } }
private Task ServerActionHandler(ServerAction serverAction) { Log.Information("Client: Receive server action request {ServerAction} ", serverAction); switch (serverAction) { case ServerAction.Removed: Log.Information("Client: Daemon has been removed from the api"); _hostApplicationLifetime.StopApplication(); break; case ServerAction.Reconnect: case ServerAction.Authentication: Log.Information("Client: The daemon will reconnect"); Dispose(); RestartAuthentication(); break; case ServerAction.Logout: Log.Information("Client: The daemon receive logout request"); _hostApplicationLifetime.StopApplication(); break; } return(Task.CompletedTask); }
private float GetMoveMagnitudeWithNoise(ServerAction action) { var random = new System.Random(); var noise = applyActionNoise ? random.NextGaussian(movementGaussianMu, movementGaussianSigma) : 0; return(action.moveMagnitude + action.noise + (float)noise); }
public override void MoveBack(ServerAction action) { action.x = 0.0f; action.y = 0; action.z = -1.0f; MoveRelative(action); }
public new void Initialize(ServerAction action) { this.applyActionNoise = action.applyActionNoise; if (action.movementGaussianMu > 0.0f) { this.movementGaussianMu = action.movementGaussianMu; } if (action.movementGaussianSigma > 0.0f) { this.movementGaussianSigma = action.movementGaussianSigma; } if (action.rotateGaussianMu > 0.0f) { this.rotateGaussianMu = action.rotateGaussianMu; } if (action.rotateGaussianSigma > 0.0f) { this.rotateGaussianSigma = action.rotateGaussianSigma; } #if UNITY_EDITOR Debug.Log("MoveNoise: " + movementGaussianMu + " mu, " + movementGaussianSigma + " sigma"); Debug.Log("RotateNoise: " + rotateGaussianMu + " mu, " + rotateGaussianSigma + " sigma"); Debug.Log("applynoise:" + applyActionNoise); #endif base.Initialize(action); }
public override void MoveAhead(ServerAction action) { action.x = 0.0f; action.y = 0; action.z = 1.0f; MoveRelative(action); }
/// <remarks> /// The <see cref="DaemonConfigOptions"/> options are added to every command. /// A non-mandatory string option "name" is added as well, which drop operation /// commands may want to use to explicitly specify the target drop name. /// </remarks> private static Command RegisterCommand( string name, IEnumerable <Option> options = null, ServerAction serverAction = null, ClientAction clientAction = null, string description = null, bool needsIpcClient = true, bool addDaemonConfigOptions = true) { var opts = (options ?? new Option[0]).ToList(); if (addDaemonConfigOptions) { opts.AddRange(DaemonConfigOptions); } if (!opts.Exists(opt => opt.LongName == "name")) { opts.Add(new Option(longName: DropName.LongName) { ShortName = DropName.ShortName, }); } var cmd = new Command(name, opts, serverAction, clientAction, description, needsIpcClient); Commands[cmd.Name] = cmd; return(cmd); }
//reset visible objects while in editor, for debug purposes only private void LateUpdate() { #if UNITY_EDITOR || UNITY_WEBGL ServerAction action = new ServerAction(); VisibleSimObjPhysics = VisibleSimObjs(action); #endif }
public void UpdateServerStatus() { Random random = new Random(); var servers = client.Servers.Get(); ServerAction newState = ServerAction.REBOOT; var server = servers[random.Next(servers.Count - 1)]; foreach (var item in servers) { if (item.Status.State == ServerState.POWERED_ON || item.Status.State == ServerState.POWERED_OFF) { server = item; break; } } if (server.Status.State == ServerState.POWERED_OFF) { newState = ServerAction.POWER_ON; } var result = client.Servers.UpdateStatus(new UpdateStatusRequest() { Action = newState, Method = ServerActionMethod.SOFTWARE }, server.Id); Assert.IsNotNull(result); Assert.IsNotNull(result.Status); //check server state is either rebooting or powering on Assert.AreEqual(result.Status.State, newState == ServerAction.REBOOT ? ServerState.REBOOTING : ServerState.POWERING_ON); }
public void Step(string serverAction) { ServerAction controlCommand = new ServerAction(); JsonUtility.FromJsonOverwrite(serverAction, controlCommand); PhysicsController.ProcessControlCommand(controlCommand); }
public static void RunForDiffElements(string[] args) { var oldESpacePath = args[1]; var newESpacePath = args[2]; if (!File.Exists(oldESpacePath)) { Console.WriteLine($"File {oldESpacePath} not found"); return; } if (!File.Exists(newESpacePath)) { Console.WriteLine($"File {newESpacePath} not found"); return; } var saveESpacePath = new FileInfo(args[3]); var outputDirectory = saveESpacePath.Directory.FullName; if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); } var modelServices = OutSystems.ModelAPILoader.Loader.ModelServicesInstance; var oldmodule = modelServices.LoadESpace(oldESpacePath); var newmodule = modelServices.LoadESpace(newESpacePath); var isoldtraditional = IsTraditional(oldmodule); var isnewtraditional = IsTraditional(newmodule); if (isoldtraditional != isnewtraditional) { Console.WriteLine("<oldFile.oml> and <newFile.oml> are not compatible"); return; } if (isoldtraditional) { BlocksTraditional tradicionalBlocks = new BlocksTraditional(); Screens s = new Screens(); ServerAction l = new ServerAction(); tradicionalBlocks.GetDiffElements(oldmodule, newmodule, "new"); s.GetDiffElements(oldmodule, newmodule, "new"); l.GetDiffElements(oldmodule, newmodule, "new"); } else { BlocksReative reactiveBlocks = new BlocksReative(); ScreensNR s = new ScreensNR(); ServerAction l = new ServerAction(); reactiveBlocks.GetDiffElements(oldmodule, newmodule, "new"); s.GetDiffElements(oldmodule, newmodule, "new"); l.GetDiffElements(oldmodule, newmodule, "new"); } newmodule.Save(saveESpacePath.FullName); Console.WriteLine($"\nESpace saved to {saveESpacePath.FullName}"); }
public void ProcessControlCommand(ServerAction controlCommand) { errorMessage = ""; errorCode = ServerActionErrorCode.Undefined; collisionsInAction = new List <string>(); lastAction = controlCommand.action; lastActionSuccess = false; lastPosition = new Vector3(transform.position.x, transform.position.y, transform.position.z); System.Reflection.MethodInfo method = this.GetType().GetMethod(controlCommand.action); this.actionComplete = false; try { if (method == null) { errorMessage = "Invalid action: " + controlCommand.action; errorCode = ServerActionErrorCode.InvalidAction; Debug.LogError(errorMessage); actionFinished(false); } else { method.Invoke(this, new object[] { controlCommand }); } } catch (Exception e) { Debug.LogError("caught error with invoke"); Debug.LogError(e); errorMessage += e.ToString(); actionFinished(false); } }
private float GetRotateMagnitudeWithNoise(ServerAction action) { var random = new System.Random(); var noise = applyActionNoise ? random.NextGaussian(rotateGaussianMu, rotateGaussianSigma) : 0; return(action.rotation.y + action.noise + (float)noise); }
public Server(string filename) { _servers = new List<ServerMetadata>(); ReadConfigurationFile(filename); action = new ServerAction(this._username); lookup = new ServerLookup(this._username, action, _servers); facade = new ServerFacade(this._username, _port, action, lookup, _servers); }
private TaskMessage(RemoteTask task, ServerAction serverAction, params object[] parameters) { Assert.NotNull(task); Task = task; ServerAction = serverAction; Message = ServerMessage.Format(serverAction, parameters); }
private TaskMessage(RemoteTask task, ServerAction serverAction, params object[] parameters) { Assert.NotNull(task); Task = task; ServerAction = serverAction; Message = ServerMessage.Format(serverAction, parameters); }
public ServerFacade(string username, int port, ServerAction action, ServerLookup lookup, List<ServerMetadata> _servers) { this._username = username; this.action = action; this.lookup = lookup; this._port = port; this._servers = _servers; _isOnline = true; }
public Server(string username, int port, string path, string configFile) { _username = username; _port = port; _path = path; _configFile = _path + configFile; _servers = new List<ServerMetadata>(); ReadConfigurationFile(); action = new ServerAction(_username); lookup = new ServerLookup(this._username, action, _servers); facade = new ServerFacade(this._username, _port, action, lookup, _servers); }
public void Run(string[] args) { FileSystemWatcher watcher = null; bool showList = false; Utils.Write("^AToxikkServerLauncher " + Version + "^7\nhttps://github.com/ToxikkModdingTeam/ToxikkServerLauncher\n"); if (!LoadMyServerConfigIni()) return; // setup interactive mode when no server IDs were specified on the command line var commands = args.ToList(); if (commands.Count == 0) { watcher = MonitorChangesToMyServerConfigIni(); reloadTimer.AutoReset = false; reloadTimer.Elapsed += ReloadMyServerConfigIni; interactive = true; showList = true; } AddAutoExecCommandsFromConfig(commands); do { action = ServerAction.Start; if (interactive) { if (showList) { ListConfigurations(); showList = false; } ShowInteractivePrompt(); commands = (Console.ReadLine() ?? "").Split(' ').ToList(); if (commands.Count == 1 && commands[0] == "") continue; } launcher.FindRunningServers(); foreach (var cmdOrId in commands) ProcessCommand(cmdOrId); } while (interactive); watcher?.Dispose(); }
public void AssertSingleMessage(ServerAction expectedServerAction, params object[] parameters) { var expectedServerMessage = ServerMessage.Format(expectedServerAction, parameters); Assert(() => Xunit.Assert.Single(messages, expectedServerMessage)); }
public static string Format(ServerAction serverAction, params object[] values) { var content = FormatContent(serverAction, values); return string.Format("{0}{1}{2}", serverAction, string.IsNullOrEmpty(content) ? "" : ": ", content); }
public ServerLookup(string username, ServerAction action, List<ServerMetadata> _servers) { this._username = username; this.action = action; this._servers = _servers; _sequenceNumber = 0; }
private void ProcessCommand(string cmdOrId) { int id; if (cmdOrId.StartsWith("-")) cmdOrId = cmdOrId.Substring(1); if (int.TryParse(cmdOrId, out id)) { var secName = id == 0 ? "Client" : Launcher.ServerSectionPrefix + cmdOrId; if (launcher.MainIni.GetSection(secName) == null) { Utils.WriteLine($"^CERROR:^7 No configuration with ID {cmdOrId}"); return; } if (action == ServerAction.Start) { bool redeploy = workshop.UpdateWorkshop(false, true, true); if (redeploy || (DateTime.Now - lastWorkshopDeployment).TotalMinutes >= WorkshopRedeployMinutes) { workshop.DeployWorkshopItems(); lastWorkshopDeployment = DateTime.Now; } launcher.StartServer(cmdOrId); } else if (action == ServerAction.Generate) launcher.GenerateConfig(id); else if (action == ServerAction.Restart) launcher.RestartServer(cmdOrId, workshop); else if (action == ServerAction.Stop) launcher.StopServer(cmdOrId); else if (action == ServerAction.Focus) launcher.FocusServerConsole(cmdOrId); } else if (cmdOrId == "h" || cmdOrId == "?" || cmdOrId == "help") ShowHelp(); else if (cmdOrId == "l" || cmdOrId == "list") ListConfigurations(); else if (cmdOrId == "g" || cmdOrId == "generate") action = ServerAction.Generate; else if (cmdOrId == "s" || cmdOrId == "start") action = ServerAction.Start; else if (cmdOrId == "r" || cmdOrId == "restart") action = ServerAction.Restart; else if (cmdOrId == "x" || cmdOrId == "stop") action = ServerAction.Stop; else if (cmdOrId == "f" || cmdOrId == "focus") action = ServerAction.Focus; else if (cmdOrId == "ut" || cmdOrId == "updatetoxikk") workshop.UpdateToxikk(true); else if (cmdOrId == "cw" || cmdOrId == "cleanworkshop") workshop.CleanWorkshopFolder(); else if (cmdOrId == "uw" || cmdOrId == "updateworkshop") { if (workshop.UpdateWorkshop(true, true, true)) lastWorkshopDeployment = DateTime.MinValue; } else if (cmdOrId == "us") { if (workshop.UpdateWorkshop(true, true, false)) lastWorkshopDeployment = DateTime.MinValue; } else if (cmdOrId == "uz") { if (workshop.UpdateWorkshop(true, false, true)) lastWorkshopDeployment = DateTime.MinValue; } else if (cmdOrId == "sw" || cmdOrId == "syncworkshop") { workshop.DeployWorkshopItems(); lastWorkshopDeployment = DateTime.Now; } else if (cmdOrId == "quit" || cmdOrId == "exit") interactive = false; else ProcessSwitch(cmdOrId); }
public void AssertSingleAction(ServerAction expectedServerAction) { Assert(() => Xunit.Assert.Single(serverActions, expectedServerAction)); }
public void AssertNoAction(ServerAction expectedServerAction) { Assert(() => Xunit.Assert.DoesNotContain(expectedServerAction, serverActions)); }