/// <summary> /// Set the lobby property /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public bool SetProperty(string key, string value) { propertiesList.Set(key, value); OnLobbyPropertyChange(key); return(true); }
protected virtual DictionaryOptions GenerateOptions() { var options = new DictionaryOptions(); options.Set(Msf.Args.Names.LobbyId, Id.ToString()); return(options); }
public override string ToString() { var options = new DictionaryOptions(Options); if (options.IsValueEmpty(MsfDictKeys.region)) { options.Set(MsfDictKeys.region, "International"); } return(options.ToReadableString() + " " + CustomOptions.ToReadableString()); }
/// <summary> /// Sends a request to master server, to spawn a process in a given region, and with given options /// </summary> /// <param name="options"></param> /// <param name="customOptions"></param> /// <param name="region"></param> /// <param name="callback"></param> public void RequestSpawn(DictionaryOptions options, DictionaryOptions customOptions, string region, ClientSpawnRequestCallback callback, IClientSocket connection) { // If we are not connected if (!connection.IsConnected) { callback?.Invoke(null, "Not connected"); return; } // Set region to room by filter. If region is empty the room will be international options.Set(MsfDictKeys.region, string.IsNullOrEmpty(region) ? string.Empty : region); // Create spawn request message packet var data = new ClientsSpawnRequestPacket() { // Options for spawners module Options = options, // Options that will be send to room CustomOptions = customOptions }; // Send request to Master Server SpawnerModule connection.SendMessage((short)MsfMessageCodes.ClientsSpawnRequest, data, (status, response) => { // If spawn request failed if (status != ResponseStatus.Success) { Logs.Error($"An error occurred when spawn request [{response.AsString()}]"); callback?.Invoke(null, response.AsString()); return; } // Create new spawn request controller var controller = new SpawnRequestController(response.AsInt(), connection, options); // List controler by spawn task id _localSpawnRequests[controller.SpawnTaskId] = controller; Logs.Debug($"Room was successfuly started with client options: {data.Options.ToReadableString()}, {data.CustomOptions.ToReadableString()}"); callback?.Invoke(controller, null); }); }
/// <summary> /// Default spawn spawned process request handler that will be used by controller if <see cref="spawnRequestHandler"/> is not overriden /// </summary> /// <param name="data"></param> /// <param name="message"></param> public virtual void SpawnRequestHandler(SpawnRequestPacket data, IIncommingMessage message) { Logger.Debug($"Default spawn handler started handling a request to spawn process for spawn controller [{SpawnerId}]"); /************************************************************************/ // Create process args string var processArguments = new DictionaryOptions(); /************************************************************************/ // Check if we're overriding an IP to master server var masterIpArgument = string.IsNullOrEmpty(SpawnSettings.MasterIp) ? Connection.ConnectionIp : SpawnSettings.MasterIp; // Create msater IP arg processArguments.Set(Msf.Args.Names.MasterIp, masterIpArgument); /************************************************************************/ /// Check if we're overriding a port to master server var masterPortArgument = SpawnSettings.MasterPort < 0 ? Connection.ConnectionPort : SpawnSettings.MasterPort; // Create master port arg processArguments.Set(Msf.Args.Names.MasterPort, masterPortArgument); /************************************************************************/ // Room Name processArguments.Set(Msf.Args.Names.RoomName, $"\"{data.Options.AsString(MsfDictKeys.roomName, "Room_" + Msf.Helper.CreateRandomString(6))}\""); /************************************************************************/ // Room Region processArguments.Set(Msf.Args.Names.RoomRegion, $"\"{SpawnSettings.Region}\""); /************************************************************************/ // Room Max Connections if (data.Options.Has(MsfDictKeys.maxPlayers)) { processArguments.Set(Msf.Args.Names.RoomMaxConnections, data.Options.AsString(MsfDictKeys.maxPlayers)); } /************************************************************************/ // Machine Ip processArguments.Set(Msf.Args.Names.RoomIp, SpawnSettings.MachineIp); /************************************************************************/ // Create port for room arg int machinePortArgument = Msf.Server.Spawners.GetAvailablePort(); processArguments.Set(Msf.Args.Names.RoomPort, machinePortArgument); /************************************************************************/ // Get the scene name if (data.Options.Has(MsfDictKeys.sceneName)) { processArguments.Set(Msf.Args.Names.LoadScene, data.Options.AsString(MsfDictKeys.sceneName)); } /************************************************************************/ // If spawn in batchmode was set and DontSpawnInBatchmode arg is not provided if (SpawnSettings.SpawnInBatchmode && !Msf.Args.DontSpawnInBatchmode) { processArguments.Set("-batchmode -nographics", string.Empty); } /************************************************************************/ // Create use websockets arg if (SpawnSettings.UseWebSockets) { processArguments.Set(Msf.Args.Names.UseWebSockets, string.Empty); } /************************************************************************/ // Create spawn id arg processArguments.Set(Msf.Args.Names.SpawnTaskId, data.SpawnTaskId); /************************************************************************/ // Create spawn code arg processArguments.Set(Msf.Args.Names.SpawnTaskUniqueCode, data.SpawnTaskUniqueCode); /************************************************************************/ // Create destroy ui arg if (Msf.Args.DestroyUi) { processArguments.Set(Msf.Args.Names.DestroyUi, string.Empty); } /************************************************************************/ // Create custom args processArguments.Append(data.CustomOptions); /************************************************************************/ // Path to executable var executablePath = SpawnSettings.ExecutablePath; if (string.IsNullOrEmpty(executablePath)) { executablePath = File.Exists(Environment.GetCommandLineArgs()[0]) ? Environment.GetCommandLineArgs()[0] : Process.GetCurrentProcess().MainModule.FileName; } // In case a path is provided with the request if (data.Options.Has(MsfDictKeys.executablePath)) { executablePath = data.Options.AsString(MsfDictKeys.executablePath); } if (!string.IsNullOrEmpty(data.OverrideExePath)) { executablePath = data.OverrideExePath; } /// Create info about starting process var startProcessInfo = new ProcessStartInfo(executablePath) { CreateNoWindow = false, UseShellExecute = false, Arguments = processArguments.ToReadableString(" ", " ") }; Logger.Debug("Starting process with args: " + startProcessInfo.Arguments); var processStarted = false; try { new Thread(() => { try { using (var process = Process.Start(startProcessInfo)) { Logger.Debug("Process started. Spawn Id: " + data.SpawnTaskId + ", pid: " + process.Id); processStarted = true; lock (processLock) { // Save the process processes[data.SpawnTaskId] = process; } var processId = process.Id; // Notify server that we've successfully handled the request MsfTimer.RunInMainThread(() => { message.Respond(ResponseStatus.Success); NotifyProcessStarted(data.SpawnTaskId, processId, startProcessInfo.Arguments); }); process.WaitForExit(); } } catch (Exception e) { if (!processStarted) { MsfTimer.RunInMainThread(() => { message.Respond(ResponseStatus.Failed); }); } Logger.Error("An exception was thrown while starting a process. Make sure that you have set a correct build path. " + $"We've tried to start a process at [{executablePath}]. You can change it at 'SpawnerBehaviour' component"); Logger.Error(e); } finally { lock (processLock) { // Remove the process processes.Remove(data.SpawnTaskId); } MsfTimer.RunInMainThread(() => { // Release the port number Msf.Server.Spawners.ReleasePort(machinePortArgument); Logger.Debug($"Notifying about killed process with spawn id [{data.SpawnTaskId}]"); NotifyProcessKilled(data.SpawnTaskId); }); } }).Start(); } catch (Exception e) { message.Respond(e.Message, ResponseStatus.Error); Logs.Error(e); } }