commit 7245c721339885d062567befc052a592391b3b4a Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Sun Mar 10 15:22:31 2019 +0200 Fixed StatusEffects only applying afflictions to one limb even if the target is "Character" instead of "Limb", added a subtle screen distortion effect to heavy radiation sickness. Closes #1256 commit e0db27e62ec9546fd4b182a0cc97f7e5830645ae Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Sat Mar 9 21:53:51 2019 +0200 Fixed WrapText adding unnecessary spaces after every line break. Closes #1215 commit 988bc58d51c195ad9265b84a1e97e0101cd3f808 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Sat Mar 9 21:12:50 2019 +0200 Fixed crashing when attempting to create a body for a wall section that's less than 1 unit long (e.g. if a wall that's just slightly longer than the wall section size receives damage). commit 8c31157425a9e2ec02312618d1bfa359ab3ee87d Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Sat Mar 9 20:30:44 2019 +0200 Fixed clients being unable to toggle the respawn shuttle on/off commit a4ccb039219830efe9cd305c26942dda1bd04e9c Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Sat Mar 9 19:33:22 2019 +0200 Fixed inability to select the respawn shuttle as a client host commit b89b2d2c282d8c74d7ccd37b3f29dcab51eff680 Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Sat Mar 9 19:32:41 2019 +0200 Made it possible to edit the style of the ListBox under GUIDropDowns, increased the opacity of the listbox to make the contents more readable when there's text behind it commit 8f6d9aef3d637fe37a18c78f4b15ef8fd266374e Author: Joonas Rikkonen <poe.regalis@gmail.com> Date: Sat Mar 9 18:11:23 2019 +0200 Fixed NetLobbyScreen not showing the names of the submarines the client doesn't have
485 lines
20 KiB
C#
485 lines
20 KiB
C#
using Lidgren.Network;
|
|
using Microsoft.Xna.Framework;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Xml;
|
|
using System.Xml.Linq;
|
|
|
|
namespace Barotrauma.Networking
|
|
{
|
|
partial class ServerSettings
|
|
{
|
|
public const string SettingsFile = "serversettings.xml";
|
|
public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.xml";
|
|
|
|
partial void InitProjSpecific()
|
|
{
|
|
LoadSettings();
|
|
LoadClientPermissions();
|
|
}
|
|
|
|
private void WriteNetProperties(NetBuffer outMsg)
|
|
{
|
|
outMsg.Write((UInt16)netProperties.Keys.Count);
|
|
foreach (UInt32 key in netProperties.Keys)
|
|
{
|
|
outMsg.Write(key);
|
|
netProperties[key].Write(outMsg);
|
|
}
|
|
}
|
|
|
|
public void ServerAdminWrite(NetBuffer outMsg, Client c)
|
|
{
|
|
//outMsg.Write(isPublic);
|
|
//outMsg.Write(EnableUPnP);
|
|
//outMsg.WritePadBits();
|
|
//outMsg.Write((UInt16)QueryPort);
|
|
|
|
WriteNetProperties(outMsg);
|
|
WriteMonsterEnabled(outMsg);
|
|
BanList.ServerAdminWrite(outMsg, c);
|
|
Whitelist.ServerAdminWrite(outMsg, c);
|
|
}
|
|
|
|
public void ServerWrite(NetBuffer outMsg,Client c)
|
|
{
|
|
outMsg.Write(ServerName);
|
|
outMsg.Write(ServerMessageText);
|
|
outMsg.WriteRangedInteger(1, 60, TickRate);
|
|
|
|
WriteExtraCargo(outMsg);
|
|
|
|
Voting.ServerWrite(outMsg);
|
|
|
|
if (c.HasPermission(Networking.ClientPermissions.ManageSettings))
|
|
{
|
|
outMsg.Write(true);
|
|
outMsg.WritePadBits();
|
|
|
|
ServerAdminWrite(outMsg, c);
|
|
}
|
|
else
|
|
{
|
|
outMsg.Write(false);
|
|
outMsg.WritePadBits();
|
|
}
|
|
}
|
|
|
|
public void ServerRead(NetIncomingMessage incMsg,Client c)
|
|
{
|
|
if (!c.HasPermission(Networking.ClientPermissions.ManageSettings)) return;
|
|
|
|
NetFlags flags = (NetFlags)incMsg.ReadByte();
|
|
|
|
bool changed = false;
|
|
|
|
if (flags.HasFlag(NetFlags.Name))
|
|
{
|
|
string serverName = incMsg.ReadString();
|
|
if (ServerName != serverName) changed = true;
|
|
ServerName = serverName;
|
|
}
|
|
|
|
if (flags.HasFlag(NetFlags.Message))
|
|
{
|
|
string serverMessageText = incMsg.ReadString();
|
|
if (ServerMessageText != serverMessageText) changed = true;
|
|
ServerMessageText = serverMessageText;
|
|
}
|
|
|
|
if (flags.HasFlag(NetFlags.Properties))
|
|
{
|
|
changed |= ReadExtraCargo(incMsg);
|
|
|
|
UInt32 count = incMsg.ReadUInt32();
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
UInt32 key = incMsg.ReadUInt32();
|
|
|
|
if (netProperties.ContainsKey(key))
|
|
{
|
|
netProperties[key].Read(incMsg);
|
|
GameServer.Log(c.Name + " changed " + netProperties[key].Name + " to " + netProperties[key].Value.ToString(), ServerLog.MessageType.ServerMessage);
|
|
changed = true;
|
|
}
|
|
else
|
|
{
|
|
UInt32 size = incMsg.ReadVariableUInt32();
|
|
incMsg.Position += 8 * size;
|
|
}
|
|
}
|
|
|
|
bool changedMonsterSettings = incMsg.ReadBoolean(); incMsg.ReadPadBits();
|
|
changed |= changedMonsterSettings;
|
|
if (changedMonsterSettings) ReadMonsterEnabled(incMsg);
|
|
changed |= BanList.ServerAdminRead(incMsg, c);
|
|
changed |= Whitelist.ServerAdminRead(incMsg, c);
|
|
}
|
|
|
|
if (flags.HasFlag(NetFlags.Misc))
|
|
{
|
|
int missionType = GameMain.NetLobbyScreen.MissionTypeIndex + incMsg.ReadByte() - 1;
|
|
while (missionType < 0) missionType += Enum.GetValues(typeof(MissionType)).Length;
|
|
while (missionType >= Enum.GetValues(typeof(MissionType)).Length) missionType -= Enum.GetValues(typeof(MissionType)).Length;
|
|
GameMain.NetLobbyScreen.MissionTypeIndex = missionType;
|
|
|
|
int traitorSetting = (int)TraitorsEnabled + incMsg.ReadByte() - 1;
|
|
if (traitorSetting < 0) traitorSetting = 2;
|
|
if (traitorSetting > 2) traitorSetting = 0;
|
|
TraitorsEnabled = (YesNoMaybe)traitorSetting;
|
|
|
|
int botCount = BotCount + incMsg.ReadByte() - 1;
|
|
if (botCount < 0) botCount = MaxBotCount;
|
|
if (botCount > MaxBotCount) botCount = 0;
|
|
BotCount = botCount;
|
|
|
|
int botSpawnMode = (int)BotSpawnMode + incMsg.ReadByte() - 1;
|
|
if (botSpawnMode < 0) botSpawnMode = 1;
|
|
if (botSpawnMode > 1) botSpawnMode = 0;
|
|
BotSpawnMode = (BotSpawnMode)botSpawnMode;
|
|
|
|
float levelDifficulty = incMsg.ReadFloat();
|
|
if (levelDifficulty >= 0.0f) SelectedLevelDifficulty = levelDifficulty;
|
|
|
|
UseRespawnShuttle = incMsg.ReadBoolean();
|
|
|
|
bool changedAutoRestart = incMsg.ReadBoolean();
|
|
bool autoRestart = incMsg.ReadBoolean();
|
|
if (changedAutoRestart)
|
|
{
|
|
AutoRestart = autoRestart;
|
|
}
|
|
|
|
changed |= true;
|
|
}
|
|
|
|
if (flags.HasFlag(NetFlags.LevelSeed))
|
|
{
|
|
GameMain.NetLobbyScreen.LevelSeed = incMsg.ReadString();
|
|
changed |= true;
|
|
}
|
|
|
|
if (changed) GameMain.NetLobbyScreen.LastUpdateID++;
|
|
}
|
|
|
|
public void SaveSettings()
|
|
{
|
|
XDocument doc = new XDocument(new XElement("serversettings"));
|
|
|
|
SerializableProperty.SerializeProperties(this, doc.Root, true);
|
|
|
|
doc.Root.SetAttributeValue("name", ServerName);
|
|
doc.Root.SetAttributeValue("public", isPublic);
|
|
doc.Root.SetAttributeValue("port", GameMain.Server.NetPeerConfiguration.Port);
|
|
if (Steam.SteamManager.USE_STEAM) doc.Root.SetAttributeValue("queryport", QueryPort);
|
|
doc.Root.SetAttributeValue("maxplayers", maxPlayers);
|
|
doc.Root.SetAttributeValue("enableupnp", GameMain.Server.NetPeerConfiguration.EnableUPnP);
|
|
|
|
doc.Root.SetAttributeValue("autorestart", autoRestart);
|
|
|
|
doc.Root.SetAttributeValue("SubSelection", SubSelectionMode.ToString());
|
|
doc.Root.SetAttributeValue("ModeSelection", ModeSelectionMode.ToString());
|
|
doc.Root.SetAttributeValue("LevelDifficulty", ((int)selectedLevelDifficulty).ToString());
|
|
doc.Root.SetAttributeValue("TraitorsEnabled", TraitorsEnabled.ToString());
|
|
|
|
/*doc.Root.SetAttributeValue("BotCount", BotCount);
|
|
doc.Root.SetAttributeValue("MaxBotCount", MaxBotCount);*/
|
|
doc.Root.SetAttributeValue("BotSpawnMode", BotSpawnMode.ToString());
|
|
|
|
doc.Root.SetAttributeValue("AllowedRandomMissionTypes", string.Join(",", AllowedRandomMissionTypes));
|
|
|
|
doc.Root.SetAttributeValue("AllowedClientNameChars", string.Join(",", AllowedClientNameChars.Select(c => c.First + "-" + c.Second)));
|
|
|
|
doc.Root.SetAttributeValue("ServerMessage", ServerMessageText);
|
|
|
|
XmlWriterSettings settings = new XmlWriterSettings
|
|
{
|
|
Indent = true,
|
|
NewLineOnAttributes = true
|
|
};
|
|
|
|
using (var writer = XmlWriter.Create(SettingsFile, settings))
|
|
{
|
|
doc.Save(writer);
|
|
}
|
|
}
|
|
|
|
private void LoadSettings()
|
|
{
|
|
XDocument doc = null;
|
|
if (File.Exists(SettingsFile))
|
|
{
|
|
doc = XMLExtensions.TryLoadXml(SettingsFile);
|
|
}
|
|
|
|
if (doc == null || doc.Root == null)
|
|
{
|
|
doc = new XDocument(new XElement("serversettings"));
|
|
}
|
|
|
|
SerializableProperties = SerializableProperty.DeserializeProperties(this, doc.Root);
|
|
|
|
AutoRestart = doc.Root.GetAttributeBool("autorestart", false);
|
|
|
|
Voting.AllowSubVoting = SubSelectionMode == SelectionMode.Vote;
|
|
Voting.AllowModeVoting = ModeSelectionMode == SelectionMode.Vote;
|
|
|
|
selectedLevelDifficulty = doc.Root.GetAttributeFloat("LevelDifficulty", 20.0f);
|
|
GameMain.NetLobbyScreen.SetLevelDifficulty(selectedLevelDifficulty);
|
|
|
|
var traitorsEnabled = TraitorsEnabled;
|
|
Enum.TryParse(doc.Root.GetAttributeString("TraitorsEnabled", "No"), out traitorsEnabled);
|
|
TraitorsEnabled = traitorsEnabled;
|
|
GameMain.NetLobbyScreen.SetTraitorsEnabled(traitorsEnabled);
|
|
|
|
var botSpawnMode = BotSpawnMode.Fill;
|
|
Enum.TryParse(doc.Root.GetAttributeString("BotSpawnMode", "Fill"), out botSpawnMode);
|
|
BotSpawnMode = botSpawnMode;
|
|
|
|
//"65-90", "97-122", "48-59" = upper and lower case english alphabet and numbers
|
|
string[] allowedClientNameCharsStr = doc.Root.GetAttributeStringArray("AllowedClientNameChars", new string[] { "65-90", "97-122", "48-59" });
|
|
foreach (string allowedClientNameCharRange in allowedClientNameCharsStr)
|
|
{
|
|
string[] splitRange = allowedClientNameCharRange.Split('-');
|
|
if (splitRange.Length == 0 || splitRange.Length > 2)
|
|
{
|
|
DebugConsole.ThrowError("Error in server settings - " + allowedClientNameCharRange + " is not a valid range for characters allowed in client names.");
|
|
continue;
|
|
}
|
|
|
|
int min = -1;
|
|
if (!int.TryParse(splitRange[0], out min))
|
|
{
|
|
DebugConsole.ThrowError("Error in server settings - " + allowedClientNameCharRange + " is not a valid range for characters allowed in client names.");
|
|
continue;
|
|
}
|
|
int max = min;
|
|
if (splitRange.Length == 2)
|
|
{
|
|
if (!int.TryParse(splitRange[1], out max))
|
|
{
|
|
DebugConsole.ThrowError("Error in server settings - " + allowedClientNameCharRange + " is not a valid range for characters allowed in client names.");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (min > -1 && max > -1) AllowedClientNameChars.Add(new Pair<int, int>(min, max));
|
|
}
|
|
|
|
AllowedRandomMissionTypes = new List<MissionType>();
|
|
string[] allowedMissionTypeNames = doc.Root.GetAttributeStringArray(
|
|
"AllowedRandomMissionTypes", Enum.GetValues(typeof(MissionType)).Cast<MissionType>().Select(m => m.ToString()).ToArray());
|
|
foreach (string missionTypeName in allowedMissionTypeNames)
|
|
{
|
|
if (Enum.TryParse(missionTypeName, out MissionType missionType))
|
|
{
|
|
if (missionType == Barotrauma.MissionType.None) continue;
|
|
AllowedRandomMissionTypes.Add(missionType);
|
|
}
|
|
}
|
|
|
|
ServerName = doc.Root.GetAttributeString("name", "");
|
|
ServerMessageText = doc.Root.GetAttributeString("ServerMessage", "");
|
|
|
|
GameMain.NetLobbyScreen.SelectedModeIdentifier = GameModeIdentifier;
|
|
GameMain.NetLobbyScreen.MissionTypeName = MissionType;
|
|
|
|
GameMain.NetLobbyScreen.SetBotSpawnMode(BotSpawnMode);
|
|
GameMain.NetLobbyScreen.SetBotCount(BotCount);
|
|
|
|
List<string> monsterNames = GameMain.Instance.GetFilesOfType(ContentType.Character).ToList();
|
|
for (int i = 0; i < monsterNames.Count; i++)
|
|
{
|
|
monsterNames[i] = Path.GetFileName(Path.GetDirectoryName(monsterNames[i]));
|
|
}
|
|
MonsterEnabled = new Dictionary<string, bool>();
|
|
foreach (string s in monsterNames)
|
|
{
|
|
if (!MonsterEnabled.ContainsKey(s)) MonsterEnabled.Add(s, true);
|
|
}
|
|
|
|
AutoBanTime = doc.Root.GetAttributeFloat("autobantime", 60);
|
|
MaxAutoBanTime = doc.Root.GetAttributeFloat("maxautobantime", 360);
|
|
}
|
|
|
|
public void LoadClientPermissions()
|
|
{
|
|
ClientPermissions.Clear();
|
|
|
|
if (!File.Exists(ClientPermissionsFile))
|
|
{
|
|
if (File.Exists("Data/clientpermissions.txt"))
|
|
{
|
|
LoadClientPermissionsOld("Data/clientpermissions.txt");
|
|
}
|
|
return;
|
|
}
|
|
|
|
XDocument doc = XMLExtensions.TryLoadXml(ClientPermissionsFile);
|
|
foreach (XElement clientElement in doc.Root.Elements())
|
|
{
|
|
string clientName = clientElement.GetAttributeString("name", "");
|
|
string clientIP = clientElement.GetAttributeString("ip", "");
|
|
string steamIdStr = clientElement.GetAttributeString("steamid", "");
|
|
|
|
if (string.IsNullOrWhiteSpace(clientName))
|
|
{
|
|
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - all clients must have a name and an IP address.");
|
|
continue;
|
|
}
|
|
if (string.IsNullOrWhiteSpace(clientIP) && string.IsNullOrWhiteSpace(steamIdStr))
|
|
{
|
|
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - all clients must have an IP address or a Steam ID.");
|
|
continue;
|
|
}
|
|
|
|
string permissionsStr = clientElement.GetAttributeString("permissions", "");
|
|
ClientPermissions permissions = Networking.ClientPermissions.None;
|
|
if (permissionsStr.ToLowerInvariant() == "all")
|
|
{
|
|
foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions)))
|
|
{
|
|
permissions |= permission;
|
|
}
|
|
}
|
|
else if (!Enum.TryParse(permissionsStr, out permissions))
|
|
{
|
|
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - \"" + permissionsStr + "\" is not a valid client permission.");
|
|
continue;
|
|
}
|
|
|
|
List<DebugConsole.Command> permittedCommands = new List<DebugConsole.Command>();
|
|
if (permissions.HasFlag(Networking.ClientPermissions.ConsoleCommands))
|
|
{
|
|
foreach (XElement commandElement in clientElement.Elements())
|
|
{
|
|
if (commandElement.Name.ToString().ToLowerInvariant() != "command") continue;
|
|
|
|
string commandName = commandElement.GetAttributeString("name", "");
|
|
DebugConsole.Command command = DebugConsole.FindCommand(commandName);
|
|
if (command == null)
|
|
{
|
|
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - \"" + commandName + "\" is not a valid console command.");
|
|
continue;
|
|
}
|
|
|
|
permittedCommands.Add(command);
|
|
}
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(steamIdStr))
|
|
{
|
|
if (ulong.TryParse(steamIdStr, out ulong steamID))
|
|
{
|
|
ClientPermissions.Add(new SavedClientPermission(clientName, steamID, permissions, permittedCommands));
|
|
}
|
|
else
|
|
{
|
|
DebugConsole.ThrowError("Error in " + ClientPermissionsFile + " - \"" + steamIdStr + "\" is not a valid Steam ID.");
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ClientPermissions.Add(new SavedClientPermission(clientName, clientIP, permissions, permittedCommands));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Method for loading old .txt client permission files to provide backwards compatibility
|
|
/// </summary>
|
|
private void LoadClientPermissionsOld(string file)
|
|
{
|
|
if (!File.Exists(file)) return;
|
|
|
|
string[] lines;
|
|
try
|
|
{
|
|
lines = File.ReadAllLines(file);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
DebugConsole.ThrowError("Failed to open client permission file " + ClientPermissionsFile, e);
|
|
return;
|
|
}
|
|
|
|
ClientPermissions.Clear();
|
|
|
|
foreach (string line in lines)
|
|
{
|
|
string[] separatedLine = line.Split('|');
|
|
if (separatedLine.Length < 3) continue;
|
|
|
|
string name = string.Join("|", separatedLine.Take(separatedLine.Length - 2));
|
|
string ip = separatedLine[separatedLine.Length - 2];
|
|
|
|
ClientPermissions permissions = Networking.ClientPermissions.None;
|
|
if (Enum.TryParse(separatedLine.Last(), out permissions))
|
|
{
|
|
ClientPermissions.Add(new SavedClientPermission(name, ip, permissions, new List<DebugConsole.Command>()));
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SaveClientPermissions()
|
|
{
|
|
//delete old client permission file
|
|
if (File.Exists("Data/clientpermissions.txt"))
|
|
{
|
|
File.Delete("Data/clientpermissions.txt");
|
|
}
|
|
|
|
GameServer.Log("Saving client permissions", ServerLog.MessageType.ServerMessage);
|
|
|
|
XDocument doc = new XDocument(new XElement("ClientPermissions"));
|
|
|
|
foreach (SavedClientPermission clientPermission in ClientPermissions)
|
|
{
|
|
XElement clientElement = new XElement("Client",
|
|
new XAttribute("name", clientPermission.Name),
|
|
new XAttribute("permissions", clientPermission.Permissions.ToString()));
|
|
|
|
if (clientPermission.SteamID > 0)
|
|
{
|
|
clientElement.Add(new XAttribute("steamid", clientPermission.SteamID));
|
|
}
|
|
else
|
|
{
|
|
clientElement.Add(new XAttribute("ip", clientPermission.IP));
|
|
}
|
|
|
|
if (clientPermission.Permissions.HasFlag(Barotrauma.Networking.ClientPermissions.ConsoleCommands))
|
|
{
|
|
foreach (DebugConsole.Command command in clientPermission.PermittedCommands)
|
|
{
|
|
clientElement.Add(new XElement("command", new XAttribute("name", command.names[0])));
|
|
}
|
|
}
|
|
|
|
doc.Root.Add(clientElement);
|
|
}
|
|
|
|
try
|
|
{
|
|
XmlWriterSettings settings = new XmlWriterSettings();
|
|
settings.Indent = true;
|
|
settings.NewLineOnAttributes = true;
|
|
|
|
using (var writer = XmlWriter.Create(ClientPermissionsFile, settings))
|
|
{
|
|
doc.Save(writer);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
DebugConsole.ThrowError("Saving client permissions to " + ClientPermissionsFile + " failed", e);
|
|
}
|
|
}
|
|
}
|
|
}
|