Clients can execute permitted console commands server-side now. The console commands have three different actions: the default action, one that's executed client-side when a client uses it, and one that's executed server-side when a clients requests it. If the client-side action is omitted, the client relays the command to the server as-is. If the third action is omitted, the server executes the default action.
This commit is contained in:
@@ -105,7 +105,7 @@ namespace Barotrauma
|
||||
|
||||
if (PlayerInput.KeyHit(Keys.Enter))
|
||||
{
|
||||
ExecuteCommand(textBox.Text, game);
|
||||
ExecuteCommand(textBox.Text);
|
||||
textBox.Text = "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -608,15 +608,17 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
if (newPermissions != permissions)
|
||||
{
|
||||
SetPermissions(newPermissions, permittedConsoleCommands);
|
||||
}
|
||||
SetPermissions(newPermissions, permittedConsoleCommands);
|
||||
}
|
||||
|
||||
private void SetPermissions(ClientPermissions newPermissions, List<string> permittedConsoleCommands)
|
||||
{
|
||||
if (newPermissions == permissions) return;
|
||||
if (!(this.permittedConsoleCommands.Any(c => !permittedConsoleCommands.Contains(c)) ||
|
||||
permittedConsoleCommands.Any(c => !this.permittedConsoleCommands.Contains(c))))
|
||||
{
|
||||
if (newPermissions == permissions) return;
|
||||
}
|
||||
|
||||
GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData as string == "permissions");
|
||||
|
||||
string msg = "";
|
||||
@@ -637,7 +639,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
//TODO: display permitted console commands
|
||||
}
|
||||
|
||||
permissions = newPermissions;
|
||||
this.permittedConsoleCommands = new List<string>(permittedConsoleCommands);
|
||||
new GUIMessageBox("Permissions changed", msg).UserData = "permissions";
|
||||
|
||||
GameMain.NetLobbyScreen.SubList.Enabled = Voting.AllowSubVoting || HasPermission(ClientPermissions.SelectSub);
|
||||
@@ -1384,6 +1388,9 @@ namespace Barotrauma.Networking
|
||||
msg.Write((byte)ClientPacketHeader.SERVER_COMMAND);
|
||||
msg.Write((byte)ClientPermissions.ConsoleCommands);
|
||||
msg.Write(command);
|
||||
Vector2 cursorWorldPos = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
msg.Write(cursorWorldPos.X);
|
||||
msg.Write(cursorWorldPos.Y);
|
||||
|
||||
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Barotrauma
|
||||
{
|
||||
while (QueuedCommands.Count>0)
|
||||
{
|
||||
ExecuteCommand(QueuedCommands[0], GameMain.Instance);
|
||||
ExecuteCommand(QueuedCommands[0]);
|
||||
QueuedCommands.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,22 +31,73 @@ namespace Barotrauma
|
||||
{
|
||||
public readonly string[] names;
|
||||
public readonly string help;
|
||||
|
||||
private Action<string[]> onExecute;
|
||||
|
||||
private bool relayToServer;
|
||||
/// <summary>
|
||||
/// Executed when a client uses the command. If not set, the command is relayed to the server as-is.
|
||||
/// </summary>
|
||||
private Action<string[]> onClientExecute;
|
||||
|
||||
/// <summary>
|
||||
/// Executed server-side when a client attempts to use the command.
|
||||
/// </summary>
|
||||
private Action<Client, Vector2, string[]> onClientRequestExecute;
|
||||
|
||||
public bool RelayToServer
|
||||
{
|
||||
get { return onClientExecute == null; }
|
||||
}
|
||||
|
||||
/// <param name="name">The name of the command. Use | to give multiple names/aliases to the command.</param>
|
||||
/// <param name="help">The text displayed when using the help command.</param>
|
||||
/// <param name="onExecute">The default action when executing the command.</param>
|
||||
/// <param name="onClientExecute">The action when a client attempts to execute the command. If null, the command is relayed to the server as-is.</param>
|
||||
/// <param name="onClientRequestExecute">The server-side action when a client requests executing the command. If null, the default action is executed.</param>
|
||||
public Command(string name, string help, Action<string[]> onExecute, Action<string[]> onClientExecute, Action<Client, Vector2, string[]> onClientRequestExecute)
|
||||
{
|
||||
names = name.Split('|');
|
||||
this.help = help;
|
||||
|
||||
this.onExecute = onExecute;
|
||||
this.onClientExecute = onClientExecute;
|
||||
this.onClientRequestExecute = onClientRequestExecute;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Use this constructor to create a command that executes the same action regardless of whether it's executed by a client or the server.
|
||||
/// </summary>
|
||||
public Command(string name, string help, Action<string[]> onExecute)
|
||||
{
|
||||
names = name.Split('|');
|
||||
this.help = help;
|
||||
|
||||
this.onExecute = onExecute;
|
||||
this.onClientExecute = onExecute;
|
||||
}
|
||||
|
||||
|
||||
public void Execute(string[] args)
|
||||
{
|
||||
onExecute(args);
|
||||
}
|
||||
|
||||
public void ClientExecute(string[] args)
|
||||
{
|
||||
onClientExecute(args);
|
||||
}
|
||||
|
||||
public void ServerExecuteOnClientRequest(Client client, Vector2 cursorWorldPos, string[] args)
|
||||
{
|
||||
if (onClientRequestExecute == null)
|
||||
{
|
||||
onExecute(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
onClientRequestExecute(client, cursorWorldPos, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int MaxMessages = 200;
|
||||
@@ -102,6 +153,15 @@ namespace Barotrauma
|
||||
NewMessage("- " + c.ID.ToString() + ": " + c.Name + ", " + c.Connection.RemoteEndPoint.Address.ToString(), Color.Cyan);
|
||||
}
|
||||
NewMessage("***************", Color.Cyan);
|
||||
}, null,
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
GameMain.Server.SendChatMessage("***************", client);
|
||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
GameMain.Server.SendChatMessage("- " + c.ID.ToString() + ": " + c.Name + ", " + c.Connection.RemoteEndPoint.Address.ToString(), client);
|
||||
}
|
||||
GameMain.Server.SendChatMessage("***************", client);
|
||||
}));
|
||||
|
||||
|
||||
@@ -112,145 +172,42 @@ namespace Barotrauma
|
||||
|
||||
commands.Add(new Command("spawn|spawncharacter", "spawn [creaturename] [near/inside/outside]: Spawn a creature at a random spawnpoint (use the second parameter to only select spawnpoints near/inside/outside the submarine).", (string[] args) =>
|
||||
{
|
||||
if (args.Length == 0) return;
|
||||
|
||||
Character spawnedCharacter = null;
|
||||
|
||||
Vector2 spawnPosition = Vector2.Zero;
|
||||
WayPoint spawnPoint = null;
|
||||
|
||||
if (args.Length > 1)
|
||||
string errorMsg;
|
||||
SpawnCharacter(args, GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), out errorMsg);
|
||||
if (!string.IsNullOrWhiteSpace(errorMsg))
|
||||
{
|
||||
switch (args[1].ToLowerInvariant())
|
||||
{
|
||||
case "inside":
|
||||
spawnPoint = WayPoint.GetRandom(SpawnType.Human, null, Submarine.MainSub);
|
||||
break;
|
||||
case "outside":
|
||||
spawnPoint = WayPoint.GetRandom(SpawnType.Enemy);
|
||||
break;
|
||||
case "near":
|
||||
case "close":
|
||||
float closestDist = -1.0f;
|
||||
foreach (WayPoint wp in WayPoint.WayPointList)
|
||||
{
|
||||
if (wp.Submarine != null) continue;
|
||||
|
||||
//don't spawn inside hulls
|
||||
if (Hull.FindHull(wp.WorldPosition, null) != null) continue;
|
||||
|
||||
float dist = Vector2.Distance(wp.WorldPosition, GameMain.GameScreen.Cam.WorldViewCenter);
|
||||
|
||||
if (closestDist < 0.0f || dist < closestDist)
|
||||
{
|
||||
spawnPoint = wp;
|
||||
closestDist = dist;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "cursor":
|
||||
spawnPosition = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
break;
|
||||
default:
|
||||
spawnPoint = WayPoint.GetRandom(args[0].ToLowerInvariant() == "human" ? SpawnType.Human : SpawnType.Enemy);
|
||||
break;
|
||||
}
|
||||
ThrowError(errorMsg);
|
||||
}
|
||||
else
|
||||
},
|
||||
null,
|
||||
(Client client, Vector2 cursorPos, string[] args) =>
|
||||
{
|
||||
string errorMsg;
|
||||
SpawnCharacter(args, cursorPos, out errorMsg);
|
||||
if (!string.IsNullOrWhiteSpace(errorMsg))
|
||||
{
|
||||
spawnPoint = WayPoint.GetRandom(args[0].ToLowerInvariant() == "human" ? SpawnType.Human : SpawnType.Enemy);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(args[0])) return;
|
||||
|
||||
if (spawnPoint != null) spawnPosition = spawnPoint.WorldPosition;
|
||||
|
||||
if (args[0].ToLowerInvariant() == "human")
|
||||
{
|
||||
spawnedCharacter = Character.Create(Character.HumanConfigFile, spawnPosition);
|
||||
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession != null)
|
||||
{
|
||||
SinglePlayerCampaign mode = GameMain.GameSession.GameMode as SinglePlayerCampaign;
|
||||
if (mode != null)
|
||||
{
|
||||
Character.Controlled = spawnedCharacter;
|
||||
GameMain.GameSession.CrewManager.AddCharacter(Character.Controlled);
|
||||
GameMain.GameSession.CrewManager.SelectCharacter(null, Character.Controlled);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
List<string> characterFiles = GameMain.Config.SelectedContentPackage.GetFilesOfType(ContentType.Character);
|
||||
|
||||
foreach (string characterFile in characterFiles)
|
||||
{
|
||||
if (Path.GetFileNameWithoutExtension(characterFile).ToLowerInvariant() == args[0].ToLowerInvariant())
|
||||
{
|
||||
Character.Create(characterFile, spawnPosition);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ThrowError("No character matching the name \"" + args[0] + "\" found in the selected content package.");
|
||||
|
||||
//attempt to open the config from the default path (the file may still be present even if it isn't included in the content package)
|
||||
string configPath = "Content/Characters/"
|
||||
+ args[0].First().ToString().ToUpper() + args[0].Substring(1)
|
||||
+ "/" + args[0].ToLower() + ".xml";
|
||||
Character.Create(configPath, spawnPosition);
|
||||
ThrowError(errorMsg);
|
||||
}
|
||||
}));
|
||||
|
||||
commands.Add(new Command("spawnitem", "spawnitem [itemname] [cursor/inventory]: Spawn an item at the position of the cursor, in the inventory of the controlled character or at a random spawnpoint if the last parameter is omitted.", (string[] args) =>
|
||||
commands.Add(new Command("spawnitem", "spawnitem [itemname] [cursor/inventory]: Spawn an item at the position of the cursor, in the inventory of the controlled character or at a random spawnpoint if the last parameter is omitted.",
|
||||
(string[] args) =>
|
||||
{
|
||||
if (args.Length < 1) return;
|
||||
|
||||
Vector2? spawnPos = null;
|
||||
Inventory spawnInventory = null;
|
||||
|
||||
int extraParams = 0;
|
||||
switch (args.Last())
|
||||
string errorMsg;
|
||||
SpawnItem(args, GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition), out errorMsg);
|
||||
if (!string.IsNullOrWhiteSpace(errorMsg))
|
||||
{
|
||||
case "cursor":
|
||||
extraParams = 1;
|
||||
spawnPos = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
break;
|
||||
case "inventory":
|
||||
extraParams = 1;
|
||||
spawnInventory = Character.Controlled == null ? null : Character.Controlled.Inventory;
|
||||
break;
|
||||
default:
|
||||
extraParams = 0;
|
||||
break;
|
||||
ThrowError(errorMsg);
|
||||
}
|
||||
|
||||
string itemName = string.Join(" ", args.Take(args.Length - extraParams)).ToLowerInvariant();
|
||||
|
||||
var itemPrefab = MapEntityPrefab.Find(itemName) as ItemPrefab;
|
||||
if (itemPrefab == null)
|
||||
},
|
||||
null,
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
string errorMsg;
|
||||
SpawnItem(args, cursorWorldPos, out errorMsg);
|
||||
if (!string.IsNullOrWhiteSpace(errorMsg))
|
||||
{
|
||||
ThrowError("Item \"" + itemName + "\" not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (spawnPos == null && spawnInventory == null)
|
||||
{
|
||||
var wp = WayPoint.GetRandom(SpawnType.Human, null, Submarine.MainSub);
|
||||
spawnPos = wp == null ? Vector2.Zero : wp.WorldPosition;
|
||||
}
|
||||
|
||||
if (spawnPos != null)
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(itemPrefab, (Vector2)spawnPos);
|
||||
|
||||
}
|
||||
else if (spawnInventory != null)
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(itemPrefab, spawnInventory);
|
||||
ThrowError(errorMsg);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -258,12 +215,26 @@ namespace Barotrauma
|
||||
{
|
||||
HumanAIController.DisableCrewAI = true;
|
||||
NewMessage("Crew AI disabled", Color.White);
|
||||
},
|
||||
null,
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
HumanAIController.DisableCrewAI = true;
|
||||
NewMessage("Crew AI disabled by \"" + client.Name + "\"", Color.White);
|
||||
GameMain.Server.SendChatMessage("Crew AI disabled", client);
|
||||
}));
|
||||
|
||||
commands.Add(new Command("enablecrewai", "enablecrewai: Enable the AI of the NPCs in the crew.", (string[] args) =>
|
||||
{
|
||||
HumanAIController.DisableCrewAI = false;
|
||||
NewMessage("Crew AI enabled", Color.White);
|
||||
},
|
||||
null,
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
HumanAIController.DisableCrewAI = false;
|
||||
NewMessage("Crew AI enabled by \"" + client.Name + "\"", Color.White);
|
||||
GameMain.Server.SendChatMessage("Crew AI enabled", client);
|
||||
}));
|
||||
|
||||
commands.Add(new Command("autorestart", "autorestart [true/false]: Enable or disable round auto-restart.", (string[] args) =>
|
||||
@@ -289,7 +260,7 @@ namespace Barotrauma
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
}
|
||||
NewMessage(GameMain.Server.AutoRestart ? "Automatic restart enabled." : "Automatic restart disabled.", Color.White);
|
||||
}));
|
||||
}, null, null));
|
||||
|
||||
commands.Add(new Command("autorestartinterval", "autorestartinterval [seconds]: Set how long the server waits between rounds before automatically starting a new one. If set to 0, autorestart is disabled.", (string[] args) =>
|
||||
{
|
||||
@@ -317,7 +288,7 @@ namespace Barotrauma
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
}
|
||||
}
|
||||
}));
|
||||
}, null, null));
|
||||
|
||||
commands.Add(new Command("autorestarttimer", "autorestarttimer [seconds]: Set the current autorestart countdown to the specified value.", (string[] args) =>
|
||||
{
|
||||
@@ -346,10 +317,12 @@ namespace Barotrauma
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
}
|
||||
}
|
||||
}));
|
||||
}, null, null));
|
||||
|
||||
commands.Add(new Command("giveperm", "giveperm [id]: Grants administrative permissions to the player with the specified client ID.", (string[] args) =>
|
||||
{
|
||||
//todo: allow client usage
|
||||
|
||||
if (GameMain.Server == null) return;
|
||||
if (args.Length < 1) return;
|
||||
|
||||
@@ -367,20 +340,23 @@ namespace Barotrauma
|
||||
ClientPermissions permission = ClientPermissions.None;
|
||||
if (perm.ToLower() == "all")
|
||||
{
|
||||
permission = ClientPermissions.EndRound | ClientPermissions.Kick | ClientPermissions.Ban | ClientPermissions.SelectSub | ClientPermissions.SelectMode | ClientPermissions.ManageCampaign;
|
||||
permission = ClientPermissions.EndRound | ClientPermissions.Kick | ClientPermissions.Ban |
|
||||
ClientPermissions.SelectSub | ClientPermissions.SelectMode | ClientPermissions.ManageCampaign | ClientPermissions.ConsoleCommands;
|
||||
}
|
||||
else
|
||||
{
|
||||
Enum.TryParse<ClientPermissions>(perm, out permission);
|
||||
Enum.TryParse(perm, out permission);
|
||||
}
|
||||
client.SetPermissions(client.Permissions | permission);
|
||||
client.GivePermission(permission);
|
||||
GameMain.Server.UpdateClientPermissions(client);
|
||||
DebugConsole.NewMessage("Granted "+perm+" permissions to "+client.Name+".",Color.White);
|
||||
NewMessage("Granted " + perm + " permissions to " + client.Name + ".", Color.White);
|
||||
});
|
||||
}));
|
||||
|
||||
commands.Add(new Command("revokeperm", "revokeperm [id]: Revokes administrative permissions to the player with the specified client ID.", (string[] args) =>
|
||||
{
|
||||
//todo: allow client usage
|
||||
|
||||
if (GameMain.Server == null) return;
|
||||
if (args.Length < 1) return;
|
||||
|
||||
@@ -402,11 +378,11 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
Enum.TryParse<ClientPermissions>(perm, out permission);
|
||||
Enum.TryParse(perm, out permission);
|
||||
}
|
||||
client.SetPermissions(client.Permissions & ~permission);
|
||||
client.RemovePermission(permission);
|
||||
GameMain.Server.UpdateClientPermissions(client);
|
||||
DebugConsole.NewMessage("Revoked " + perm + " permissions from " + client.Name + ".", Color.White);
|
||||
NewMessage("Revoked " + perm + " permissions from " + client.Name + ".", Color.White);
|
||||
});
|
||||
}));
|
||||
|
||||
@@ -521,7 +497,7 @@ namespace Barotrauma
|
||||
}
|
||||
banDuration = parsedBanDuration;
|
||||
}
|
||||
|
||||
|
||||
var client = GameMain.Server.ConnectedClients.Find(c => c.Connection.RemoteEndPoint.Address.ToString() == args[0]);
|
||||
if (client == null)
|
||||
{
|
||||
@@ -556,6 +532,28 @@ namespace Barotrauma
|
||||
tpCharacter.Submarine = null;
|
||||
tpCharacter.AnimController.SetPosition(ConvertUnits.ToSimUnits(cam.ScreenToWorld(PlayerInput.MousePosition)));
|
||||
tpCharacter.AnimController.FindHull(cam.ScreenToWorld(PlayerInput.MousePosition), true);
|
||||
},
|
||||
null,
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
Character tpCharacter = null;
|
||||
|
||||
if (args.Length == 0)
|
||||
{
|
||||
tpCharacter = client.Character;
|
||||
}
|
||||
else
|
||||
{
|
||||
tpCharacter = FindMatchingCharacter(args, false);
|
||||
}
|
||||
|
||||
if (tpCharacter == null) return;
|
||||
|
||||
var cam = GameMain.GameScreen.Cam;
|
||||
tpCharacter.AnimController.CurrentHull = null;
|
||||
tpCharacter.Submarine = null;
|
||||
tpCharacter.AnimController.SetPosition(ConvertUnits.ToSimUnits(cursorWorldPos));
|
||||
tpCharacter.AnimController.FindHull(cursorWorldPos, true);
|
||||
}));
|
||||
|
||||
commands.Add(new Command("godmode", "godmode: Toggle submarine godmode. Makes the main submarine invulnerable to damage.", (string[] args) =>
|
||||
@@ -564,17 +562,26 @@ namespace Barotrauma
|
||||
|
||||
Submarine.MainSub.GodMode = !Submarine.MainSub.GodMode;
|
||||
NewMessage(Submarine.MainSub.GodMode ? "Godmode on" : "Godmode off", Color.White);
|
||||
},
|
||||
null,
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
if (Submarine.MainSub == null) return;
|
||||
|
||||
Submarine.MainSub.GodMode = !Submarine.MainSub.GodMode;
|
||||
NewMessage((Submarine.MainSub.GodMode ? "Godmode turned on by \"" : "Godmode off by \"") + client.Name+"\"", Color.White);
|
||||
GameMain.Server.SendChatMessage(Submarine.MainSub.GodMode ? "Godmode on" : "Godmode off", client);
|
||||
}));
|
||||
|
||||
commands.Add(new Command("lockx", "lockx: Lock horizontal movement of the main submarine.", (string[] args) =>
|
||||
{
|
||||
Submarine.LockX = !Submarine.LockX;
|
||||
}));
|
||||
}, null, null));
|
||||
|
||||
commands.Add(new Command("locky", "loxky: Lock vertical movement of the main submarine.", (string[] args) =>
|
||||
{
|
||||
Submarine.LockY = !Submarine.LockY;
|
||||
}));
|
||||
}, null, null));
|
||||
|
||||
commands.Add(new Command("dumpids", "", (string[] args) =>
|
||||
{
|
||||
@@ -601,6 +608,27 @@ namespace Barotrauma
|
||||
healedCharacter = FindMatchingCharacter(args);
|
||||
}
|
||||
|
||||
if (healedCharacter != null)
|
||||
{
|
||||
healedCharacter.AddDamage(CauseOfDeath.Damage, -healedCharacter.MaxHealth, null);
|
||||
healedCharacter.Oxygen = 100.0f;
|
||||
healedCharacter.Bleeding = 0.0f;
|
||||
healedCharacter.SetStun(0.0f, true);
|
||||
}
|
||||
},
|
||||
null,
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
Character healedCharacter = null;
|
||||
if (args.Length == 0)
|
||||
{
|
||||
healedCharacter = client.Character;
|
||||
}
|
||||
else
|
||||
{
|
||||
healedCharacter = FindMatchingCharacter(args);
|
||||
}
|
||||
|
||||
if (healedCharacter != null)
|
||||
{
|
||||
healedCharacter.AddDamage(CauseOfDeath.Damage, -healedCharacter.MaxHealth, null);
|
||||
@@ -636,11 +664,44 @@ namespace Barotrauma
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
null,
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
Character revivedCharacter = null;
|
||||
if (args.Length == 0)
|
||||
{
|
||||
revivedCharacter = client.Character;
|
||||
}
|
||||
else
|
||||
{
|
||||
revivedCharacter = FindMatchingCharacter(args);
|
||||
}
|
||||
|
||||
if (revivedCharacter == null) return;
|
||||
|
||||
revivedCharacter.Revive(false);
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
if (c.Character != revivedCharacter) continue;
|
||||
|
||||
//clients stop controlling the character when it dies, force control back
|
||||
GameMain.Server.SetClientCharacter(c, revivedCharacter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
commands.Add(new Command("freeze", "", (string[] args) =>
|
||||
{
|
||||
if (Character.Controlled != null) Character.Controlled.AnimController.Frozen = !Character.Controlled.AnimController.Frozen;
|
||||
},
|
||||
null,
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
if (client.Character != null) client.Character.AnimController.Frozen = !client.Character.AnimController.Frozen;
|
||||
}));
|
||||
|
||||
commands.Add(new Command("freecamera|freecam", "freecam: Detach the camera from the controlled character.", (string[] args) =>
|
||||
@@ -676,6 +737,17 @@ namespace Barotrauma
|
||||
if (args.Length > 2) float.TryParse(args[2], out damage);
|
||||
if (args.Length > 3) float.TryParse(args[3], out structureDamage);
|
||||
new Explosion(range, force, damage, structureDamage).Explode(explosionPos);
|
||||
},
|
||||
null,
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
Vector2 explosionPos = cursorWorldPos;
|
||||
float range = 500, force = 10, damage = 50, structureDamage = 10;
|
||||
if (args.Length > 0) float.TryParse(args[0], out range);
|
||||
if (args.Length > 1) float.TryParse(args[1], out force);
|
||||
if (args.Length > 2) float.TryParse(args[2], out damage);
|
||||
if (args.Length > 3) float.TryParse(args[3], out structureDamage);
|
||||
new Explosion(range, force, damage, structureDamage).Explode(explosionPos);
|
||||
}));
|
||||
|
||||
commands.Add(new Command("fixitems", "fixitems: Repairs all items and restores them to full condition.", (string[] args) =>
|
||||
@@ -684,7 +756,7 @@ namespace Barotrauma
|
||||
{
|
||||
it.Condition = it.Prefab.Health;
|
||||
}
|
||||
}));
|
||||
}, null, null));
|
||||
|
||||
commands.Add(new Command("fixhulls|fixwalls", "fixwalls/fixhulls: Fixes all walls.", (string[] args) =>
|
||||
{
|
||||
@@ -695,7 +767,7 @@ namespace Barotrauma
|
||||
w.AddDamage(i, -100000.0f);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}, null, null));
|
||||
|
||||
commands.Add(new Command("power", "power [temperature]: Immediately sets the temperature of the nuclear reactor to the specified value.", (string[] args) =>
|
||||
{
|
||||
@@ -714,7 +786,7 @@ namespace Barotrauma
|
||||
{
|
||||
reactorItem.CreateServerEvent(reactor);
|
||||
}
|
||||
}));
|
||||
}, null, null));
|
||||
|
||||
commands.Add(new Command("oxygen|air", "oxygen/air: Replenishes the oxygen levels in every room to 100%.", (string[] args) =>
|
||||
{
|
||||
@@ -722,7 +794,7 @@ namespace Barotrauma
|
||||
{
|
||||
hull.OxygenPercentage = 100.0f;
|
||||
}
|
||||
}));
|
||||
}, null, null));
|
||||
|
||||
commands.Add(new Command("killmonsters", "killmonsters: Immediately kills all AI-controlled enemies in the level.", (string[] args) =>
|
||||
{
|
||||
@@ -731,7 +803,7 @@ namespace Barotrauma
|
||||
if (!(c.AIController is EnemyAIController)) continue;
|
||||
c.AddDamage(CauseOfDeath.Damage, 10000.0f, null);
|
||||
}
|
||||
}));
|
||||
}, null, null));
|
||||
|
||||
commands.Add(new Command("netstats", "netstats: Toggles the visibility of the network statistics UI.", (string[] args) =>
|
||||
{
|
||||
@@ -744,7 +816,6 @@ namespace Barotrauma
|
||||
if (GameMain.Server == null) return;
|
||||
|
||||
int separatorIndex = Array.IndexOf(args, ";");
|
||||
|
||||
if (separatorIndex == -1 || args.Length < 3)
|
||||
{
|
||||
ThrowError("Invalid parameters. The command should be formatted as \"setclientcharacter [client] ; [character]\"");
|
||||
@@ -753,8 +824,7 @@ namespace Barotrauma
|
||||
|
||||
string[] argsLeft = args.Take(separatorIndex).ToArray();
|
||||
string[] argsRight = args.Skip(separatorIndex + 1).ToArray();
|
||||
|
||||
string clientName = String.Join(" ", argsLeft);
|
||||
string clientName = string.Join(" ", argsLeft);
|
||||
|
||||
var client = GameMain.Server.ConnectedClients.Find(c => c.Name == clientName);
|
||||
if (client == null)
|
||||
@@ -762,6 +832,29 @@ namespace Barotrauma
|
||||
ThrowError("Client \"" + clientName + "\" not found.");
|
||||
}
|
||||
|
||||
var character = FindMatchingCharacter(argsRight, false);
|
||||
GameMain.Server.SetClientCharacter(client, character);
|
||||
},
|
||||
null,
|
||||
(Client senderClient, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
int separatorIndex = Array.IndexOf(args, ";");
|
||||
if (separatorIndex == -1 || args.Length < 3)
|
||||
{
|
||||
GameMain.Server.SendChatMessage("Invalid parameters. The command should be formatted as \"setclientcharacter [client] ; [character]\"", senderClient);
|
||||
return;
|
||||
}
|
||||
|
||||
string[] argsLeft = args.Take(separatorIndex).ToArray();
|
||||
string[] argsRight = args.Skip(separatorIndex + 1).ToArray();
|
||||
string clientName = string.Join(" ", argsLeft);
|
||||
|
||||
var client = GameMain.Server.ConnectedClients.Find(c => c.Name == clientName);
|
||||
if (client == null)
|
||||
{
|
||||
GameMain.Server.SendChatMessage("Client \"" + clientName + "\" not found.", senderClient);
|
||||
}
|
||||
|
||||
var character = FindMatchingCharacter(argsRight, false);
|
||||
GameMain.Server.SetClientCharacter(client, character);
|
||||
}));
|
||||
@@ -822,6 +915,69 @@ namespace Barotrauma
|
||||
campaign.Map.SelectLocation(location);
|
||||
NewMessage(location.Name + " selected.", Color.White);
|
||||
}
|
||||
},
|
||||
(string[] args) =>
|
||||
{
|
||||
#if CLIENT
|
||||
var campaign = GameMain.GameSession?.GameMode as CampaignMode;
|
||||
if (campaign == null)
|
||||
{
|
||||
ThrowError("No campaign active!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Length == 0)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (LocationConnection connection in campaign.Map.CurrentLocation.Connections)
|
||||
{
|
||||
NewMessage(" " + i + ". " + connection.OtherLocation(campaign.Map.CurrentLocation).Name, Color.White);
|
||||
i++;
|
||||
}
|
||||
ShowQuestionPrompt("Select a destination (0 - " + (campaign.Map.CurrentLocation.Connections.Count - 1) + "):", (string selectedDestination) =>
|
||||
{
|
||||
int destinationIndex = -1;
|
||||
if (!int.TryParse(selectedDestination, out destinationIndex)) return;
|
||||
if (destinationIndex < 0 || destinationIndex >= campaign.Map.CurrentLocation.Connections.Count)
|
||||
{
|
||||
NewMessage("Index out of bounds!", Color.Red);
|
||||
return;
|
||||
}
|
||||
GameMain.Client.SendConsoleCommand("campaigndestination " + destinationIndex);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
int destinationIndex = -1;
|
||||
if (!int.TryParse(args[0], out destinationIndex)) return;
|
||||
if (destinationIndex < 0 || destinationIndex >= campaign.Map.CurrentLocation.Connections.Count)
|
||||
{
|
||||
NewMessage("Index out of bounds!", Color.Red);
|
||||
return;
|
||||
}
|
||||
GameMain.Client.SendConsoleCommand("campaigndestination " + destinationIndex);
|
||||
}
|
||||
#endif
|
||||
},
|
||||
(Client senderClient, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
var campaign = GameMain.GameSession?.GameMode as CampaignMode;
|
||||
if (campaign == null)
|
||||
{
|
||||
GameMain.Server.SendChatMessage("No campaign active!", senderClient);
|
||||
return;
|
||||
}
|
||||
|
||||
int destinationIndex = -1;
|
||||
if (args.Length < 1 || !int.TryParse(args[0], out destinationIndex)) return;
|
||||
if (destinationIndex < 0 || destinationIndex >= campaign.Map.CurrentLocation.Connections.Count)
|
||||
{
|
||||
GameMain.Server.SendChatMessage("Index out of bounds!", senderClient);
|
||||
return;
|
||||
}
|
||||
Location location = campaign.Map.CurrentLocation.Connections[destinationIndex].OtherLocation(campaign.Map.CurrentLocation);
|
||||
campaign.Map.SelectLocation(location);
|
||||
GameMain.Server.SendChatMessage(location.Name + " selected.", senderClient);
|
||||
}));
|
||||
|
||||
#if DEBUG
|
||||
@@ -856,7 +1012,7 @@ namespace Barotrauma
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(wall);
|
||||
}
|
||||
}));
|
||||
}, null, null));
|
||||
#endif
|
||||
InitProjectSpecific();
|
||||
|
||||
@@ -944,7 +1100,7 @@ namespace Barotrauma
|
||||
return Messages[selectedIndex].Text;
|
||||
}
|
||||
|
||||
public static void ExecuteCommand(string command, GameMain game)
|
||||
public static void ExecuteCommand(string command)
|
||||
{
|
||||
if (activeQuestionCallback != null)
|
||||
{
|
||||
@@ -967,14 +1123,25 @@ namespace Barotrauma
|
||||
{
|
||||
NewMessage(command, Color.White);
|
||||
}
|
||||
|
||||
|
||||
#if !DEBUG && CLIENT
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
if (GameMain.Client.HasConsoleCommandPermission(splitCommand[0].ToLowerInvariant()))
|
||||
{
|
||||
GameMain.Client.SendConsoleCommand(command);
|
||||
NewMessage("Server command: "+command, Color.White);
|
||||
Command matchingCommand = commands.Find(c => c.names.Contains(splitCommand[0].ToLowerInvariant()));
|
||||
|
||||
//if the command is not defined client-side, we'll relay it anyway because it may be a custom command at the server's side
|
||||
if (matchingCommand == null || matchingCommand.RelayToServer)
|
||||
{
|
||||
GameMain.Client.SendConsoleCommand(command);
|
||||
}
|
||||
else
|
||||
{
|
||||
matchingCommand.ClientExecute(splitCommand.Skip(1).ToArray());
|
||||
}
|
||||
|
||||
NewMessage("Server command: " + command, Color.White);
|
||||
return;
|
||||
}
|
||||
if (!IsCommandPermitted(splitCommand[0].ToLowerInvariant(), GameMain.Client))
|
||||
@@ -1001,7 +1168,41 @@ namespace Barotrauma
|
||||
ThrowError("Command \"" + splitCommand[0] + "\" not found.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void ExecuteClientCommand(Client client, Vector2 cursorWorldPos, string command)
|
||||
{
|
||||
if (GameMain.Server == null) return;
|
||||
if (string.IsNullOrWhiteSpace(command)) return;
|
||||
if (!client.HasPermission(ClientPermissions.ConsoleCommands))
|
||||
{
|
||||
GameMain.Server.SendChatMessage("You are not permitted to use console commands!", client);
|
||||
return;
|
||||
}
|
||||
|
||||
string[] splitCommand = SplitCommand(command);
|
||||
Command matchingCommand = commands.Find(c => c.names.Contains(splitCommand[0].ToLowerInvariant()));
|
||||
if (matchingCommand != null && !client.PermittedConsoleCommands.Contains(matchingCommand))
|
||||
{
|
||||
GameMain.Server.SendChatMessage("You are not permitted to use the command\"" + matchingCommand.names[0] + "\"!", client);
|
||||
return;
|
||||
}
|
||||
else if (matchingCommand == null)
|
||||
{
|
||||
GameMain.Server.SendChatMessage("Command \"" + splitCommand[0] + "\" not found.", client);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
matchingCommand.ServerExecuteOnClientRequest(client, cursorWorldPos, splitCommand.Skip(1).ToArray());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ThrowError("Executing the command \"" + matchingCommand.names[0]+"\" by request from \""+client.Name+"\" failed.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Character FindMatchingCharacter(string[] args, bool ignoreRemotePlayers = false)
|
||||
{
|
||||
if (args.Length == 0) return null;
|
||||
@@ -1049,6 +1250,152 @@ namespace Barotrauma
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void SpawnCharacter(string[] args, Vector2 cursorWorldPos, out string errorMsg)
|
||||
{
|
||||
errorMsg = "";
|
||||
if (args.Length == 0) return;
|
||||
|
||||
Character spawnedCharacter = null;
|
||||
|
||||
Vector2 spawnPosition = Vector2.Zero;
|
||||
WayPoint spawnPoint = null;
|
||||
|
||||
if (args.Length > 1)
|
||||
{
|
||||
switch (args[1].ToLowerInvariant())
|
||||
{
|
||||
case "inside":
|
||||
spawnPoint = WayPoint.GetRandom(SpawnType.Human, null, Submarine.MainSub);
|
||||
break;
|
||||
case "outside":
|
||||
spawnPoint = WayPoint.GetRandom(SpawnType.Enemy);
|
||||
break;
|
||||
case "near":
|
||||
case "close":
|
||||
float closestDist = -1.0f;
|
||||
foreach (WayPoint wp in WayPoint.WayPointList)
|
||||
{
|
||||
if (wp.Submarine != null) continue;
|
||||
|
||||
//don't spawn inside hulls
|
||||
if (Hull.FindHull(wp.WorldPosition, null) != null) continue;
|
||||
|
||||
float dist = Vector2.Distance(wp.WorldPosition, GameMain.GameScreen.Cam.WorldViewCenter);
|
||||
|
||||
if (closestDist < 0.0f || dist < closestDist)
|
||||
{
|
||||
spawnPoint = wp;
|
||||
closestDist = dist;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "cursor":
|
||||
spawnPosition = cursorWorldPos;
|
||||
break;
|
||||
default:
|
||||
spawnPoint = WayPoint.GetRandom(args[0].ToLowerInvariant() == "human" ? SpawnType.Human : SpawnType.Enemy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spawnPoint = WayPoint.GetRandom(args[0].ToLowerInvariant() == "human" ? SpawnType.Human : SpawnType.Enemy);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(args[0])) return;
|
||||
|
||||
if (spawnPoint != null) spawnPosition = spawnPoint.WorldPosition;
|
||||
|
||||
if (args[0].ToLowerInvariant() == "human")
|
||||
{
|
||||
spawnedCharacter = Character.Create(Character.HumanConfigFile, spawnPosition);
|
||||
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession != null)
|
||||
{
|
||||
SinglePlayerCampaign mode = GameMain.GameSession.GameMode as SinglePlayerCampaign;
|
||||
if (mode != null)
|
||||
{
|
||||
Character.Controlled = spawnedCharacter;
|
||||
GameMain.GameSession.CrewManager.AddCharacter(Character.Controlled);
|
||||
GameMain.GameSession.CrewManager.SelectCharacter(null, Character.Controlled);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
List<string> characterFiles = GameMain.Config.SelectedContentPackage.GetFilesOfType(ContentType.Character);
|
||||
|
||||
foreach (string characterFile in characterFiles)
|
||||
{
|
||||
if (Path.GetFileNameWithoutExtension(characterFile).ToLowerInvariant() == args[0].ToLowerInvariant())
|
||||
{
|
||||
Character.Create(characterFile, spawnPosition);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
errorMsg = "No character matching the name \"" + args[0] + "\" found in the selected content package.";
|
||||
|
||||
//attempt to open the config from the default path (the file may still be present even if it isn't included in the content package)
|
||||
string configPath = "Content/Characters/"
|
||||
+ args[0].First().ToString().ToUpper() + args[0].Substring(1)
|
||||
+ "/" + args[0].ToLower() + ".xml";
|
||||
Character.Create(configPath, spawnPosition);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SpawnItem(string[] args, Vector2 cursorPos, out string errorMsg)
|
||||
{
|
||||
errorMsg = "";
|
||||
if (args.Length < 1) return;
|
||||
|
||||
Vector2? spawnPos = null;
|
||||
Inventory spawnInventory = null;
|
||||
|
||||
int extraParams = 0;
|
||||
switch (args.Last())
|
||||
{
|
||||
case "cursor":
|
||||
extraParams = 1;
|
||||
spawnPos = cursorPos;
|
||||
break;
|
||||
case "inventory":
|
||||
extraParams = 1;
|
||||
spawnInventory = Character.Controlled == null ? null : Character.Controlled.Inventory;
|
||||
break;
|
||||
default:
|
||||
extraParams = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
string itemName = string.Join(" ", args.Take(args.Length - extraParams)).ToLowerInvariant();
|
||||
|
||||
var itemPrefab = MapEntityPrefab.Find(itemName) as ItemPrefab;
|
||||
if (itemPrefab == null)
|
||||
{
|
||||
errorMsg = "Item \"" + itemName + "\" not found!";
|
||||
return;
|
||||
}
|
||||
|
||||
if (spawnPos == null && spawnInventory == null)
|
||||
{
|
||||
var wp = WayPoint.GetRandom(SpawnType.Human, null, Submarine.MainSub);
|
||||
spawnPos = wp == null ? Vector2.Zero : wp.WorldPosition;
|
||||
}
|
||||
|
||||
if (spawnPos != null)
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(itemPrefab, (Vector2)spawnPos);
|
||||
|
||||
}
|
||||
else if (spawnInventory != null)
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(itemPrefab, spawnInventory);
|
||||
}
|
||||
}
|
||||
|
||||
public static void NewMessage(string msg, Color color)
|
||||
{
|
||||
if (string.IsNullOrEmpty((msg))) return;
|
||||
|
||||
@@ -157,9 +157,10 @@ namespace Barotrauma.Networking
|
||||
return rName;
|
||||
}
|
||||
|
||||
public void SetPermissions(ClientPermissions permissions)
|
||||
public void SetPermissions(ClientPermissions permissions, List<DebugConsole.Command> permittedConsoleCommands)
|
||||
{
|
||||
this.Permissions = permissions;
|
||||
this.PermittedConsoleCommands = permittedConsoleCommands;
|
||||
}
|
||||
|
||||
public void GivePermission(ClientPermissions permission)
|
||||
|
||||
@@ -795,6 +795,11 @@ namespace Barotrauma.Networking
|
||||
campaign.ServerRead(inc, sender);
|
||||
}
|
||||
break;
|
||||
case ClientPermissions.ConsoleCommands:
|
||||
string consoleCommand = inc.ReadString();
|
||||
Vector2 clientCursorPos = new Vector2(inc.ReadSingle(), inc.ReadSingle());
|
||||
DebugConsole.ExecuteClientCommand(sender, clientCursorPos, consoleCommand);
|
||||
break;
|
||||
}
|
||||
|
||||
inc.ReadPadBits();
|
||||
@@ -853,7 +858,7 @@ namespace Barotrauma.Networking
|
||||
outmsg.Write(GameStarted);
|
||||
outmsg.Write(AllowSpectating);
|
||||
|
||||
outmsg.Write((byte)c.Permissions);
|
||||
WritePermissions(outmsg, c);
|
||||
}
|
||||
|
||||
private void ClientWriteIngame(Client c)
|
||||
@@ -1622,6 +1627,12 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public void SendChatMessage(string txt, Client recipient)
|
||||
{
|
||||
ChatMessage msg = ChatMessage.Create("", txt, ChatMessageType.Server, null);
|
||||
SendChatMessage(msg, recipient);
|
||||
}
|
||||
|
||||
public void SendChatMessage(ChatMessage msg, Client recipient)
|
||||
{
|
||||
msg.NetStateID = recipient.ChatMsgQueue.Count > 0 ?
|
||||
@@ -1928,6 +1939,15 @@ namespace Barotrauma.Networking
|
||||
|
||||
var msg = server.CreateMessage();
|
||||
msg.Write((byte)ServerPacketHeader.PERMISSIONS);
|
||||
WritePermissions(msg, client);
|
||||
|
||||
server.SendMessage(msg, client.Connection, NetDeliveryMethod.ReliableUnordered);
|
||||
|
||||
SaveClientPermissions();
|
||||
}
|
||||
|
||||
private void WritePermissions(NetBuffer msg, Client client)
|
||||
{
|
||||
msg.Write((byte)client.Permissions);
|
||||
if (client.Permissions.HasFlag(ClientPermissions.ConsoleCommands))
|
||||
{
|
||||
@@ -1940,10 +1960,6 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
server.SendMessage(msg, client.Connection, NetDeliveryMethod.ReliableUnordered);
|
||||
|
||||
SaveClientPermissions();
|
||||
}
|
||||
|
||||
public void SetClientCharacter(Client client, Character newCharacter)
|
||||
|
||||
@@ -218,11 +218,11 @@ namespace Barotrauma.Networking
|
||||
var savedPermissions = clientPermissions.Find(cp => cp.IP == newClient.Connection.RemoteEndPoint.Address.ToString());
|
||||
if (savedPermissions != null)
|
||||
{
|
||||
newClient.SetPermissions(savedPermissions.Permissions);
|
||||
newClient.SetPermissions(savedPermissions.Permissions, savedPermissions.PermittedCommands);
|
||||
}
|
||||
else
|
||||
{
|
||||
newClient.SetPermissions(ClientPermissions.None);
|
||||
newClient.SetPermissions(ClientPermissions.None, new List<DebugConsole.Command>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -364,14 +364,13 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
new SavedClientPermission(clientName, clientIP, permissions, permittedCommands);
|
||||
clientPermissions.Add(new SavedClientPermission(clientName, clientIP, permissions, permittedCommands));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method for loading old .txt client permission files to provide backwards compatibility
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
private void LoadClientPermissionsOld(string file)
|
||||
{
|
||||
if (!File.Exists(file)) return;
|
||||
@@ -407,6 +406,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void SaveClientPermissions()
|
||||
{
|
||||
//delete old client permission file
|
||||
if (File.Exists("Data/clientpermissions.txt"))
|
||||
{
|
||||
File.Delete("Data/clientpermissions.txt");
|
||||
}
|
||||
|
||||
Log("Saving client permissions", ServerLog.MessageType.ServerMessage);
|
||||
|
||||
XDocument doc = new XDocument(new XElement("ClientPermissions"));
|
||||
|
||||
Reference in New Issue
Block a user