mirror of
https://github.com/tribufu/ServerManagers
synced 2026-05-18 09:35:48 +00:00
source code checkin
This commit is contained in:
parent
5f8fb2c825
commit
7e57b72e35
675 changed files with 168433 additions and 0 deletions
14
src/ARKServerManager/Lib/Events/ProfileEventArgs.cs
Normal file
14
src/ARKServerManager/Lib/Events/ProfileEventArgs.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public class ProfileEventArgs : EventArgs
|
||||
{
|
||||
public ProfileEventArgs(ServerProfile profile)
|
||||
{
|
||||
Profile = profile;
|
||||
}
|
||||
|
||||
public ServerProfile Profile;
|
||||
}
|
||||
}
|
||||
410
src/ARKServerManager/Lib/GameData.cs
Normal file
410
src/ARKServerManager/Lib/GameData.cs
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Enums;
|
||||
using ServerManagerTool.Lib.ViewModel;
|
||||
using ServerManagerTool.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using WPFSharp.Globalizer;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public static class GameData
|
||||
{
|
||||
public const string MOD_ALL = "All";
|
||||
public const string MOD_UNKNOWN = "Unknown";
|
||||
|
||||
public static string MainDataFolder = Path.Combine(Environment.CurrentDirectory, Config.Default.GameDataDir);
|
||||
public static string UserDataFolder = Path.Combine(Config.Default.DataDir, Config.Default.GameDataDir);
|
||||
|
||||
public static int DefaultMaxExperiencePointsDino = 10;
|
||||
public static int DefaultMaxExperiencePointsPlayer = 5;
|
||||
|
||||
private static MainGameData gameData = null;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
// read static game data
|
||||
GameDataUtils.ReadAllData(out gameData, MainDataFolder, Config.Default.GameDataExtension, Config.Default.GameDataApplication);
|
||||
|
||||
// read user game data
|
||||
MainGameData userGameData = new MainGameData();
|
||||
if (!UserDataFolder.Equals(MainDataFolder, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
GameDataUtils.ReadAllData(out userGameData, UserDataFolder, Config.Default.GameDataExtension, Config.Default.GameDataApplication, true);
|
||||
}
|
||||
|
||||
// creatures
|
||||
gameData.Creatures.AddRange(userGameData.Creatures);
|
||||
|
||||
dinoSpawns = gameData.Creatures.ConvertAll(item => new DinoSpawn { ClassName = item.ClassName, Mod = item.Mod, KnownDino = true, DinoNameTag = item.NameTag }).ToArray();
|
||||
dinoMultipliers = gameData.Creatures.ConvertAll(item => new ClassMultiplier { ClassName = item.ClassName }).ToArray();
|
||||
|
||||
// engrams
|
||||
gameData.Engrams.AddRange(userGameData.Engrams);
|
||||
|
||||
engrams = gameData.Engrams.ConvertAll(item => new Engram { EngramClassName = item.ClassName, EngramLevelRequirement = item.Level, EngramPointsCost = item.Points, Mod = item.Mod, KnownEngram = true, IsTekgram = item.IsTekGram }).ToArray();
|
||||
|
||||
// items
|
||||
gameData.Items.AddRange(userGameData.Items);
|
||||
|
||||
items = gameData.Items.ConvertAll(item => new PrimalItem { ClassName = item.ClassName, Mod = item.Mod, KnownItem = true, Category = item.Category }).ToArray();
|
||||
|
||||
// resources
|
||||
resourceMultipliers = gameData.Items.Where(item => item.IsHarvestable).ToList().ConvertAll(item => new ResourceClassMultiplier { ClassName = item.ClassName, Mod = item.Mod, KnownResource = true }).ToArray();
|
||||
|
||||
// map spawners
|
||||
gameData.MapSpawners.AddRange(userGameData.MapSpawners);
|
||||
|
||||
mapSpawners = gameData.MapSpawners.ConvertAll(item => new MapSpawner { ClassName = item.ClassName, Mod = item.Mod, KnownSpawner = true }).ToArray();
|
||||
|
||||
// supply crates
|
||||
gameData.SupplyCrates.AddRange(userGameData.SupplyCrates);
|
||||
|
||||
var crates = gameData.SupplyCrates.ConvertAll(item => new SupplyCrate { ClassName = item.ClassName, Mod = item.Mod, KnownSupplyCrate = true });
|
||||
|
||||
// inventories
|
||||
gameData.Inventories.AddRange(userGameData.Inventories);
|
||||
|
||||
crates.AddRange(gameData.Inventories.ConvertAll(item => new SupplyCrate { ClassName = item.ClassName, Mod = item.Mod, KnownSupplyCrate = true }));
|
||||
|
||||
supplyCrates = crates.ToArray();
|
||||
|
||||
// game maps
|
||||
gameData.GameMaps.AddRange(userGameData.GameMaps);
|
||||
|
||||
if (gameData.GameMaps.Count > 0)
|
||||
{
|
||||
var maps1 = gameMaps.ToList();
|
||||
maps1.AddRange(gameData.GameMaps.Where(item => !item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
|
||||
var maps2 = gameMapsSotF.ToList();
|
||||
maps2.AddRange(gameData.GameMaps.Where(item => item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
|
||||
|
||||
gameMaps = maps1.ToArray();
|
||||
gameMapsSotF = maps2.ToArray();
|
||||
}
|
||||
|
||||
// total conversion mods
|
||||
gameData.Mods.AddRange(userGameData.Mods);
|
||||
|
||||
if (gameData.Mods.Count > 0)
|
||||
{
|
||||
var mods1 = totalConversions.ToList();
|
||||
mods1.AddRange(gameData.Mods.Where(item => !item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
|
||||
var mods2 = totalConversionsSotF.ToList();
|
||||
mods2.AddRange(gameData.Mods.Where(item => item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.ClassName, DisplayMember = item.Description }));
|
||||
|
||||
totalConversions = mods1.ToArray();
|
||||
totalConversionsSotF = mods2.ToArray();
|
||||
}
|
||||
|
||||
// creature levels
|
||||
if (userGameData.CreatureLevels.Count > 0)
|
||||
gameData.CreatureLevels = userGameData.CreatureLevels;
|
||||
|
||||
if (gameData.CreatureLevels.Count > 0)
|
||||
{
|
||||
levelsDino = gameData.CreatureLevels.ConvertAll(item => new Level { XPRequired = item.XPRequired }).ToArray();
|
||||
DefaultMaxExperiencePointsDino = levelsDino.Max(l => l.XPRequired) + 1;
|
||||
}
|
||||
|
||||
// player levels
|
||||
if (userGameData.PlayerLevels.Count > 0)
|
||||
gameData.PlayerLevels = userGameData.PlayerLevels;
|
||||
|
||||
LevelsPlayerAdditional = userGameData.PlayerAdditionalLevels;
|
||||
|
||||
if (gameData.PlayerLevels.Count > 0)
|
||||
{
|
||||
levelsPlayer = gameData.PlayerLevels.ConvertAll(item => new Level { EngramPoints = item.EngramPoints, XPRequired = item.XPRequired }).ToArray();
|
||||
DefaultMaxExperiencePointsPlayer = levelsPlayer.Max(l => l.XPRequired) + 1;
|
||||
}
|
||||
|
||||
if (gameData.PlayerAdditionalLevels > LevelsPlayerAdditional)
|
||||
LevelsPlayerAdditional = gameData.PlayerAdditionalLevels;
|
||||
|
||||
// branches
|
||||
gameData.Branches.AddRange(userGameData.Branches);
|
||||
|
||||
if (gameData.Branches.Count > 0)
|
||||
{
|
||||
var branches1 = branches.ToList();
|
||||
branches1.AddRange(gameData.Branches.Where(item => !item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.BranchName, DisplayMember = item.Description }));
|
||||
var branches2 = branchesSotF.ToList();
|
||||
branches2.AddRange(gameData.Branches.Where(item => item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.BranchName, DisplayMember = item.Description }));
|
||||
|
||||
branches = branches1.ToArray();
|
||||
branchesSotF = branches2.ToArray();
|
||||
}
|
||||
|
||||
// events
|
||||
gameData.Events.AddRange(userGameData.Events);
|
||||
|
||||
if (gameData.Events.Count > 0)
|
||||
{
|
||||
var events1 = events.ToList();
|
||||
events1.AddRange(gameData.Events.Where(item => !item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.EventName, DisplayMember = item.Description }));
|
||||
var events2 = eventsSotF.ToList();
|
||||
events2.AddRange(gameData.Events.Where(item => item.IsSotF).ToList().ConvertAll(item => new ComboBoxItem { ValueMember = item.EventName, DisplayMember = item.Description }));
|
||||
|
||||
events = events1.ToArray();
|
||||
eventsSotF = events2.ToArray();
|
||||
}
|
||||
|
||||
// official mods
|
||||
gameData.OfficialMods.AddRange(userGameData.OfficialMods);
|
||||
|
||||
if (gameData.OfficialMods.Count > 0)
|
||||
{
|
||||
ModUtils.AddOfficialMods(gameData.OfficialMods.Where(m => !string.IsNullOrWhiteSpace(m.ModId)).Select(m => m.ModId));
|
||||
}
|
||||
}
|
||||
|
||||
public static string FriendlyNameForClass(string className, bool returnNullIfNotFound = false) => string.IsNullOrWhiteSpace(className) ? (returnNullIfNotFound ? null : string.Empty) : GlobalizedApplication.Instance.GetResourceString(className) ?? (returnNullIfNotFound ? null : className);
|
||||
|
||||
#region Creatures
|
||||
private static DinoSpawn[] dinoSpawns = new DinoSpawn[0];
|
||||
|
||||
public static IEnumerable<DinoSpawn> GetDinoSpawns() => dinoSpawns.Select(d => d.Duplicate<DinoSpawn>());
|
||||
|
||||
public static IEnumerable<NPCReplacement> GetNPCReplacements() => dinoSpawns.Select(d => new NPCReplacement() { FromClassName = d.ClassName, ToClassName = d.ClassName });
|
||||
|
||||
public static bool IsSpawnableForClass(string className) => gameData?.Creatures?.FirstOrDefault(c => c.ClassName.Equals(className))?.IsSpawnable ?? true;
|
||||
|
||||
public static DinoTamable IsTameableForClass(string className) => gameData?.Creatures?.FirstOrDefault(c => c.ClassName.Equals(className))?.IsTameable ?? DinoTamable.True;
|
||||
|
||||
public static string NameTagForClass(string className, bool returnEmptyIfNotFound = false) => gameData?.Creatures?.FirstOrDefault(c => c.ClassName.Equals(className))?.NameTag ?? (returnEmptyIfNotFound ? string.Empty : className);
|
||||
|
||||
public static string FriendlyCreatureNameForClass(string className, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(className) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(className) ?? gameData?.Creatures?.FirstOrDefault(i => i.ClassName.Equals(className))?.Description ?? (returnEmptyIfNotFound ? string.Empty : className);
|
||||
|
||||
private static ClassMultiplier[] dinoMultipliers = new ClassMultiplier[0];
|
||||
|
||||
public static IEnumerable<ClassMultiplier> GetDinoMultipliers() => dinoMultipliers.Select(d => d.Duplicate<ClassMultiplier>());
|
||||
#endregion
|
||||
|
||||
#region Engrams
|
||||
private static Engram[] engrams = new Engram[0];
|
||||
|
||||
public static IEnumerable<Engram> GetEngrams() => engrams.Select(d => d.Duplicate());
|
||||
|
||||
public static IEnumerable<EngramEntry> GetEngramEntries() => engrams.Select(d => new EngramEntry() { EngramClassName = d.EngramClassName, EngramLevelRequirement = d.EngramLevelRequirement, EngramPointsCost = d.EngramPointsCost });
|
||||
|
||||
public static Engram GetEngramForClass(string className) => engrams.FirstOrDefault(e => e.EngramClassName.Equals(className));
|
||||
|
||||
public static bool HasEngramForClass(string className) => engrams.Any(e => e.EngramClassName.Equals(className));
|
||||
|
||||
public static bool IsTekgram(string className) => engrams.Any(e => e.EngramClassName.Equals(className) && e.IsTekgram);
|
||||
|
||||
public static string FriendlyEngramNameForClass(string className, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(className) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(className) ?? gameData?.Engrams?.FirstOrDefault(i => i.ClassName.Equals(className))?.Description ?? (returnEmptyIfNotFound ? string.Empty : className);
|
||||
#endregion
|
||||
|
||||
#region Items
|
||||
private static PrimalItem[] items = new PrimalItem[0];
|
||||
|
||||
public static IEnumerable<PrimalItem> GetItems() => items.Select(d => d.Duplicate());
|
||||
|
||||
public static PrimalItem GetItemForClass(string className) => items.FirstOrDefault(e => e.ClassName.Equals(className));
|
||||
|
||||
public static bool HasItemForClass(string className) => items.Any(e => e.ClassName.Equals(className));
|
||||
|
||||
public static string FriendlyItemNameForClass(string className, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(className) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(className) ?? gameData?.Items?.FirstOrDefault(i => i.ClassName.Equals(className))?.Description ?? (returnEmptyIfNotFound ? string.Empty : className);
|
||||
#endregion
|
||||
|
||||
#region Resources
|
||||
private static ResourceClassMultiplier[] resourceMultipliers = new ResourceClassMultiplier[0];
|
||||
|
||||
public static IEnumerable<ResourceClassMultiplier> GetResourceMultipliers() => resourceMultipliers.Select(d => d.Duplicate<ResourceClassMultiplier>());
|
||||
|
||||
public static ResourceClassMultiplier GetResourceMultiplierForClass(string className) => resourceMultipliers.FirstOrDefault(e => e.ClassName.Equals(className));
|
||||
|
||||
public static bool HasResourceMultiplierForClass(string className) => resourceMultipliers.Any(e => e.ClassName.Equals(className));
|
||||
|
||||
public static string FriendlyResourceNameForClass(string className) => string.IsNullOrWhiteSpace(className) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(className) ?? gameData?.Items?.FirstOrDefault(i => i.ClassName.Equals(className) && i.IsHarvestable)?.Description ?? className;
|
||||
#endregion
|
||||
|
||||
#region Map Spawners
|
||||
private static MapSpawner[] mapSpawners = new MapSpawner[0];
|
||||
|
||||
public static IEnumerable<MapSpawner> GetMapSpawners() => mapSpawners.Select(d => d.Duplicate());
|
||||
|
||||
public static MapSpawner GetMapSpawnerForClass(string className) => mapSpawners.FirstOrDefault(e => e.ClassName.Equals(className));
|
||||
|
||||
public static bool HasMapSpawnerForClass(string className) => mapSpawners.Any(e => e.ClassName.Equals(className));
|
||||
|
||||
public static string FriendlyMapSpawnerNameForClass(string className, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(className) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(className) ?? gameData?.MapSpawners?.FirstOrDefault(i => i.ClassName.Equals(className))?.Description ?? (returnEmptyIfNotFound ? string.Empty : className);
|
||||
#endregion
|
||||
|
||||
#region Supply Crates
|
||||
private static SupplyCrate[] supplyCrates = new SupplyCrate[0];
|
||||
|
||||
public static IEnumerable<SupplyCrate> GetSupplyCrates() => supplyCrates.Select(d => d.Duplicate());
|
||||
|
||||
public static SupplyCrate GetSupplyCrateForClass(string className) => supplyCrates.FirstOrDefault(e => e.ClassName.Equals(className));
|
||||
|
||||
public static bool HasSupplyCrateForClass(string className) => supplyCrates.Any(e => e.ClassName.Equals(className));
|
||||
|
||||
public static string FriendlySupplyCrateNameForClass(string className, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(className) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(className) ?? gameData?.SupplyCrates?.FirstOrDefault(i => i.ClassName.Equals(className))?.Description ?? (returnEmptyIfNotFound ? string.Empty : className);
|
||||
#endregion
|
||||
|
||||
#region Game Maps
|
||||
private static ComboBoxItem[] gameMaps = new[]
|
||||
{
|
||||
new ComboBoxItem { ValueMember="", DisplayMember="" },
|
||||
};
|
||||
|
||||
public static IEnumerable<ComboBoxItem> GetGameMaps() => gameMaps.Select(d => d.Duplicate());
|
||||
|
||||
public static string FriendlyMapNameForClass(string className, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(className) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(className) ?? gameData?.GameMaps?.FirstOrDefault(i => i.ClassName.Equals(className) && !i.IsSotF)?.Description ?? (returnEmptyIfNotFound ? string.Empty : className);
|
||||
|
||||
private static ComboBoxItem[] gameMapsSotF = new[]
|
||||
{
|
||||
new ComboBoxItem { ValueMember="", DisplayMember="" },
|
||||
};
|
||||
|
||||
public static IEnumerable<ComboBoxItem> GetGameMapsSotF() => gameMapsSotF.Select(d => d.Duplicate());
|
||||
|
||||
public static string FriendlyMapSotFNameForClass(string className, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(className) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(className) ?? gameData?.GameMaps?.FirstOrDefault(i => i.ClassName.Equals(className) && i.IsSotF)?.Description ?? (returnEmptyIfNotFound ? string.Empty : className);
|
||||
#endregion
|
||||
|
||||
#region Total Conversions
|
||||
private static ComboBoxItem[] totalConversions = new[]
|
||||
{
|
||||
new ComboBoxItem { ValueMember="", DisplayMember="" },
|
||||
};
|
||||
|
||||
public static IEnumerable<ComboBoxItem> GetTotalConversions() => totalConversions.Select(d => d.Duplicate());
|
||||
|
||||
public static string FriendlyTotalConversionNameForClass(string className, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(className) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(className) ?? gameData?.Mods?.FirstOrDefault(i => i.ClassName.Equals(className) && !i.IsSotF)?.Description ?? (returnEmptyIfNotFound ? string.Empty : className);
|
||||
|
||||
private static ComboBoxItem[] totalConversionsSotF = new[]
|
||||
{
|
||||
new ComboBoxItem { ValueMember="", DisplayMember="" },
|
||||
};
|
||||
|
||||
public static IEnumerable<ComboBoxItem> GetTotalConversionsSotF() => totalConversionsSotF.Select(d => d.Duplicate());
|
||||
|
||||
public static string FriendlyTotalConversionSotFNameForClass(string className, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(className) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(className) ?? gameData?.Mods?.FirstOrDefault(i => i.ClassName.Equals(className) && i.IsSotF)?.Description ?? (returnEmptyIfNotFound ? string.Empty : className);
|
||||
#endregion
|
||||
|
||||
#region Stats Multipliers
|
||||
internal static IEnumerable<float> GetPerLevelStatsMultipliers_DinoWild()
|
||||
{
|
||||
return new float[] { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
}
|
||||
|
||||
internal static IEnumerable<float> GetPerLevelStatsMultipliers_DinoTamed()
|
||||
{
|
||||
return new float[] { 0.2f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.17f, 1.0f, 1.0f, 1.0f };
|
||||
}
|
||||
|
||||
internal static IEnumerable<float> GetPerLevelStatsMultipliers_DinoTamedAdd()
|
||||
{
|
||||
return new float[] { 0.14f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.14f, 1.0f, 1.0f, 1.0f };
|
||||
}
|
||||
|
||||
internal static IEnumerable<float> GetPerLevelStatsMultipliers_DinoTamedAffinity()
|
||||
{
|
||||
return new float[] { 0.44f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.44f, 1.0f, 1.0f, 1.0f };
|
||||
}
|
||||
|
||||
internal static IEnumerable<float> GetBaseStatMultipliers_Player()
|
||||
{
|
||||
return new float[] { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
}
|
||||
|
||||
internal static IEnumerable<float> GetPerLevelStatsMultipliers_Player()
|
||||
{
|
||||
return new float[] { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
}
|
||||
|
||||
internal static bool[] GetStatMultiplierInclusions_DinoWildPerLevel()
|
||||
{
|
||||
return new bool[] { true, true, false, true, true, false, true, true, true, true, false, true };
|
||||
}
|
||||
|
||||
internal static bool[] GetStatMultiplierInclusions_DinoTamedPerLevel()
|
||||
{
|
||||
return new bool[] { true, true, false, true, true, false, true, true, true, true, false, true };
|
||||
}
|
||||
|
||||
internal static bool[] GetStatMultiplierInclusions_DinoTamedAdd()
|
||||
{
|
||||
return new bool[] { true, true, true, true, true, true, true, true, true, true, true, true };
|
||||
}
|
||||
|
||||
internal static bool[] GetStatMultiplierInclusions_DinoTamedAffinity()
|
||||
{
|
||||
return new bool[] { true, true, true, true, true, true, true, true, true, true, true, true };
|
||||
}
|
||||
|
||||
internal static bool[] GetStatMultiplierInclusions_PlayerBase()
|
||||
{
|
||||
return new bool[] { true, true, true, true, true, true, true, true, true, true, true, true };
|
||||
}
|
||||
|
||||
internal static bool[] GetStatMultiplierInclusions_PlayerPerLevel()
|
||||
{
|
||||
return new bool[] { true, true, false, true, true, true, true, true, true, true, true, true };
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Levels
|
||||
private static Level[] levelsDino = new[]
|
||||
{
|
||||
new Level { XPRequired=10 },
|
||||
};
|
||||
|
||||
private static Level[] levelsPlayer = new[]
|
||||
{
|
||||
new Level { XPRequired=5, EngramPoints=8 },
|
||||
};
|
||||
|
||||
public static IEnumerable<Level> LevelsDino => levelsDino.Select(l => l.Duplicate());
|
||||
|
||||
public static IEnumerable<Level> LevelsPlayer => levelsPlayer.Select(l => l.Duplicate());
|
||||
|
||||
public static int LevelsPlayerAdditional = 0;
|
||||
#endregion
|
||||
|
||||
#region Branches
|
||||
private static ComboBoxItem[] branches = new[]
|
||||
{
|
||||
new ComboBoxItem { ValueMember="", DisplayMember=FriendlyNameForClass(Config.Default.DefaultServerBranchName) },
|
||||
};
|
||||
|
||||
public static IEnumerable<ComboBoxItem> GetBranches() => branches.Select(d => d.Duplicate());
|
||||
|
||||
public static string FriendlyBranchName(string branchName, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(branchName) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(branchName) ?? gameData?.Branches?.FirstOrDefault(i => i.BranchName.Equals(branchName) && !i.IsSotF)?.Description ?? (returnEmptyIfNotFound ? string.Empty : branchName);
|
||||
|
||||
private static ComboBoxItem[] branchesSotF = new[]
|
||||
{
|
||||
new ComboBoxItem { ValueMember="", DisplayMember=FriendlyNameForClass(Config.Default.DefaultServerBranchName) },
|
||||
};
|
||||
|
||||
public static IEnumerable<ComboBoxItem> GetBranchesSotF() => branchesSotF.Select(d => d.Duplicate());
|
||||
|
||||
public static string FriendlyBranchSotFName(string branchName, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(branchName) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(branchName) ?? gameData?.Branches?.FirstOrDefault(i => i.BranchName.Equals(branchName) && i.IsSotF)?.Description ?? (returnEmptyIfNotFound ? string.Empty : branchName);
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
private static ComboBoxItem[] events = new[]
|
||||
{
|
||||
new ComboBoxItem { ValueMember="", DisplayMember=string.Empty },
|
||||
};
|
||||
|
||||
public static IEnumerable<ComboBoxItem> GetEvents() => events.Select(d => d.Duplicate());
|
||||
|
||||
public static string FriendlyEventName(string eventName, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(eventName) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(eventName) ?? gameData?.Events?.FirstOrDefault(i => i.EventName.Equals(eventName) && !i.IsSotF)?.Description ?? (returnEmptyIfNotFound ? string.Empty : eventName);
|
||||
|
||||
private static ComboBoxItem[] eventsSotF = new[]
|
||||
{
|
||||
new ComboBoxItem { ValueMember="", DisplayMember=string.Empty },
|
||||
};
|
||||
|
||||
public static IEnumerable<ComboBoxItem> GetEventsSotF() => eventsSotF.Select(d => d.Duplicate());
|
||||
|
||||
public static string FriendlyEventSotFName(string eventName, bool returnEmptyIfNotFound = false) => string.IsNullOrWhiteSpace(eventName) ? string.Empty : GlobalizedApplication.Instance.GetResourceString(eventName) ?? gameData?.Events?.FirstOrDefault(i => i.EventName.Equals(eventName) && i.IsSotF)?.Description ?? (returnEmptyIfNotFound ? string.Empty : eventName);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
46
src/ARKServerManager/Lib/Model/ClassMultiplier.cs
Normal file
46
src/ARKServerManager/Lib/Model/ClassMultiplier.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
using ServerManagerTool.Common.Attibutes;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
public class ClassMultiplier : AggregateIniValue
|
||||
{
|
||||
public const float DEFAULT_MULTIPLIER = 1.0f;
|
||||
|
||||
public static readonly DependencyProperty ClassNameProperty = DependencyProperty.Register(nameof(ClassName), typeof(string), typeof(ClassMultiplier), new PropertyMetadata(string.Empty));
|
||||
public static readonly DependencyProperty MultiplierProperty = DependencyProperty.Register(nameof(Multiplier), typeof(float), typeof(ClassMultiplier), new PropertyMetadata(DEFAULT_MULTIPLIER));
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public string ClassName
|
||||
{
|
||||
get { return (string)GetValue(ClassNameProperty); }
|
||||
set { SetValue(ClassNameProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float Multiplier
|
||||
{
|
||||
get { return (float)GetValue(MultiplierProperty); }
|
||||
set { SetValue(MultiplierProperty, value); }
|
||||
}
|
||||
|
||||
public virtual string DisplayName => GameData.FriendlyNameForClass(ClassName);
|
||||
|
||||
public static ClassMultiplier FromINIValue(string iniValue)
|
||||
{
|
||||
var newSpawn = new ClassMultiplier();
|
||||
newSpawn.InitializeFromINIValue(iniValue);
|
||||
return newSpawn;
|
||||
}
|
||||
|
||||
public override string GetSortKey() => GameData.FriendlyNameForClass(this.ClassName);
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other) => String.Equals(this.ClassName, ((ClassMultiplier)other).ClassName, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
123
src/ARKServerManager/Lib/Model/CraftingOverride.cs
Normal file
123
src/ARKServerManager/Lib/Model/CraftingOverride.cs
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
using ServerManagerTool.Common.Attibutes;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
public class CraftingOverride : AggregateIniValue
|
||||
{
|
||||
public CraftingOverride()
|
||||
{
|
||||
BaseCraftingResourceRequirements = new AggregateIniValueList<CraftingResourceRequirement>(null, null);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemClassStringProperty = DependencyProperty.Register(nameof(ItemClassString), typeof(string), typeof(CraftingOverride), new PropertyMetadata(string.Empty));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public string ItemClassString
|
||||
{
|
||||
get { return (string)GetValue(ItemClassStringProperty); }
|
||||
set { SetValue(ItemClassStringProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty BaseCraftingResourceRequirementsProperty = DependencyProperty.Register(nameof(BaseCraftingResourceRequirements), typeof(AggregateIniValueList<CraftingResourceRequirement>), typeof(CraftingOverride), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(ValueWithinBrackets = true, ListValueWithinBrackets = true)]
|
||||
public AggregateIniValueList<CraftingResourceRequirement> BaseCraftingResourceRequirements
|
||||
{
|
||||
get { return (AggregateIniValueList<CraftingResourceRequirement>)GetValue(BaseCraftingResourceRequirementsProperty); }
|
||||
set { SetValue(BaseCraftingResourceRequirementsProperty, value); }
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return;
|
||||
|
||||
var kvPair = value.Split(new[] { '=' }, 2);
|
||||
var kvValue = kvPair[1].Trim(' ');
|
||||
if (kvValue.StartsWith("("))
|
||||
kvValue = kvValue.Substring(1);
|
||||
if (kvValue.EndsWith(")"))
|
||||
kvValue = kvValue.Substring(0, kvValue.Length - 1);
|
||||
|
||||
base.FromComplexINIValue(kvValue);
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
return base.ToComplexINIValue(true);
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlyItemNameForClass(ItemClassString);
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(ItemClassString) && BaseCraftingResourceRequirements.Count > 0;
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class CraftingResourceRequirement : AggregateIniValue
|
||||
{
|
||||
public static readonly DependencyProperty ResourceItemTypeStringProperty = DependencyProperty.Register(nameof(ResourceItemTypeString), typeof(string), typeof(CraftingResourceRequirement), new PropertyMetadata(string.Empty));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public string ResourceItemTypeString
|
||||
{
|
||||
get { return (string)GetValue(ResourceItemTypeStringProperty); }
|
||||
set { SetValue(ResourceItemTypeStringProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty BaseResourceRequirementProperty = DependencyProperty.Register(nameof(BaseResourceRequirement), typeof(float), typeof(CraftingResourceRequirement), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float BaseResourceRequirement
|
||||
{
|
||||
get { return (float)GetValue(BaseResourceRequirementProperty); }
|
||||
set { SetValue(BaseResourceRequirementProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty CraftingRequireExactResourceTypeProperty = DependencyProperty.Register(nameof(CraftingRequireExactResourceType), typeof(bool), typeof(CraftingResourceRequirement), new PropertyMetadata(false));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "bCraftingRequireExactResourceType")]
|
||||
public bool CraftingRequireExactResourceType
|
||||
{
|
||||
get { return (bool)GetValue(CraftingRequireExactResourceTypeProperty); }
|
||||
set { SetValue(CraftingRequireExactResourceTypeProperty, value); }
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
base.FromComplexINIValue(value);
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
return base.ToComplexINIValue(false);
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlyItemNameForClass(ResourceItemTypeString);
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(ResourceItemTypeString);
|
||||
}
|
||||
}
|
||||
101
src/ARKServerManager/Lib/Model/DinoSpawn.cs
Normal file
101
src/ARKServerManager/Lib/Model/DinoSpawn.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
using ServerManagerTool.Common.Attibutes;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Enums;
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
public class DinoSpawn : AggregateIniValue
|
||||
{
|
||||
public const bool DEFAULT_OVERRIDE_SPAWN_LIMIT_PERCENTAGE = true;
|
||||
public const float DEFAULT_SPAWN_LIMIT_PERCENTAGE = ClassMultiplier.DEFAULT_MULTIPLIER;
|
||||
public const float DEFAULT_SPAWN_WEIGHT_MULTIPLIER = ClassMultiplier.DEFAULT_MULTIPLIER;
|
||||
|
||||
public static readonly DependencyProperty ClassNameProperty = DependencyProperty.Register(nameof(ClassName), typeof(string), typeof(DinoSpawn), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty ModProperty = DependencyProperty.Register(nameof(Mod), typeof(string), typeof(DinoSpawn), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty KnownDinoProperty = DependencyProperty.Register(nameof(KnownDino), typeof(bool), typeof(DinoSpawn), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty DinoNameTagProperty = DependencyProperty.Register(nameof(DinoNameTag), typeof(string), typeof(DinoSpawn), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty OverrideSpawnLimitPercentageProperty = DependencyProperty.Register(nameof(OverrideSpawnLimitPercentage), typeof(bool), typeof(DinoSpawn), new PropertyMetadata(DEFAULT_OVERRIDE_SPAWN_LIMIT_PERCENTAGE));
|
||||
public static readonly DependencyProperty SpawnLimitPercentageProperty = DependencyProperty.Register(nameof(SpawnLimitPercentage), typeof(float), typeof(DinoSpawn), new PropertyMetadata(DEFAULT_SPAWN_LIMIT_PERCENTAGE));
|
||||
public static readonly DependencyProperty SpawnWeightMultiplierProperty = DependencyProperty.Register(nameof(SpawnWeightMultiplier), typeof(float), typeof(DinoSpawn), new PropertyMetadata(DEFAULT_SPAWN_WEIGHT_MULTIPLIER));
|
||||
|
||||
[DataMember]
|
||||
public string ClassName
|
||||
{
|
||||
get { return (string)GetValue(ClassNameProperty); }
|
||||
set { SetValue(ClassNameProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public string Mod
|
||||
{
|
||||
get { return (string)GetValue(ModProperty); }
|
||||
set { SetValue(ModProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public bool KnownDino
|
||||
{
|
||||
get { return (bool)GetValue(KnownDinoProperty); }
|
||||
set { SetValue(KnownDinoProperty, value); }
|
||||
}
|
||||
|
||||
[XmlElement(ElementName="Name")]
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public string DinoNameTag
|
||||
{
|
||||
get { return (string)GetValue(DinoNameTagProperty); }
|
||||
set { SetValue(DinoNameTagProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public bool OverrideSpawnLimitPercentage
|
||||
{
|
||||
get { return (bool)GetValue(OverrideSpawnLimitPercentageProperty); }
|
||||
set { SetValue(OverrideSpawnLimitPercentageProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float SpawnLimitPercentage
|
||||
{
|
||||
get { return (float)GetValue(SpawnLimitPercentageProperty); }
|
||||
set { SetValue(SpawnLimitPercentageProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float SpawnWeightMultiplier
|
||||
{
|
||||
get { return (float)GetValue(SpawnWeightMultiplierProperty); }
|
||||
set { SetValue(SpawnWeightMultiplierProperty, value); }
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlyCreatureNameForClass(ClassName);
|
||||
|
||||
public string DisplayMod => GameData.FriendlyNameForClass($"Mod_{Mod}", true) ?? Mod;
|
||||
|
||||
public static DinoSpawn FromINIValue(string iniValue)
|
||||
{
|
||||
var newSpawn = new DinoSpawn();
|
||||
newSpawn.InitializeFromINIValue(iniValue);
|
||||
return newSpawn;
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return this.DinoNameTag;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return String.Equals(this.DinoNameTag, ((DinoSpawn)other).DinoNameTag, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
91
src/ARKServerManager/Lib/Model/EngramAutoUnlock.cs
Normal file
91
src/ARKServerManager/Lib/Model/EngramAutoUnlock.cs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
using ServerManagerTool.Common.Attibutes;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public class EngramAutoUnlockList : AggregateIniValueList<EngramAutoUnlock>
|
||||
{
|
||||
public EngramAutoUnlockList(string aggregateValueName)
|
||||
: base(aggregateValueName, null)
|
||||
{
|
||||
}
|
||||
|
||||
public override void FromIniValues(IEnumerable<string> iniValues)
|
||||
{
|
||||
var items = iniValues?.Select(AggregateIniValue.FromINIValue<EngramAutoUnlock>).ToArray();
|
||||
|
||||
Clear();
|
||||
|
||||
var itemsToAdd = items.Where(i => !this.Any(e => e.IsEquivalent(i))).ToArray();
|
||||
AddRange(itemsToAdd);
|
||||
|
||||
var itemsToUpdate = items.Where(i => this.Any(e => e.IsEquivalent(i))).ToArray();
|
||||
foreach (var item in itemsToUpdate)
|
||||
{
|
||||
var e = this.FirstOrDefault(r => r.IsEquivalent(item));
|
||||
e.LevelToAutoUnlock = item.LevelToAutoUnlock;
|
||||
}
|
||||
|
||||
IsEnabled = (Count != 0);
|
||||
|
||||
Sort(AggregateIniValue.SortKeySelector);
|
||||
}
|
||||
|
||||
public override IEnumerable<string> ToIniValues()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(IniCollectionKey))
|
||||
return this.Where(d => d.ShouldSave()).Select(d => d.ToINIValue());
|
||||
|
||||
return this.Where(d => d.ShouldSave()).Select(d => $"{this.IniCollectionKey}={d.ToINIValue()}");
|
||||
}
|
||||
}
|
||||
|
||||
public class EngramAutoUnlock : AggregateIniValue
|
||||
{
|
||||
public static readonly DependencyProperty EngramClassNameProperty = DependencyProperty.Register(nameof(EngramClassName), typeof(string), typeof(EngramAutoUnlock), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty LevelToAutoUnlockProperty = DependencyProperty.Register(nameof(LevelToAutoUnlock), typeof(int), typeof(EngramAutoUnlock), new PropertyMetadata(0));
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public string EngramClassName
|
||||
{
|
||||
get { return (string)GetValue(EngramClassNameProperty); }
|
||||
set { SetValue(EngramClassNameProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public int LevelToAutoUnlock
|
||||
{
|
||||
get { return (int)GetValue(LevelToAutoUnlockProperty); }
|
||||
set { SetValue(LevelToAutoUnlockProperty, value); }
|
||||
}
|
||||
|
||||
public static EngramAutoUnlock FromINIValue(string iniValue)
|
||||
{
|
||||
var engramAutoUnlock = new EngramAutoUnlock();
|
||||
engramAutoUnlock.InitializeFromINIValue(iniValue);
|
||||
return engramAutoUnlock;
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return String.Equals(this.EngramClassName, ((EngramAutoUnlock)other).EngramClassName, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
return base.ToINIValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
128
src/ARKServerManager/Lib/Model/EngramEntry.cs
Normal file
128
src/ARKServerManager/Lib/Model/EngramEntry.cs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
using ServerManagerTool.Common.Attibutes;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
public class EngramEntryList : AggregateIniValueList<EngramEntry>
|
||||
{
|
||||
public EngramEntryList(string aggregateValueName)
|
||||
: base(aggregateValueName, null)
|
||||
{
|
||||
}
|
||||
|
||||
public override void FromIniValues(IEnumerable<string> iniValues)
|
||||
{
|
||||
var items = iniValues?.Select(AggregateIniValue.FromINIValue<EngramEntry>).ToArray();
|
||||
|
||||
Clear();
|
||||
|
||||
var itemsToAdd = items.Where(i => !this.Any(e => e.IsEquivalent(i))).ToArray();
|
||||
AddRange(itemsToAdd);
|
||||
|
||||
var itemsToUpdate = items.Where(i => this.Any(e => e.IsEquivalent(i))).ToArray();
|
||||
foreach (var item in itemsToUpdate)
|
||||
{
|
||||
var e = this.FirstOrDefault(r => r.IsEquivalent(item));
|
||||
e.EngramLevelRequirement = item.EngramLevelRequirement;
|
||||
e.EngramPointsCost = item.EngramPointsCost;
|
||||
e.EngramHidden = item.EngramHidden;
|
||||
e.RemoveEngramPreReq = item.RemoveEngramPreReq;
|
||||
}
|
||||
|
||||
IsEnabled = (Count != 0);
|
||||
|
||||
Sort(AggregateIniValue.SortKeySelector);
|
||||
}
|
||||
|
||||
public override IEnumerable<string> ToIniValues()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(IniCollectionKey))
|
||||
return this.Where(d => d.ShouldSave()).Select(d => d.ToINIValue());
|
||||
|
||||
return this.Where(d => d.ShouldSave()).Select(d => $"{this.IniCollectionKey}={d.ToINIValue()}");
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class EngramEntry : AggregateIniValue
|
||||
{
|
||||
public static readonly DependencyProperty EngramClassNameProperty = DependencyProperty.Register(nameof(EngramClassName), typeof(string), typeof(EngramEntry), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty EngramLevelRequirementProperty = DependencyProperty.Register(nameof(EngramLevelRequirement), typeof(int), typeof(EngramEntry), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty EngramPointsCostProperty = DependencyProperty.Register(nameof(EngramPointsCost), typeof(int), typeof(EngramEntry), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty EngramHiddenProperty = DependencyProperty.Register(nameof(EngramHidden), typeof(bool), typeof(EngramEntry), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty RemoveEngramPreReqProperty = DependencyProperty.Register(nameof(RemoveEngramPreReq), typeof(bool), typeof(EngramEntry), new PropertyMetadata(false));
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public string EngramClassName
|
||||
{
|
||||
get { return (string)GetValue(EngramClassNameProperty); }
|
||||
set { SetValue(EngramClassNameProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public int EngramLevelRequirement
|
||||
{
|
||||
get { return (int)GetValue(EngramLevelRequirementProperty); }
|
||||
set { SetValue(EngramLevelRequirementProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public int EngramPointsCost
|
||||
{
|
||||
get { return (int)GetValue(EngramPointsCostProperty); }
|
||||
set { SetValue(EngramPointsCostProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public bool EngramHidden
|
||||
{
|
||||
get { return (bool)GetValue(EngramHiddenProperty); }
|
||||
set { SetValue(EngramHiddenProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public bool RemoveEngramPreReq
|
||||
{
|
||||
get { return (bool)GetValue(RemoveEngramPreReqProperty); }
|
||||
set { SetValue(RemoveEngramPreReqProperty, value); }
|
||||
}
|
||||
|
||||
public static EngramEntry FromINIValue(string iniValue)
|
||||
{
|
||||
var engramEntry = new EngramEntry();
|
||||
engramEntry.InitializeFromINIValue(iniValue);
|
||||
return engramEntry;
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
base.InitializeFromINIValue(value);
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return String.Equals(this.EngramClassName, ((EngramEntry)other).EngramClassName, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
return base.ToINIValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
260
src/ARKServerManager/Lib/Model/Level.cs
Normal file
260
src/ARKServerManager/Lib/Model/Level.cs
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Diagnostics;
|
||||
using System.Xml.Serialization;
|
||||
using TinyCsvParser.Mapping;
|
||||
using System.Runtime.Serialization;
|
||||
using ServerManagerTool.Common.Model;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
public class LevelList : SortableObservableCollection<Level>
|
||||
{
|
||||
const bool WORKAROUND_FOR_ENGRAM_LIST = true;
|
||||
|
||||
public static readonly Regex XPRegex = new Regex(@"ExperiencePointsForLevel\[(?<level>\d*)]=(?<xp>\d*)", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture | RegexOptions.Compiled);
|
||||
public static readonly Regex EngramRegex = new Regex(@"OverridePlayerLevelEngramPoints=(?<points>\d*)", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture | RegexOptions.Compiled);
|
||||
|
||||
public static int AdditionalLevels = GameData.LevelsPlayerAdditional;
|
||||
|
||||
public void RemoveLevel(Level level)
|
||||
{
|
||||
base.Remove(level);
|
||||
UpdateTotals();
|
||||
}
|
||||
|
||||
public void AddRange(IEnumerable<Level> levels)
|
||||
{
|
||||
foreach (var level in levels)
|
||||
{
|
||||
base.Add(level);
|
||||
}
|
||||
|
||||
UpdateTotals();
|
||||
}
|
||||
|
||||
public void AddNewLevel(Level afterLevel)
|
||||
{
|
||||
AddNewLevel(afterLevel, 1);
|
||||
}
|
||||
|
||||
public void AddNewLevel(Level afterLevel, int xpIncrease)
|
||||
{
|
||||
var newLevel = new Level
|
||||
{
|
||||
LevelIndex = 0,
|
||||
XPRequired = afterLevel.XPRequired + xpIncrease,
|
||||
EngramPoints = afterLevel.EngramPoints
|
||||
};
|
||||
|
||||
base.Insert(base.IndexOf(afterLevel) + 1, newLevel);
|
||||
UpdateTotals();
|
||||
}
|
||||
|
||||
public void UpdateTotals()
|
||||
{
|
||||
int index = 0;
|
||||
int xpTotal = 0;
|
||||
int engramTotal = 0;
|
||||
foreach (var existingLevel in this.OrderBy(l => l.XPRequired).ToArray())
|
||||
{
|
||||
xpTotal += existingLevel.XPRequired;
|
||||
engramTotal += existingLevel.EngramPoints;
|
||||
|
||||
existingLevel.XPTotal = xpTotal;
|
||||
existingLevel.EngramTotal = engramTotal;
|
||||
|
||||
existingLevel.LevelIndex = index;
|
||||
existingLevel.ShowColored = index >= this.Count - AdditionalLevels;
|
||||
index++;
|
||||
}
|
||||
|
||||
base.Sort(f => f.LevelIndex);
|
||||
}
|
||||
|
||||
public string ToINIValueForXP()
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
builder.Append("LevelExperienceRampOverrides=(");
|
||||
builder.Append(String.Join(",", this.OrderBy(l => l.XPRequired).Select(l => l.GetINISubValueForXP())));
|
||||
builder.Append(')');
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public List<string> ToINIValuesForEngramPoints()
|
||||
{
|
||||
var entries = new List<string>();
|
||||
|
||||
|
||||
if (WORKAROUND_FOR_ENGRAM_LIST)
|
||||
{
|
||||
entries.Add(new Level().GetINIValueForEngramPointsEarned());
|
||||
}
|
||||
|
||||
foreach (var level in this.OrderBy(l => l.XPRequired))
|
||||
{
|
||||
entries.Add(level.GetINIValueForEngramPointsEarned());
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
public static LevelList FromINIValues(string xpValue, IEnumerable<string> engramValues = null)
|
||||
{
|
||||
var levels = new LevelList();
|
||||
var xpResult = XPRegex.Match(xpValue);
|
||||
var engramResult = engramValues == null ? null : EngramRegex.Match(String.Join(" ", engramValues));
|
||||
|
||||
if (WORKAROUND_FOR_ENGRAM_LIST)
|
||||
{
|
||||
if (engramResult != null)
|
||||
{
|
||||
engramResult = engramResult.NextMatch();
|
||||
}
|
||||
}
|
||||
|
||||
while (xpResult.Success && (engramValues == null || engramResult.Success))
|
||||
{
|
||||
int levelIndex;
|
||||
if (!int.TryParse(xpResult.Groups["level"].Value, out levelIndex))
|
||||
{
|
||||
Debug.WriteLine(String.Format("Invalid level index value: '{0}'", xpResult.Groups["level"].Value));
|
||||
break;
|
||||
}
|
||||
|
||||
int xpRequired;
|
||||
if (!int.TryParse(xpResult.Groups["xp"].Value, out xpRequired))
|
||||
{
|
||||
Debug.WriteLine(String.Format("Invalid xm required value: '{0}'", xpResult.Groups["xp"].Value));
|
||||
break;
|
||||
}
|
||||
|
||||
int engramPoints = 0;
|
||||
if (engramResult != null)
|
||||
{
|
||||
if (!int.TryParse(engramResult.Groups["points"].Value, out engramPoints))
|
||||
{
|
||||
Debug.WriteLine(String.Format("Invalid engram points value: '{0}'", engramResult.Groups["points"].Value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
levels.Add(new Level { LevelIndex = levelIndex, XPRequired = xpRequired, EngramPoints = engramPoints });
|
||||
xpResult = xpResult.NextMatch();
|
||||
if (engramResult != null)
|
||||
{
|
||||
engramResult = engramResult.NextMatch();
|
||||
}
|
||||
}
|
||||
|
||||
levels.UpdateTotals();
|
||||
return levels;
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class Level : DependencyObject
|
||||
{
|
||||
public static readonly DependencyProperty LevelIndexProperty = DependencyProperty.Register(nameof(LevelIndex), typeof(int), typeof(Level), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty XPRequiredProperty = DependencyProperty.Register(nameof(XPRequired), typeof(int), typeof(Level), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty EngramPointsProperty = DependencyProperty.Register(nameof(EngramPoints), typeof(int), typeof(Level), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty XPTotalProperty = DependencyProperty.Register(nameof(XPTotal), typeof(int), typeof(Level), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty EngramTotalProperty = DependencyProperty.Register(nameof(EngramTotal), typeof(int), typeof(Level), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty ShowColoredProperty = DependencyProperty.Register(nameof(ShowColored), typeof(bool), typeof(Level), new PropertyMetadata(false));
|
||||
|
||||
[DataMember]
|
||||
public int LevelIndex
|
||||
{
|
||||
get { return (int)GetValue(LevelIndexProperty); }
|
||||
set { SetValue(LevelIndexProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public int XPRequired
|
||||
{
|
||||
get { return (int)GetValue(XPRequiredProperty); }
|
||||
set { SetValue(XPRequiredProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public int EngramPoints
|
||||
{
|
||||
get { return (int)GetValue(EngramPointsProperty); }
|
||||
set { SetValue(EngramPointsProperty, value); }
|
||||
}
|
||||
|
||||
[XmlIgnore()]
|
||||
public int XPTotal
|
||||
{
|
||||
get { return (int)GetValue(XPTotalProperty); }
|
||||
set { SetValue(XPTotalProperty, value); }
|
||||
}
|
||||
|
||||
[XmlIgnore()]
|
||||
public int EngramTotal
|
||||
{
|
||||
get { return (int)GetValue(EngramTotalProperty); }
|
||||
set { SetValue(EngramTotalProperty, value); }
|
||||
}
|
||||
|
||||
public string GetINISubValueForXP()
|
||||
{
|
||||
return String.Format("ExperiencePointsForLevel[{0}]={1}", this.LevelIndex, this.XPRequired);
|
||||
}
|
||||
|
||||
public string GetINIValueForEngramPointsEarned()
|
||||
{
|
||||
return String.Format("OverridePlayerLevelEngramPoints={0}", this.EngramPoints);
|
||||
}
|
||||
|
||||
internal Level Duplicate()
|
||||
{
|
||||
return new Level { XPRequired = this.XPRequired, EngramPoints = this.EngramPoints };
|
||||
}
|
||||
|
||||
public bool ShowColored
|
||||
{
|
||||
get { return (bool)GetValue(ShowColoredProperty); }
|
||||
set { SetValue(ShowColoredProperty, value); }
|
||||
}
|
||||
}
|
||||
|
||||
public class CsvPlayerLevelMapping : CsvMapping<ImportLevel>
|
||||
{
|
||||
public CsvPlayerLevelMapping()
|
||||
: base()
|
||||
{
|
||||
MapProperty(0, x => x.LevelIndex);
|
||||
MapProperty(1, x => x.XPRequired);
|
||||
MapProperty(2, x => x.EngramPoints);
|
||||
}
|
||||
}
|
||||
|
||||
public class CsvDinoLevelMapping : CsvMapping<ImportLevel>
|
||||
{
|
||||
public CsvDinoLevelMapping()
|
||||
: base()
|
||||
{
|
||||
MapProperty(0, x => x.LevelIndex);
|
||||
MapProperty(1, x => x.XPRequired);
|
||||
}
|
||||
}
|
||||
|
||||
public class ImportLevel
|
||||
{
|
||||
public int LevelIndex { get; set; }
|
||||
public int XPRequired { get; set; }
|
||||
public int EngramPoints { get; set; }
|
||||
|
||||
public Level AsLevel()
|
||||
{
|
||||
return new Level() { LevelIndex = LevelIndex, XPRequired = XPRequired, EngramPoints = EngramPoints };
|
||||
}
|
||||
}
|
||||
}
|
||||
53
src/ARKServerManager/Lib/Model/NPCReplacement.cs
Normal file
53
src/ARKServerManager/Lib/Model/NPCReplacement.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
using ServerManagerTool.Common.Attibutes;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
public class NPCReplacement : AggregateIniValue
|
||||
{
|
||||
public static readonly DependencyProperty FromClassNameProperty = DependencyProperty.Register(nameof(FromClassName), typeof(string), typeof(NPCReplacement), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty ToClassNameProperty = DependencyProperty.Register(nameof(ToClassName), typeof(string), typeof(NPCReplacement), new PropertyMetadata(String.Empty));
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public string FromClassName
|
||||
{
|
||||
get { return (string)GetValue(FromClassNameProperty); }
|
||||
set { SetValue(FromClassNameProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public string ToClassName
|
||||
{
|
||||
get { return (string)GetValue(ToClassNameProperty); }
|
||||
set { SetValue(ToClassNameProperty, value); }
|
||||
}
|
||||
|
||||
public static NPCReplacement FromINIValue(string iniValue)
|
||||
{
|
||||
var newSpawn = new NPCReplacement();
|
||||
newSpawn.InitializeFromINIValue(iniValue);
|
||||
return newSpawn;
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return this.FromClassName;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return String.Equals(this.FromClassName, ((NPCReplacement)other).FromClassName, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public override bool ShouldSave()
|
||||
{
|
||||
return (!String.Equals(FromClassName, ToClassName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
||||
509
src/ARKServerManager/Lib/Model/NPCSpawner.cs
Normal file
509
src/ARKServerManager/Lib/Model/NPCSpawner.cs
Normal file
|
|
@ -0,0 +1,509 @@
|
|||
using ServerManagerTool.Common.Attibutes;
|
||||
using ServerManagerTool.Common.Interfaces;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Common.Utils;
|
||||
using ServerManagerTool.Enums;
|
||||
using ServerManagerTool.Interface;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
|
||||
public class NPCSpawnAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute for the NPCSpawn value
|
||||
/// </summary>
|
||||
public NPCSpawnAttribute(NPCSpawnContainerType[] containerTypes)
|
||||
{
|
||||
this.ContainerTypes = containerTypes.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ContainerTypes that are valid for the property.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public List<NPCSpawnContainerType> ContainerTypes;
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class NPCSpawnContainerList<T> : AggregateIniValueList<T>, ISpawnIniValuesCollection
|
||||
where T : AggregateIniValue, new()
|
||||
{
|
||||
public NPCSpawnContainerList(string aggregateValueName, NPCSpawnContainerType containerType)
|
||||
: base(aggregateValueName, null)
|
||||
{
|
||||
ContainerType = containerType;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public NPCSpawnContainerType ContainerType
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> ToIniValues()
|
||||
{
|
||||
return this.ToIniValues(ContainerType);
|
||||
}
|
||||
|
||||
public IEnumerable<string> ToIniValues(NPCSpawnContainerType containerType)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(IniCollectionKey))
|
||||
return this.Where(d => d.ShouldSave()).Cast<ISpawnIniValue>().Select(d => d.ToIniValue(containerType));
|
||||
|
||||
return this.Where(d => d.ShouldSave()).Cast<ISpawnIniValue>().Select(d => $"{this.IniCollectionKey}={d.ToIniValue(containerType)}");
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class NPCSpawnContainer : AggregateIniValue, ISpawnIniValue
|
||||
{
|
||||
public NPCSpawnContainer()
|
||||
{
|
||||
NPCSpawnEntries = new NPCSpawnList<NPCSpawnEntry>(null);
|
||||
NPCSpawnLimits = new NPCSpawnList<NPCSpawnLimit>(null);
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public Guid UniqueId = Guid.NewGuid();
|
||||
|
||||
public static readonly DependencyProperty NPCSpawnEntriesContainerClassStringProperty = DependencyProperty.Register(nameof(NPCSpawnEntriesContainerClassString), typeof(string), typeof(NPCSpawnContainer), new PropertyMetadata(string.Empty));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
[NPCSpawn(new[] { NPCSpawnContainerType.Add, NPCSpawnContainerType.Subtract, NPCSpawnContainerType.Override })]
|
||||
public string NPCSpawnEntriesContainerClassString
|
||||
{
|
||||
get { return (string)GetValue(NPCSpawnEntriesContainerClassStringProperty); }
|
||||
set { SetValue(NPCSpawnEntriesContainerClassStringProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NPCSpawnEntriesProperty = DependencyProperty.Register(nameof(NPCSpawnEntries), typeof(NPCSpawnList<NPCSpawnEntry>), typeof(NPCSpawnContainer), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(ValueWithinBrackets = true, ListValueWithinBrackets = true)]
|
||||
[NPCSpawn(new[] { NPCSpawnContainerType.Add, NPCSpawnContainerType.Subtract, NPCSpawnContainerType.Override })]
|
||||
public NPCSpawnList<NPCSpawnEntry> NPCSpawnEntries
|
||||
{
|
||||
get { return (NPCSpawnList<NPCSpawnEntry>)GetValue(NPCSpawnEntriesProperty); }
|
||||
set { SetValue(NPCSpawnEntriesProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NPCSpawnLimitsProperty = DependencyProperty.Register(nameof(NPCSpawnLimits), typeof(NPCSpawnList<NPCSpawnLimit>), typeof(NPCSpawnContainer), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(ValueWithinBrackets = true, ListValueWithinBrackets = true)]
|
||||
[NPCSpawn(new[] { NPCSpawnContainerType.Add, NPCSpawnContainerType.Subtract, NPCSpawnContainerType.Override })]
|
||||
public NPCSpawnList<NPCSpawnLimit> NPCSpawnLimits
|
||||
{
|
||||
get { return (NPCSpawnList<NPCSpawnLimit>)GetValue(NPCSpawnLimitsProperty); }
|
||||
set { SetValue(NPCSpawnLimitsProperty, value); }
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return;
|
||||
|
||||
var kvPair = value.Split(new[] { '=' }, 2);
|
||||
var kvValue = kvPair[1].Trim(' ');
|
||||
if (kvValue.StartsWith("("))
|
||||
kvValue = kvValue.Substring(1);
|
||||
if (kvValue.EndsWith(")"))
|
||||
kvValue = kvValue.Substring(0, kvValue.Length - 1);
|
||||
|
||||
base.FromComplexINIValue(kvValue);
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string ToIniValue(NPCSpawnContainerType containerType)
|
||||
{
|
||||
GetPropertyInfos();
|
||||
if (this.Properties.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var result = new StringBuilder();
|
||||
result.Append("(");
|
||||
|
||||
var delimiter = "";
|
||||
foreach (var prop in this.Properties)
|
||||
{
|
||||
var attrSpawn = prop.GetCustomAttributes(typeof(NPCSpawnAttribute), false).OfType<NPCSpawnAttribute>().FirstOrDefault();
|
||||
if (!attrSpawn?.ContainerTypes?.Contains(containerType) ?? false)
|
||||
continue;
|
||||
|
||||
result.Append(delimiter);
|
||||
|
||||
var attr = prop.GetCustomAttributes(typeof(AggregateIniValueEntryAttribute), false).OfType<AggregateIniValueEntryAttribute>().FirstOrDefault();
|
||||
var propName = string.IsNullOrWhiteSpace(attr?.Key) ? prop.Name : attr.Key;
|
||||
|
||||
result.Append($"{propName}=");
|
||||
if (attr?.ValueWithinBrackets ?? false)
|
||||
result.Append("(");
|
||||
|
||||
var val = prop.GetValue(this);
|
||||
var spawnCollection = val as ISpawnIniValuesCollection;
|
||||
if (spawnCollection != null)
|
||||
{
|
||||
var iniVals = spawnCollection.ToIniValues(containerType);
|
||||
var delimiter2 = "";
|
||||
foreach (var iniVal in iniVals)
|
||||
{
|
||||
result.Append(delimiter2);
|
||||
if (attr?.ListValueWithinBrackets ?? false)
|
||||
result.Append($"({iniVal})");
|
||||
else
|
||||
result.Append(iniVal);
|
||||
|
||||
delimiter2 = DELIMITER.ToString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var collection = val as IIniValuesCollection;
|
||||
if (collection != null)
|
||||
{
|
||||
var iniVals = collection.ToIniValues();
|
||||
var delimiter2 = "";
|
||||
foreach (var iniVal in iniVals)
|
||||
{
|
||||
result.Append(delimiter2);
|
||||
if (attr?.ListValueWithinBrackets ?? false)
|
||||
result.Append($"({iniVal})");
|
||||
else
|
||||
result.Append(iniVal);
|
||||
|
||||
delimiter2 = DELIMITER.ToString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var propValue = StringUtils.GetPropertyValue(val, prop);
|
||||
result.Append(propValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (attr?.ValueWithinBrackets ?? false)
|
||||
result.Append(")");
|
||||
|
||||
delimiter = DELIMITER.ToString();
|
||||
}
|
||||
|
||||
result.Append(")");
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{NPCSpawnEntriesContainerClassString}; NPCSpawnEntries={NPCSpawnEntries.Count}; NPCSpawnLimits={NPCSpawnLimits.Count}";
|
||||
}
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(NPCSpawnEntriesContainerClassString) && NPCSpawnEntries.Count == NPCSpawnLimits.Count;
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class NPCSpawnList<T> : AggregateIniValueList<T>, ISpawnIniValuesCollection
|
||||
where T : AggregateIniValue, new()
|
||||
{
|
||||
public NPCSpawnList(string aggregateValueName)
|
||||
: base(aggregateValueName, null)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerable<string> ToIniValues()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<string> ToIniValues(NPCSpawnContainerType containerType)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(IniCollectionKey))
|
||||
return this.Where(d => d.ShouldSave()).Cast<ISpawnIniValue>().Select(d => d.ToIniValue(containerType));
|
||||
|
||||
return this.Where(d => d.ShouldSave()).Cast<ISpawnIniValue>().Select(d => $"{this.IniCollectionKey}={d.ToIniValue(containerType)}");
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class NPCSpawnEntry : AggregateIniValue, ISpawnIniValue
|
||||
{
|
||||
public static readonly DependencyProperty AnEntryNameProperty = DependencyProperty.Register(nameof(AnEntryName), typeof(string), typeof(NPCSpawnEntry), new PropertyMetadata(string.Empty));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
[NPCSpawn(new[] { NPCSpawnContainerType.Add, NPCSpawnContainerType.Override })]
|
||||
public string AnEntryName
|
||||
{
|
||||
get { return (string)GetValue(AnEntryNameProperty); }
|
||||
set { SetValue(AnEntryNameProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EntryWeightProperty = DependencyProperty.Register(nameof(EntryWeight), typeof(float), typeof(NPCSpawnEntry), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
[NPCSpawn(new[] { NPCSpawnContainerType.Add, NPCSpawnContainerType.Override })]
|
||||
public float EntryWeight
|
||||
{
|
||||
get { return (float)GetValue(EntryWeightProperty); }
|
||||
set { SetValue(EntryWeightProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NPCsToSpawnStringsProperty = DependencyProperty.Register(nameof(NPCsToSpawnStrings), typeof(string), typeof(NPCSpawnEntry), new PropertyMetadata(string.Empty));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(ValueWithinBrackets = true)]
|
||||
[NPCSpawn(new[] { NPCSpawnContainerType.Add, NPCSpawnContainerType.Subtract, NPCSpawnContainerType.Override })]
|
||||
public string NPCsToSpawnStrings
|
||||
{
|
||||
get { return (string)GetValue(NPCsToSpawnStringsProperty); }
|
||||
set { SetValue(NPCsToSpawnStringsProperty, value); }
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
base.FromComplexINIValue(value);
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string ToIniValue(NPCSpawnContainerType containerType)
|
||||
{
|
||||
GetPropertyInfos();
|
||||
if (this.Properties.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var result = new StringBuilder();
|
||||
|
||||
var delimiter = "";
|
||||
foreach (var prop in this.Properties)
|
||||
{
|
||||
var attrSpawn = prop.GetCustomAttributes(typeof(NPCSpawnAttribute), false).OfType<NPCSpawnAttribute>().FirstOrDefault();
|
||||
if (!attrSpawn?.ContainerTypes?.Contains(containerType) ?? false)
|
||||
continue;
|
||||
|
||||
result.Append(delimiter);
|
||||
|
||||
var attr = prop.GetCustomAttributes(typeof(AggregateIniValueEntryAttribute), false).OfType<AggregateIniValueEntryAttribute>().FirstOrDefault();
|
||||
var propName = string.IsNullOrWhiteSpace(attr?.Key) ? prop.Name : attr.Key;
|
||||
|
||||
result.Append($"{propName}=");
|
||||
if (attr?.ValueWithinBrackets ?? false)
|
||||
result.Append("(");
|
||||
|
||||
var val = prop.GetValue(this);
|
||||
var spawnCollection = val as ISpawnIniValuesCollection;
|
||||
if (spawnCollection != null)
|
||||
{
|
||||
var iniVals = spawnCollection.ToIniValues(containerType);
|
||||
var delimiter2 = "";
|
||||
foreach (var iniVal in iniVals)
|
||||
{
|
||||
result.Append(delimiter2);
|
||||
if (attr?.ListValueWithinBrackets ?? false)
|
||||
result.Append($"({iniVal})");
|
||||
else
|
||||
result.Append(iniVal);
|
||||
|
||||
delimiter2 = DELIMITER.ToString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var collection = val as IIniValuesCollection;
|
||||
if (collection != null)
|
||||
{
|
||||
var iniVals = collection.ToIniValues();
|
||||
var delimiter2 = "";
|
||||
foreach (var iniVal in iniVals)
|
||||
{
|
||||
result.Append(delimiter2);
|
||||
if (attr?.ListValueWithinBrackets ?? false)
|
||||
result.Append($"({iniVal})");
|
||||
else
|
||||
result.Append(iniVal);
|
||||
|
||||
delimiter2 = DELIMITER.ToString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var propValue = StringUtils.GetPropertyValue(val, prop);
|
||||
result.Append(propValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (attr?.ValueWithinBrackets ?? false)
|
||||
result.Append(")");
|
||||
|
||||
delimiter = DELIMITER.ToString();
|
||||
}
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"AnEntryName={AnEntryName}; EntryWeight={EntryWeight}; NPCsToSpawnStrings={NPCsToSpawnStrings}";
|
||||
}
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(NPCsToSpawnStrings);
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class NPCSpawnLimit : AggregateIniValue, ISpawnIniValue
|
||||
{
|
||||
public static readonly DependencyProperty NPCClassStringProperty = DependencyProperty.Register(nameof(NPCClassString), typeof(string), typeof(NPCSpawnLimit), new PropertyMetadata(string.Empty));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
[NPCSpawn(new[] { NPCSpawnContainerType.Add, NPCSpawnContainerType.Subtract, NPCSpawnContainerType.Override })]
|
||||
public string NPCClassString
|
||||
{
|
||||
get { return (string)GetValue(NPCClassStringProperty); }
|
||||
set { SetValue(NPCClassStringProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MaxPercentageOfDesiredNumToAllowProperty = DependencyProperty.Register(nameof(MaxPercentageOfDesiredNumToAllow), typeof(float), typeof(NPCSpawnLimit), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
[NPCSpawn(new[] { NPCSpawnContainerType.Add, NPCSpawnContainerType.Override })]
|
||||
public float MaxPercentageOfDesiredNumToAllow
|
||||
{
|
||||
get { return (float)GetValue(MaxPercentageOfDesiredNumToAllowProperty); }
|
||||
set { SetValue(MaxPercentageOfDesiredNumToAllowProperty, value); }
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
base.FromComplexINIValue(value);
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string ToIniValue(NPCSpawnContainerType containerType)
|
||||
{
|
||||
GetPropertyInfos();
|
||||
if (this.Properties.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var result = new StringBuilder();
|
||||
|
||||
var delimiter = "";
|
||||
foreach (var prop in this.Properties)
|
||||
{
|
||||
var attrSpawn = prop.GetCustomAttributes(typeof(NPCSpawnAttribute), false).OfType<NPCSpawnAttribute>().FirstOrDefault();
|
||||
if (!attrSpawn?.ContainerTypes?.Contains(containerType) ?? false)
|
||||
continue;
|
||||
|
||||
result.Append(delimiter);
|
||||
|
||||
var attr = prop.GetCustomAttributes(typeof(AggregateIniValueEntryAttribute), false).OfType<AggregateIniValueEntryAttribute>().FirstOrDefault();
|
||||
var propName = string.IsNullOrWhiteSpace(attr?.Key) ? prop.Name : attr.Key;
|
||||
|
||||
result.Append($"{propName}=");
|
||||
if (attr?.ValueWithinBrackets ?? false)
|
||||
result.Append("(");
|
||||
|
||||
var val = prop.GetValue(this);
|
||||
var spawnCollection = val as ISpawnIniValuesCollection;
|
||||
if (spawnCollection != null)
|
||||
{
|
||||
var iniVals = spawnCollection.ToIniValues(containerType);
|
||||
var delimiter2 = "";
|
||||
foreach (var iniVal in iniVals)
|
||||
{
|
||||
result.Append(delimiter2);
|
||||
if (attr?.ListValueWithinBrackets ?? false)
|
||||
result.Append($"({iniVal})");
|
||||
else
|
||||
result.Append(iniVal);
|
||||
|
||||
delimiter2 = DELIMITER.ToString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var collection = val as IIniValuesCollection;
|
||||
if (collection != null)
|
||||
{
|
||||
var iniVals = collection.ToIniValues();
|
||||
var delimiter2 = "";
|
||||
foreach (var iniVal in iniVals)
|
||||
{
|
||||
result.Append(delimiter2);
|
||||
if (attr?.ListValueWithinBrackets ?? false)
|
||||
result.Append($"({iniVal})");
|
||||
else
|
||||
result.Append(iniVal);
|
||||
|
||||
delimiter2 = DELIMITER.ToString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var propValue = StringUtils.GetPropertyValue(val, prop);
|
||||
result.Append(propValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (attr?.ValueWithinBrackets ?? false)
|
||||
result.Append(")");
|
||||
|
||||
delimiter = DELIMITER.ToString();
|
||||
}
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"NPCClassString={NPCClassString}; MaxPercentageOfDesiredNumToAllow={MaxPercentageOfDesiredNumToAllow}";
|
||||
}
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(NPCClassString);
|
||||
}
|
||||
}
|
||||
855
src/ARKServerManager/Lib/Model/PGMTerrain.cs
Normal file
855
src/ARKServerManager/Lib/Model/PGMTerrain.cs
Normal file
|
|
@ -0,0 +1,855 @@
|
|||
using ServerManagerTool.Common.Attibutes;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Common.Utils;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
public class PGMTerrain : AggregateIniValue
|
||||
{
|
||||
private new const char DELIMITER = ';';
|
||||
|
||||
public PGMTerrain()
|
||||
{
|
||||
SnowBiomeLocation = new PGMTerrainXY(0.2f, 0.2f);
|
||||
RedWoodForestBiomeLocation = new PGMTerrainXY(0.5f, 0.5f);
|
||||
|
||||
NorthRegion1Start = new PGMTerrainXY(0.25f, 0.0f);
|
||||
NorthRegion1End = new PGMTerrainXY(0.416f, 0.5f);
|
||||
NorthRegion2Start = new PGMTerrainXY(0.416f, 0.0f);
|
||||
NorthRegion2End = new PGMTerrainXY(0.582f, 0.5f);
|
||||
NorthRegion3Start = new PGMTerrainXY(0.582f, 0.0f);
|
||||
NorthRegion3End = new PGMTerrainXY(0.75f, 0.0f);
|
||||
SouthRegion1Start = new PGMTerrainXY(0.25f, 0.5f);
|
||||
SouthRegion1End = new PGMTerrainXY(0.416f, 1.0f);
|
||||
SouthRegion2Start = new PGMTerrainXY(0.416f, 0.5f);
|
||||
SouthRegion2End = new PGMTerrainXY(0.582f, 1.0f);
|
||||
SouthRegion3Start = new PGMTerrainXY(0.582f, 0.5f);
|
||||
SouthRegion3End = new PGMTerrainXY(0.75f, 1.0f);
|
||||
EastRegion1Start = new PGMTerrainXY(0.75f, 0.0f);
|
||||
EastRegion1End = new PGMTerrainXY(1.0f, 0.333f);
|
||||
EastRegion2Start = new PGMTerrainXY(0.75f, 0.333f);
|
||||
EastRegion2End = new PGMTerrainXY(1.0f, 0.666f);
|
||||
EastRegion3Start = new PGMTerrainXY(0.75f, 0.666f);
|
||||
EastRegion3End = new PGMTerrainXY(1.0f, 1.0f);
|
||||
WestRegion1Start = new PGMTerrainXY(0.0f, 0.0f);
|
||||
WestRegion1End = new PGMTerrainXY(0.25f, 0.333f);
|
||||
WestRegion2Start = new PGMTerrainXY(0.0f, 0.333f);
|
||||
WestRegion2End = new PGMTerrainXY(0.25f, 0.666f);
|
||||
WestRegion3Start = new PGMTerrainXY(0.0f, 0.666f);
|
||||
WestRegion3End = new PGMTerrainXY(0.25f, 1.0f);
|
||||
|
||||
TerrainScaleMultiplier = new PGMTerrainXYZ(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MapSeedProperty = DependencyProperty.Register(nameof(MapSeed), typeof(int), typeof(PGMTerrain), new PropertyMetadata(999));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public int MapSeed
|
||||
{
|
||||
get { return (int)GetValue(MapSeedProperty); }
|
||||
set { SetValue(MapSeedProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LandscapeRadiusProperty = DependencyProperty.Register(nameof(LandscapeRadius), typeof(float), typeof(PGMTerrain), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float LandscapeRadius
|
||||
{
|
||||
get { return (float)GetValue(LandscapeRadiusProperty); }
|
||||
set { SetValue(LandscapeRadiusProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty WaterFrequencyProperty = DependencyProperty.Register(nameof(WaterFrequency), typeof(float), typeof(PGMTerrain), new PropertyMetadata(5.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "Water Frequency")]
|
||||
public float WaterFrequency
|
||||
{
|
||||
get { return (float)GetValue(WaterFrequencyProperty); }
|
||||
set { SetValue(WaterFrequencyProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MountainsFrequencyProperty = DependencyProperty.Register(nameof(MountainsFrequency), typeof(float), typeof(PGMTerrain), new PropertyMetadata(12.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "Mountains Frequency")]
|
||||
public float MountainsFrequency
|
||||
{
|
||||
get { return (float)GetValue(MountainsFrequencyProperty); }
|
||||
set { SetValue(MountainsFrequencyProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MountainsSlopeProperty = DependencyProperty.Register(nameof(MountainsSlope), typeof(float), typeof(PGMTerrain), new PropertyMetadata(1.8f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "Mountains Slope")]
|
||||
public float MountainsSlope
|
||||
{
|
||||
get { return (float)GetValue(MountainsSlopeProperty); }
|
||||
set { SetValue(MountainsSlopeProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MountainsHeightProperty = DependencyProperty.Register(nameof(MountainsHeight), typeof(float), typeof(PGMTerrain), new PropertyMetadata(1.25f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MountainsHeight
|
||||
{
|
||||
get { return (float)GetValue(MountainsHeightProperty); }
|
||||
set { SetValue(MountainsHeightProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TurbulencePowerProperty = DependencyProperty.Register(nameof(TurbulencePower), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.0125f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "Turbulence Power")]
|
||||
public float TurbulencePower
|
||||
{
|
||||
get { return (float)GetValue(TurbulencePowerProperty); }
|
||||
set { SetValue(TurbulencePowerProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShoreSlopeProperty = DependencyProperty.Register(nameof(ShoreSlope), typeof(float), typeof(PGMTerrain), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "Shore Slope")]
|
||||
public float ShoreSlope
|
||||
{
|
||||
get { return (float)GetValue(ShoreSlopeProperty); }
|
||||
set { SetValue(ShoreSlopeProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty WaterLevelProperty = DependencyProperty.Register(nameof(WaterLevel), typeof(float), typeof(PGMTerrain), new PropertyMetadata(-0.72f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float WaterLevel
|
||||
{
|
||||
get { return (float)GetValue(WaterLevelProperty); }
|
||||
set { SetValue(WaterLevelProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShoreLineEndProperty = DependencyProperty.Register(nameof(ShoreLineEnd), typeof(float), typeof(PGMTerrain), new PropertyMetadata(-0.715f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float ShoreLineEnd
|
||||
{
|
||||
get { return (float)GetValue(ShoreLineEndProperty); }
|
||||
set { SetValue(ShoreLineEndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty GrassDensityProperty = DependencyProperty.Register(nameof(GrassDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float GrassDensity
|
||||
{
|
||||
get { return (float)GetValue(GrassDensityProperty); }
|
||||
set { SetValue(GrassDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty JungleGrassDensityProperty = DependencyProperty.Register(nameof(JungleGrassDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.02f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float JungleGrassDensity
|
||||
{
|
||||
get { return (float)GetValue(JungleGrassDensityProperty); }
|
||||
set { SetValue(JungleGrassDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty OceanFloorLevelProperty = DependencyProperty.Register(nameof(OceanFloorLevel), typeof(float), typeof(PGMTerrain), new PropertyMetadata(-1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float OceanFloorLevel
|
||||
{
|
||||
get { return (float)GetValue(OceanFloorLevelProperty); }
|
||||
set { SetValue(OceanFloorLevelProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SnowBiomeSizeProperty = DependencyProperty.Register(nameof(SnowBiomeSize), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.3f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float SnowBiomeSize
|
||||
{
|
||||
get { return (float)GetValue(SnowBiomeSizeProperty); }
|
||||
set { SetValue(SnowBiomeSizeProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty RedWoodBiomeSizeProperty = DependencyProperty.Register(nameof(RedWoodBiomeSize), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.075f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "RWBiomeSize")]
|
||||
public float RedWoodBiomeSize
|
||||
{
|
||||
get { return (float)GetValue(RedWoodBiomeSizeProperty); }
|
||||
set { SetValue(RedWoodBiomeSizeProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MountainBiomeStartProperty = DependencyProperty.Register(nameof(MountainBiomeStart), typeof(float), typeof(PGMTerrain), new PropertyMetadata(-0.55f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MountainBiomeStart
|
||||
{
|
||||
get { return (float)GetValue(MountainBiomeStartProperty); }
|
||||
set { SetValue(MountainBiomeStartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MountainsTreeDensityProperty = DependencyProperty.Register(nameof(MountainsTreeDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.01f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MountainsTreeDensity
|
||||
{
|
||||
get { return (float)GetValue(MountainsTreeDensityProperty); }
|
||||
set { SetValue(MountainsTreeDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty JungleBiomeStartProperty = DependencyProperty.Register(nameof(JungleBiomeStart), typeof(float), typeof(PGMTerrain), new PropertyMetadata(-0.65f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float JungleBiomeStart
|
||||
{
|
||||
get { return (float)GetValue(JungleBiomeStartProperty); }
|
||||
set { SetValue(JungleBiomeStartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IslandBorderCurveExponentProperty = DependencyProperty.Register(nameof(IslandBorderCurveExponent), typeof(float), typeof(PGMTerrain), new PropertyMetadata(4.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "IslandBorderCurveExp")]
|
||||
public float IslandBorderCurveExponent
|
||||
{
|
||||
get { return (float)GetValue(IslandBorderCurveExponentProperty); }
|
||||
set { SetValue(IslandBorderCurveExponentProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MaxSpawnPointHeightProperty = DependencyProperty.Register(nameof(MaxSpawnPointHeight), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.1f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "MaxSawnPointHeight")]
|
||||
public float MaxSpawnPointHeight
|
||||
{
|
||||
get { return (float)GetValue(MaxSpawnPointHeightProperty); }
|
||||
set { SetValue(MaxSpawnPointHeightProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MountainGrassDensityProperty = DependencyProperty.Register(nameof(MountainGrassDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.05f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MountainGrassDensity
|
||||
{
|
||||
get { return (float)GetValue(MountainGrassDensityProperty); }
|
||||
set { SetValue(MountainGrassDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SnowMountainGrassDensityProperty = DependencyProperty.Register(nameof(SnowMountainGrassDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.15f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float SnowMountainGrassDensity
|
||||
{
|
||||
get { return (float)GetValue(SnowMountainGrassDensityProperty); }
|
||||
set { SetValue(SnowMountainGrassDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SnowGrassDensityProperty = DependencyProperty.Register(nameof(SnowGrassDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.25f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float SnowGrassDensity
|
||||
{
|
||||
get { return (float)GetValue(SnowGrassDensityProperty); }
|
||||
set { SetValue(SnowGrassDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty UnderwaterObjectsDensityProperty = DependencyProperty.Register(nameof(UnderwaterObjectsDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.5f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float UnderwaterObjectsDensity
|
||||
{
|
||||
get { return (float)GetValue(UnderwaterObjectsDensityProperty); }
|
||||
set { SetValue(UnderwaterObjectsDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SnowMountainsTreeDensityProperty = DependencyProperty.Register(nameof(SnowMountainsTreeDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.01f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float SnowMountainsTreeDensity
|
||||
{
|
||||
get { return (float)GetValue(SnowMountainsTreeDensityProperty); }
|
||||
set { SetValue(SnowMountainsTreeDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TreeDensityProperty = DependencyProperty.Register(nameof(TreeDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.003f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float TreeDensity
|
||||
{
|
||||
get { return (float)GetValue(TreeDensityProperty); }
|
||||
set { SetValue(TreeDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty JungleTreeDensityProperty = DependencyProperty.Register(nameof(JungleTreeDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.66f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float JungleTreeDensity
|
||||
{
|
||||
get { return (float)GetValue(JungleTreeDensityProperty); }
|
||||
set { SetValue(JungleTreeDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty RedWoodTreeDensityProperty = DependencyProperty.Register(nameof(RedWoodTreeDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.35f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float RedWoodTreeDensity
|
||||
{
|
||||
get { return (float)GetValue(RedWoodTreeDensityProperty); }
|
||||
set { SetValue(RedWoodTreeDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SnowTreeDensityProperty = DependencyProperty.Register(nameof(SnowTreeDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float SnowTreeDensity
|
||||
{
|
||||
get { return (float)GetValue(SnowTreeDensityProperty); }
|
||||
set { SetValue(SnowTreeDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty RedwoodGrassDensityProperty = DependencyProperty.Register(nameof(RedwoodGrassDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.1f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float RedwoodGrassDensity
|
||||
{
|
||||
get { return (float)GetValue(RedwoodGrassDensityProperty); }
|
||||
set { SetValue(RedwoodGrassDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShoreTreeDensityProperty = DependencyProperty.Register(nameof(ShoreTreeDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.05f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float ShoreTreeDensity
|
||||
{
|
||||
get { return (float)GetValue(ShoreTreeDensityProperty); }
|
||||
set { SetValue(ShoreTreeDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SnowShoreTreeDensityProperty = DependencyProperty.Register(nameof(SnowShoreTreeDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.025f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float SnowShoreTreeDensity
|
||||
{
|
||||
get { return (float)GetValue(SnowShoreTreeDensityProperty); }
|
||||
set { SetValue(SnowShoreTreeDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DeepWaterBiomesDepthProperty = DependencyProperty.Register(nameof(DeepWaterBiomesDepth), typeof(float), typeof(PGMTerrain), new PropertyMetadata(-0.24f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float DeepWaterBiomesDepth
|
||||
{
|
||||
get { return (float)GetValue(DeepWaterBiomesDepthProperty); }
|
||||
set { SetValue(DeepWaterBiomesDepthProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty InlandWaterObjectsDensityProperty = DependencyProperty.Register(nameof(InlandWaterObjectsDensity), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.5f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float InlandWaterObjectsDensity
|
||||
{
|
||||
get { return (float)GetValue(InlandWaterObjectsDensityProperty); }
|
||||
set { SetValue(InlandWaterObjectsDensityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShorelineStartOffsetProperty = DependencyProperty.Register(nameof(ShorelineStartOffset), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.01f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float ShorelineStartOffset
|
||||
{
|
||||
get { return (float)GetValue(ShorelineStartOffsetProperty); }
|
||||
set { SetValue(ShorelineStartOffsetProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShorelineThicknessProperty = DependencyProperty.Register(nameof(ShorelineThickness), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.0015f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float ShorelineThickness
|
||||
{
|
||||
get { return (float)GetValue(ShorelineThicknessProperty); }
|
||||
set { SetValue(ShorelineThicknessProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TreesGroundSlopeAccuracyProperty = DependencyProperty.Register(nameof(TreesGroundSlopeAccuracy), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.5f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float TreesGroundSlopeAccuracy
|
||||
{
|
||||
get { return (float)GetValue(TreesGroundSlopeAccuracyProperty); }
|
||||
set { SetValue(TreesGroundSlopeAccuracyProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ErosionStepsProperty = DependencyProperty.Register(nameof(ErosionSteps), typeof(int), typeof(PGMTerrain), new PropertyMetadata(4));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public int ErosionSteps
|
||||
{
|
||||
get { return (int)GetValue(ErosionStepsProperty); }
|
||||
set { SetValue(ErosionStepsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ErosionStrengthProperty = DependencyProperty.Register(nameof(ErosionStrength), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.75f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float ErosionStrength
|
||||
{
|
||||
get { return (float)GetValue(ErosionStrengthProperty); }
|
||||
set { SetValue(ErosionStrengthProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DepositionStrengthProperty = DependencyProperty.Register(nameof(DepositionStrength), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.5f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float DepositionStrength
|
||||
{
|
||||
get { return (float)GetValue(DepositionStrengthProperty); }
|
||||
set { SetValue(DepositionStrengthProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MountainGeneralTreesPercentProperty = DependencyProperty.Register(nameof(MountainGeneralTreesPercent), typeof(float), typeof(PGMTerrain), new PropertyMetadata(0.1f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MountainGeneralTreesPercent
|
||||
{
|
||||
get { return (float)GetValue(MountainGeneralTreesPercentProperty); }
|
||||
set { SetValue(MountainGeneralTreesPercentProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SnowBiomeLocationProperty = DependencyProperty.Register(nameof(SnowBiomeLocation), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY SnowBiomeLocation
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(SnowBiomeLocationProperty); }
|
||||
set { SetValue(SnowBiomeLocationProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty RedWoodForestBiomeLocationProperty = DependencyProperty.Register(nameof(RedWoodForestBiomeLocation), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "RWForestBiomeLocation")]
|
||||
public PGMTerrainXY RedWoodForestBiomeLocation
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(RedWoodForestBiomeLocationProperty); }
|
||||
set { SetValue(RedWoodForestBiomeLocationProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NorthRegion1StartProperty = DependencyProperty.Register(nameof(NorthRegion1Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY NorthRegion1Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(NorthRegion1StartProperty); }
|
||||
set { SetValue(NorthRegion1StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NorthRegion1EndProperty = DependencyProperty.Register(nameof(NorthRegion1End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY NorthRegion1End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(NorthRegion1EndProperty); }
|
||||
set { SetValue(NorthRegion1EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NorthRegion2StartProperty = DependencyProperty.Register(nameof(NorthRegion2Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY NorthRegion2Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(NorthRegion2StartProperty); }
|
||||
set { SetValue(NorthRegion2StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NorthRegion2EndProperty = DependencyProperty.Register(nameof(NorthRegion2End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY NorthRegion2End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(NorthRegion2EndProperty); }
|
||||
set { SetValue(NorthRegion2EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NorthRegion3StartProperty = DependencyProperty.Register(nameof(NorthRegion3Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY NorthRegion3Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(NorthRegion3StartProperty); }
|
||||
set { SetValue(NorthRegion3StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NorthRegion3EndProperty = DependencyProperty.Register(nameof(NorthRegion3End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY NorthRegion3End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(NorthRegion3EndProperty); }
|
||||
set { SetValue(NorthRegion3EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SouthRegion1StartProperty = DependencyProperty.Register(nameof(SouthRegion1Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY SouthRegion1Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(SouthRegion1StartProperty); }
|
||||
set { SetValue(SouthRegion1StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SouthRegion1EndProperty = DependencyProperty.Register(nameof(SouthRegion1End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY SouthRegion1End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(SouthRegion1EndProperty); }
|
||||
set { SetValue(SouthRegion1EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SouthRegion2StartProperty = DependencyProperty.Register(nameof(SouthRegion2Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY SouthRegion2Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(SouthRegion2StartProperty); }
|
||||
set { SetValue(SouthRegion2StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SouthRegion2EndProperty = DependencyProperty.Register(nameof(SouthRegion2End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY SouthRegion2End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(SouthRegion2EndProperty); }
|
||||
set { SetValue(SouthRegion2EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SouthRegion3StartProperty = DependencyProperty.Register(nameof(SouthRegion3Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY SouthRegion3Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(SouthRegion3StartProperty); }
|
||||
set { SetValue(SouthRegion3StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SouthRegion3EndProperty = DependencyProperty.Register(nameof(SouthRegion3End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY SouthRegion3End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(SouthRegion3EndProperty); }
|
||||
set { SetValue(SouthRegion3EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EastRegion1StartProperty = DependencyProperty.Register(nameof(EastRegion1Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY EastRegion1Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(EastRegion1StartProperty); }
|
||||
set { SetValue(EastRegion1StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EastRegion1EndProperty = DependencyProperty.Register(nameof(EastRegion1End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY EastRegion1End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(EastRegion1EndProperty); }
|
||||
set { SetValue(EastRegion1EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EastRegion2StartProperty = DependencyProperty.Register(nameof(EastRegion2Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY EastRegion2Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(EastRegion2StartProperty); }
|
||||
set { SetValue(EastRegion2StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EastRegion2EndProperty = DependencyProperty.Register(nameof(EastRegion2End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY EastRegion2End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(EastRegion2EndProperty); }
|
||||
set { SetValue(EastRegion2EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EastRegion3StartProperty = DependencyProperty.Register(nameof(EastRegion3Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY EastRegion3Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(EastRegion3StartProperty); }
|
||||
set { SetValue(EastRegion3StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EastRegion3EndProperty = DependencyProperty.Register(nameof(EastRegion3End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY EastRegion3End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(EastRegion3EndProperty); }
|
||||
set { SetValue(EastRegion3EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty WestRegion1StartProperty = DependencyProperty.Register(nameof(WestRegion1Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY WestRegion1Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(WestRegion1StartProperty); }
|
||||
set { SetValue(WestRegion1StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty WestRegion1EndProperty = DependencyProperty.Register(nameof(WestRegion1End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY WestRegion1End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(WestRegion1EndProperty); }
|
||||
set { SetValue(WestRegion1EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty WestRegion2StartProperty = DependencyProperty.Register(nameof(WestRegion2Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY WestRegion2Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(WestRegion2StartProperty); }
|
||||
set { SetValue(WestRegion2StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty WestRegion2EndProperty = DependencyProperty.Register(nameof(WestRegion2End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY WestRegion2End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(WestRegion2EndProperty); }
|
||||
set { SetValue(WestRegion2EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty WestRegion3StartProperty = DependencyProperty.Register(nameof(WestRegion3Start), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY WestRegion3Start
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(WestRegion3StartProperty); }
|
||||
set { SetValue(WestRegion3StartProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty WestRegion3EndProperty = DependencyProperty.Register(nameof(WestRegion3End), typeof(PGMTerrainXY), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXY WestRegion3End
|
||||
{
|
||||
get { return (PGMTerrainXY)GetValue(WestRegion3EndProperty); }
|
||||
set { SetValue(WestRegion3EndProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TerrainScaleMultiplierProperty = DependencyProperty.Register(nameof(TerrainScaleMultiplier), typeof(PGMTerrainXYZ), typeof(PGMTerrain), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public PGMTerrainXYZ TerrainScaleMultiplier
|
||||
{
|
||||
get { return (PGMTerrainXYZ)GetValue(TerrainScaleMultiplierProperty); }
|
||||
set { SetValue(TerrainScaleMultiplierProperty, value); }
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return;
|
||||
|
||||
GetPropertyInfos();
|
||||
if (this.Properties.Count == 0)
|
||||
return;
|
||||
|
||||
value = value.Trim('(', ')', ' ');
|
||||
var pairs = value.Split(DELIMITER);
|
||||
|
||||
foreach (var pair in pairs)
|
||||
{
|
||||
var kvPair = pair.Split(new[] { '=' }, 2);
|
||||
if (kvPair.Length != 2)
|
||||
continue;
|
||||
|
||||
var key = kvPair[0].Trim();
|
||||
var val = kvPair[1].Trim();
|
||||
var propInfo = this.Properties.FirstOrDefault(p => string.Equals(p.Name, key, StringComparison.OrdinalIgnoreCase));
|
||||
if (propInfo != null)
|
||||
StringUtils.SetPropertyValue(val, this, propInfo);
|
||||
else
|
||||
{
|
||||
propInfo = this.Properties.FirstOrDefault(f => f.GetCustomAttributes(typeof(AggregateIniValueEntryAttribute), false).OfType<AggregateIniValueEntryAttribute>().Any(a => string.Equals(a.Key, key, StringComparison.OrdinalIgnoreCase)));
|
||||
if (propInfo != null)
|
||||
StringUtils.SetPropertyValue(val, this, propInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
GetPropertyInfos();
|
||||
if (this.Properties.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var result = new StringBuilder();
|
||||
|
||||
var delimiter = "";
|
||||
foreach (var prop in this.Properties)
|
||||
{
|
||||
result.Append(delimiter);
|
||||
|
||||
var attr = prop.GetCustomAttributes(typeof(AggregateIniValueEntryAttribute), false).OfType<AggregateIniValueEntryAttribute>().FirstOrDefault();
|
||||
var propName = string.IsNullOrWhiteSpace(attr?.Key) ? prop.Name : attr.Key;
|
||||
|
||||
var val = prop.GetValue(this);
|
||||
var propValue = StringUtils.GetPropertyValue(val, prop);
|
||||
|
||||
result.Append($"{propName}={propValue}");
|
||||
|
||||
delimiter = DELIMITER.ToString();
|
||||
}
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class PGMTerrainXY : AggregateIniValue
|
||||
{
|
||||
public PGMTerrainXY()
|
||||
{
|
||||
}
|
||||
public PGMTerrainXY(float x, float y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty XProperty = DependencyProperty.Register(nameof(X), typeof(float), typeof(PGMTerrainXY), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float X
|
||||
{
|
||||
get { return (float)GetValue(XProperty); }
|
||||
set { SetValue(XProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty YProperty = DependencyProperty.Register(nameof(Y), typeof(float), typeof(PGMTerrainXY), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float Y
|
||||
{
|
||||
get { return (float)GetValue(YProperty); }
|
||||
set { SetValue(YProperty, value); }
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return;
|
||||
|
||||
GetPropertyInfos();
|
||||
if (this.Properties.Count == 0)
|
||||
return;
|
||||
|
||||
value = value.Trim('(', ')', ' ');
|
||||
var pairs = value.Split(DELIMITER);
|
||||
|
||||
foreach (var pair in pairs)
|
||||
{
|
||||
var kvPair = pair.Split(new[] { '=' }, 2);
|
||||
if (kvPair.Length != 2)
|
||||
continue;
|
||||
|
||||
var key = kvPair[0].Trim();
|
||||
var val = kvPair[1].Trim();
|
||||
var propInfo = this.Properties.FirstOrDefault(p => string.Equals(p.Name, key, StringComparison.OrdinalIgnoreCase));
|
||||
if (propInfo != null)
|
||||
StringUtils.SetPropertyValue(val, this, propInfo);
|
||||
else
|
||||
{
|
||||
propInfo = this.Properties.FirstOrDefault(f => f.GetCustomAttributes(typeof(AggregateIniValueEntryAttribute), false).OfType<AggregateIniValueEntryAttribute>().Any(a => string.Equals(a.Key, key, StringComparison.OrdinalIgnoreCase)));
|
||||
if (propInfo != null)
|
||||
StringUtils.SetPropertyValue(val, this, propInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
GetPropertyInfos();
|
||||
if (this.Properties.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
var result = new StringBuilder();
|
||||
result.Append("(");
|
||||
|
||||
var delimiter = "";
|
||||
foreach (var prop in this.Properties.OrderBy(p => p.Name))
|
||||
{
|
||||
result.Append(delimiter);
|
||||
|
||||
var attr = prop.GetCustomAttributes(typeof(AggregateIniValueEntryAttribute), false).OfType<AggregateIniValueEntryAttribute>().FirstOrDefault();
|
||||
var propName = string.IsNullOrWhiteSpace(attr?.Key) ? prop.Name : attr.Key;
|
||||
|
||||
var val = prop.GetValue(this);
|
||||
var propValue = StringUtils.GetPropertyValue(val, prop);
|
||||
|
||||
result.Append($"{propName}={propValue}");
|
||||
|
||||
delimiter = DELIMITER.ToString();
|
||||
}
|
||||
|
||||
result.Append(")");
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class PGMTerrainXYZ : PGMTerrainXY
|
||||
{
|
||||
public PGMTerrainXYZ()
|
||||
{
|
||||
}
|
||||
public PGMTerrainXYZ(float x, float y, float z)
|
||||
: base(x, y)
|
||||
{
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ZProperty = DependencyProperty.Register(nameof(Z), typeof(float), typeof(PGMTerrainXYZ), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float Z
|
||||
{
|
||||
get { return (float)GetValue(ZProperty); }
|
||||
set { SetValue(ZProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/ARKServerManager/Lib/Model/PlayerListParameters.cs
Normal file
33
src/ARKServerManager/Lib/Model/PlayerListParameters.cs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public class PlayerListParameters : DependencyObject
|
||||
{
|
||||
public static readonly DependencyProperty ProfileNameProperty = DependencyProperty.Register(nameof(ProfileName), typeof(string), typeof(PlayerListParameters), new PropertyMetadata(string.Empty));
|
||||
|
||||
public string ProfileName
|
||||
{
|
||||
get { return (string)GetValue(ProfileNameProperty); }
|
||||
set { SetValue(ProfileNameProperty, value); }
|
||||
}
|
||||
|
||||
public string ProfileId { get; set; }
|
||||
|
||||
public string InstallDirectory { get; set; }
|
||||
|
||||
public string AltSaveDirectoryName { get; set; }
|
||||
|
||||
public bool PGM_Enabled { get; set; }
|
||||
|
||||
public string PGM_Name { get; set; }
|
||||
|
||||
public Server Server { get; set; }
|
||||
|
||||
public string ServerMap { get; set; }
|
||||
|
||||
public Rect WindowExtents { get; set; }
|
||||
|
||||
public string WindowTitle { get; set; }
|
||||
}
|
||||
}
|
||||
503
src/ARKServerManager/Lib/Model/PublishedFileDetail.cs
Normal file
503
src/ARKServerManager/Lib/Model/PublishedFileDetail.cs
Normal file
|
|
@ -0,0 +1,503 @@
|
|||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using WPFSharp.Globalizer;
|
||||
|
||||
namespace ServerManagerTool.Lib.Model
|
||||
{
|
||||
public class ModDetailList : ObservableCollection<ModDetail>
|
||||
{
|
||||
public bool AnyUnknownModTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Any(m => !m.IsValidModType);
|
||||
}
|
||||
}
|
||||
|
||||
public new void Add(ModDetail mod)
|
||||
{
|
||||
if (mod == null || this.Any(m => m.ModId.Equals(mod.ModId)))
|
||||
return;
|
||||
|
||||
base.Add(mod);
|
||||
SetPublishedFileIndex();
|
||||
}
|
||||
|
||||
public void AddRange(ModDetail[] mods)
|
||||
{
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
if (mod == null || this.Any(m => m.ModId.Equals(mod.ModId)))
|
||||
continue;
|
||||
base.Add(mod);
|
||||
}
|
||||
SetPublishedFileIndex();
|
||||
}
|
||||
|
||||
public new void Insert(int index, ModDetail mod)
|
||||
{
|
||||
if (mod == null || this.Any(m => m.ModId.Equals(mod.ModId)))
|
||||
return;
|
||||
|
||||
base.Insert(index, mod);
|
||||
SetPublishedFileIndex();
|
||||
}
|
||||
|
||||
public void Move(ModDetail mod, int newIndex)
|
||||
{
|
||||
if (mod == null)
|
||||
return;
|
||||
|
||||
var index = base.IndexOf(mod);
|
||||
if (index <= 0)
|
||||
return;
|
||||
|
||||
base.Move(index, newIndex);
|
||||
SetPublishedFileIndex();
|
||||
}
|
||||
|
||||
public void MoveDown(ModDetail mod)
|
||||
{
|
||||
if (mod == null)
|
||||
return;
|
||||
|
||||
var index = base.IndexOf(mod);
|
||||
if (index >= base.Count - 1)
|
||||
return;
|
||||
|
||||
base.Move(index, index + 1);
|
||||
SetPublishedFileIndex();
|
||||
}
|
||||
|
||||
public void MoveUp(ModDetail mod)
|
||||
{
|
||||
if (mod == null)
|
||||
return;
|
||||
|
||||
var index = base.IndexOf(mod);
|
||||
if (index <= 0)
|
||||
return;
|
||||
|
||||
base.Move(index, index - 1);
|
||||
SetPublishedFileIndex();
|
||||
}
|
||||
|
||||
public void PopulateExtended(string modsRootFolder)
|
||||
{
|
||||
var results = new Dictionary<ModDetail, ModDetailExtended>();
|
||||
foreach (var mod in this)
|
||||
{
|
||||
results.Add(mod, new ModDetailExtended(mod.ModId));
|
||||
}
|
||||
|
||||
Parallel.ForEach(results, kvp => kvp.Value.PopulateExtended(modsRootFolder));
|
||||
|
||||
foreach (var kvp in results)
|
||||
{
|
||||
kvp.Key.PopulateExtended(kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public new bool Remove(ModDetail mod)
|
||||
{
|
||||
if (mod == null)
|
||||
return false;
|
||||
|
||||
var removed = base.Remove(mod);
|
||||
|
||||
SetPublishedFileIndex();
|
||||
return removed;
|
||||
}
|
||||
|
||||
public void SetPublishedFileIndex()
|
||||
{
|
||||
foreach (var mod in this)
|
||||
{
|
||||
mod.Index = base.IndexOf(mod) + 1;
|
||||
mod.IsFirst = false;
|
||||
mod.IsLast = false;
|
||||
}
|
||||
|
||||
if (this.Count == 0)
|
||||
return;
|
||||
|
||||
this[0].IsFirst = true;
|
||||
this[base.Count - 1].IsLast = true;
|
||||
}
|
||||
|
||||
public bool GetModStrings(out string mapString, out string totalConversionString, out string modIdString)
|
||||
{
|
||||
mapString = null;
|
||||
totalConversionString = null;
|
||||
modIdString = string.Empty;
|
||||
|
||||
var delimiter = "";
|
||||
foreach (var mod in this)
|
||||
{
|
||||
switch (mod.ModType)
|
||||
{
|
||||
case ModUtils.MODTYPE_MAP:
|
||||
mapString = $"/Game/Mods/{mod.ModId}/{mod.MapName}";
|
||||
break;
|
||||
case ModUtils.MODTYPE_TOTCONV:
|
||||
totalConversionString = mod.ModId;
|
||||
break;
|
||||
case ModUtils.MODTYPE_MAPEXT:
|
||||
case ModUtils.MODTYPE_MOD:
|
||||
default:
|
||||
modIdString += $"{delimiter}{mod.ModId}";
|
||||
delimiter = ",";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ModDetailList GetModDetails(List<string> modIdList, string modsRootFolder, WorkshopFileList workshopFiles, PublishedFileDetailsResponse response)
|
||||
{
|
||||
var result = new ModDetailList();
|
||||
|
||||
if (modIdList != null)
|
||||
{
|
||||
foreach (var modId in modIdList)
|
||||
{
|
||||
var temp = workshopFiles?.FirstOrDefault(w => w.WorkshopId.Equals(modId));
|
||||
|
||||
result.Add(new ModDetail()
|
||||
{
|
||||
AppId = temp?.AppId ?? string.Empty,
|
||||
ModId = modId,
|
||||
TimeUpdated = -1,
|
||||
Title = temp?.Title ?? "Mod name not available",
|
||||
IsValid = false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (response?.publishedfiledetails != null)
|
||||
{
|
||||
foreach (var item in result)
|
||||
{
|
||||
var temp = response.publishedfiledetails.FirstOrDefault(w => w.publishedfileid.Equals(item.ModId));
|
||||
|
||||
if (temp != null)
|
||||
{
|
||||
item.AppId = temp?.creator_app_id ?? string.Empty;
|
||||
item.ModId = temp?.publishedfileid ?? item.ModId;
|
||||
item.TimeUpdated = temp?.time_updated ?? item.TimeUpdated;
|
||||
item.Title = temp?.title ?? item.Title;
|
||||
item.IsValid = temp?.creator_app_id != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.SetPublishedFileIndex();
|
||||
result.PopulateExtended(modsRootFolder);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(ModDetailList)} - {Count}";
|
||||
}
|
||||
}
|
||||
|
||||
public class ModDetail : DependencyObject
|
||||
{
|
||||
private readonly GlobalizedApplication _globalizer = GlobalizedApplication.Instance;
|
||||
|
||||
public static readonly DependencyProperty AppIdProperty = DependencyProperty.Register(nameof(AppId), typeof(string), typeof(ModDetail), new PropertyMetadata(string.Empty));
|
||||
public static readonly DependencyProperty IndexProperty = DependencyProperty.Register(nameof(Index), typeof(int), typeof(ModDetail), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty IsFirstProperty = DependencyProperty.Register(nameof(IsFirst), typeof(bool), typeof(ModDetail), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty IsLastProperty = DependencyProperty.Register(nameof(IsLast), typeof(bool), typeof(ModDetail), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty LastWriteTimeProperty = DependencyProperty.Register(nameof(LastWriteTime), typeof(DateTime), typeof(ModDetail), new PropertyMetadata(DateTime.MinValue));
|
||||
public static readonly DependencyProperty LastTimeUpdatedProperty = DependencyProperty.Register(nameof(LastTimeUpdated), typeof(int), typeof(ModDetail), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty ModIdProperty = DependencyProperty.Register(nameof(ModId), typeof(string), typeof(ModDetail), new PropertyMetadata(string.Empty));
|
||||
public static readonly DependencyProperty ModTypeProperty = DependencyProperty.Register(nameof(ModType), typeof(string), typeof(ModDetail), new PropertyMetadata(ModUtils.MODTYPE_UNKNOWN));
|
||||
public static readonly DependencyProperty ModTypeStringProperty = DependencyProperty.Register(nameof(ModTypeString), typeof(string), typeof(ModDetail), new PropertyMetadata(string.Empty));
|
||||
public static readonly DependencyProperty ModUrlProperty = DependencyProperty.Register(nameof(ModUrl), typeof(string), typeof(ModDetail), new PropertyMetadata(string.Empty));
|
||||
public static readonly DependencyProperty TimeUpdatedProperty = DependencyProperty.Register(nameof(TimeUpdated), typeof(int), typeof(ModDetail), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(ModDetail), new PropertyMetadata(string.Empty));
|
||||
public static readonly DependencyProperty IsValidProperty = DependencyProperty.Register(nameof(IsValid), typeof(bool), typeof(ModDetail), new PropertyMetadata(false));
|
||||
|
||||
|
||||
public string AppId
|
||||
{
|
||||
get { return (string)GetValue(AppIdProperty); }
|
||||
set { SetValue(AppIdProperty, value); }
|
||||
}
|
||||
|
||||
public int Index
|
||||
{
|
||||
get { return (int)GetValue(IndexProperty); }
|
||||
set { SetValue(IndexProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsFirst
|
||||
{
|
||||
get { return (bool)GetValue(IsFirstProperty); }
|
||||
set { SetValue(IsFirstProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsLast
|
||||
{
|
||||
get { return (bool)GetValue(IsLastProperty); }
|
||||
set { SetValue(IsLastProperty, value); }
|
||||
}
|
||||
|
||||
public DateTime LastWriteTime
|
||||
{
|
||||
get { return (DateTime)GetValue(LastWriteTimeProperty); }
|
||||
set { SetValue(LastWriteTimeProperty, value); }
|
||||
}
|
||||
|
||||
public int LastTimeUpdated
|
||||
{
|
||||
get { return (int)GetValue(LastTimeUpdatedProperty); }
|
||||
set { SetValue(LastTimeUpdatedProperty, value); }
|
||||
}
|
||||
|
||||
public string ModId
|
||||
{
|
||||
get { return (string)GetValue(ModIdProperty); }
|
||||
set { SetValue(ModIdProperty, value); }
|
||||
}
|
||||
|
||||
public string ModType
|
||||
{
|
||||
get { return (string)GetValue(ModTypeProperty); }
|
||||
set
|
||||
{
|
||||
SetValue(ModTypeProperty, value);
|
||||
SetModTypeString();
|
||||
}
|
||||
}
|
||||
|
||||
public string ModTypeString
|
||||
{
|
||||
get { return (string)GetValue(ModTypeStringProperty); }
|
||||
set { SetValue(ModTypeStringProperty, value); }
|
||||
}
|
||||
|
||||
public int TimeUpdated
|
||||
{
|
||||
get { return (int)GetValue(TimeUpdatedProperty); }
|
||||
set { SetValue(TimeUpdatedProperty, value); }
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get { return (string)GetValue(TitleProperty); }
|
||||
set
|
||||
{
|
||||
SetValue(TitleProperty, value);
|
||||
|
||||
TitleFilterString = value?.ToLower();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValid
|
||||
{
|
||||
get { return (bool)GetValue(IsValidProperty); }
|
||||
set { SetValue(IsValidProperty, value); }
|
||||
}
|
||||
|
||||
|
||||
public bool IsOfficialMod => ModUtils.IsOfficialMod(ModId);
|
||||
|
||||
public bool IsValidModType => !string.IsNullOrWhiteSpace(ModType) && (ModType.Equals(ModUtils.MODTYPE_MAP) || ModType.Equals(ModUtils.MODTYPE_MAPEXT) || ModType.Equals(ModUtils.MODTYPE_MOD) || ModType.Equals(ModUtils.MODTYPE_TOTCONV));
|
||||
|
||||
public string LastWriteTimeString => LastWriteTime == DateTime.MinValue ? string.Empty : LastWriteTime.ToString();
|
||||
|
||||
public string LastWriteTimeSortString => LastWriteTime == DateTime.MinValue ? string.Empty : LastWriteTime.ToString("yyyyMMdd_HHmmss");
|
||||
|
||||
public string MapName { get; set; }
|
||||
|
||||
public string ModUrl => $"http://steamcommunity.com/sharedfiles/filedetails/?id={ModId}";
|
||||
|
||||
public string TimeUpdatedString => TimeUpdated <= 0 ? string.Empty : ModUtils.UnixTimeStampToDateTime(TimeUpdated).ToString();
|
||||
|
||||
public string TimeUpdatedSortString => TimeUpdated <= 0 ? string.Empty : ModUtils.UnixTimeStampToDateTime(TimeUpdated).ToString("yyyyMMdd_HHmmss");
|
||||
|
||||
public string TitleFilterString
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool UpToDate => !IsValid && TimeUpdated == -1 || LastTimeUpdated > 0 && LastTimeUpdated == TimeUpdated;
|
||||
|
||||
public long FolderSize { get; set; }
|
||||
|
||||
public string FolderSizeString
|
||||
{
|
||||
get
|
||||
{
|
||||
// GB
|
||||
var divisor = Math.Pow(1024, 3);
|
||||
if (FolderSize > divisor)
|
||||
return $"{FolderSize / divisor:N2} GB";
|
||||
|
||||
// MB
|
||||
divisor = Math.Pow(1024, 2);
|
||||
if (FolderSize > divisor)
|
||||
return $"{FolderSize / divisor:N2} MB";
|
||||
|
||||
// KB
|
||||
divisor = Math.Pow(1024, 1);
|
||||
if (FolderSize > divisor)
|
||||
return $"{FolderSize / divisor:N2} KB";
|
||||
|
||||
return $"{FolderSize} B";
|
||||
}
|
||||
}
|
||||
|
||||
public void PopulateExtended(string modsRootFolder)
|
||||
{
|
||||
var modExtended = new ModDetailExtended(ModId);
|
||||
modExtended.PopulateExtended(modsRootFolder);
|
||||
PopulateExtended(modExtended);
|
||||
}
|
||||
|
||||
public void PopulateExtended(ModDetailExtended extended)
|
||||
{
|
||||
LastTimeUpdated = extended.LastTimeUpdated;
|
||||
LastWriteTime = extended.LastWriteTime;
|
||||
MapName = extended.MapName;
|
||||
ModType = extended.ModType;
|
||||
FolderSize = extended.FolderSize;
|
||||
}
|
||||
|
||||
public void SetModTypeString()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ModType))
|
||||
ModTypeString = _globalizer.GetResourceString("ModType_Unknown");
|
||||
|
||||
switch (ModType)
|
||||
{
|
||||
case ModUtils.MODTYPE_MAP:
|
||||
ModTypeString = _globalizer.GetResourceString("ModType_Map");
|
||||
break;
|
||||
case ModUtils.MODTYPE_MAPEXT:
|
||||
ModTypeString = _globalizer.GetResourceString("ModType_MapExtension");
|
||||
break;
|
||||
case ModUtils.MODTYPE_MOD:
|
||||
ModTypeString = _globalizer.GetResourceString("ModType_Mod");
|
||||
break;
|
||||
case ModUtils.MODTYPE_TOTCONV:
|
||||
ModTypeString = _globalizer.GetResourceString("ModType_TotalConversion");
|
||||
break;
|
||||
default:
|
||||
if (string.IsNullOrWhiteSpace(AppId))
|
||||
ModTypeString = _globalizer.GetResourceString("ModType_Unknown");
|
||||
else
|
||||
ModTypeString = _globalizer.GetResourceString("ModType_NotDownloaded");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static ModDetail GetModDetail(PublishedFileDetail detail)
|
||||
{
|
||||
var result = new ModDetail();
|
||||
result.AppId = detail.creator_app_id;
|
||||
result.ModId = detail.publishedfileid;
|
||||
result.TimeUpdated = detail.time_updated;
|
||||
result.Title = detail.title;
|
||||
result.IsValid = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ModDetail GetModDetail(WorkshopFileDetail detail)
|
||||
{
|
||||
var result = new ModDetail();
|
||||
result.AppId = detail.creator_appid;
|
||||
result.ModId = detail.publishedfileid;
|
||||
result.TimeUpdated = detail.time_updated;
|
||||
result.Title = detail.title;
|
||||
result.IsValid = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ModDetail GetModDetail(WorkshopFileItem detail)
|
||||
{
|
||||
var result = new ModDetail();
|
||||
result.AppId = detail.AppId;
|
||||
result.ModId = detail.WorkshopId;
|
||||
result.TimeUpdated = detail.TimeUpdated;
|
||||
result.Title = detail.Title;
|
||||
result.IsValid = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{ModId} - {Title}";
|
||||
}
|
||||
}
|
||||
|
||||
public class ModDetailExtended
|
||||
{
|
||||
public ModDetailExtended(string modId)
|
||||
{
|
||||
ModId = modId;
|
||||
}
|
||||
|
||||
public string MapName { get; set; }
|
||||
|
||||
private string ModId { get; set; }
|
||||
|
||||
public string ModType { get; set; }
|
||||
|
||||
public DateTime LastWriteTime { get; set; }
|
||||
|
||||
public int LastTimeUpdated { get; set; }
|
||||
|
||||
public long FolderSize { get; set; }
|
||||
|
||||
public void PopulateExtended(string modsRootFolder)
|
||||
{
|
||||
try
|
||||
{
|
||||
var modFolder = Path.Combine(modsRootFolder, ModId);
|
||||
var modFile = $"{modFolder}.mod";
|
||||
|
||||
if (string.IsNullOrWhiteSpace(modFolder) || !Directory.Exists(modFolder))
|
||||
return;
|
||||
if (string.IsNullOrWhiteSpace(modFile) || !File.Exists(modFile))
|
||||
return;
|
||||
|
||||
LastWriteTime = File.GetLastWriteTime(modFile);
|
||||
|
||||
var modTimeFile = Path.Combine(modFolder, Config.Default.LastUpdatedTimeFile);
|
||||
if (!string.IsNullOrWhiteSpace(modTimeFile) && File.Exists(modTimeFile))
|
||||
{
|
||||
LastTimeUpdated = ModUtils.GetModLatestTime(modTimeFile);
|
||||
}
|
||||
|
||||
ModUtils.ReadModFile(modFile, out string modId, out Dictionary<string, string> metaInformation, out List<string> mapNames);
|
||||
|
||||
ModType = metaInformation != null && metaInformation.ContainsKey("ModType") ? metaInformation["ModType"] : ModUtils.MODTYPE_UNKNOWN;
|
||||
MapName = mapNames != null && mapNames.Count > 0 ? mapNames[0] : string.Empty;
|
||||
|
||||
FolderSize = 0;
|
||||
foreach (var file in new DirectoryInfo(modFolder).GetFiles("*.*", SearchOption.AllDirectories))
|
||||
{
|
||||
FolderSize += file.Length;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/ARKServerManager/Lib/Model/RCONParameters.cs
Normal file
40
src/ARKServerManager/Lib/Model/RCONParameters.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
using System.Net;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public class RCONParameters : PlayerListParameters
|
||||
{
|
||||
public static readonly DependencyProperty MaxPlayersProperty = DependencyProperty.Register(nameof(MaxPlayers), typeof(int), typeof(RCONParameters), new PropertyMetadata(0));
|
||||
|
||||
public string RCONHost { get; set; }
|
||||
|
||||
public IPAddress RCONHostIP
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
var ipAddresses = Dns.GetHostAddresses(RCONHost);
|
||||
if (ipAddresses.Length > 0)
|
||||
return ipAddresses[0].MapToIPv4();
|
||||
}
|
||||
catch {}
|
||||
|
||||
return IPAddress.None;
|
||||
}
|
||||
}
|
||||
|
||||
public int RCONPort { get; set; }
|
||||
|
||||
public string AdminPassword { get; set; }
|
||||
|
||||
public int MaxPlayers
|
||||
{
|
||||
get { return (int)GetValue(MaxPlayersProperty); }
|
||||
set { SetValue(MaxPlayersProperty, value); }
|
||||
}
|
||||
|
||||
public double PlayerListWidth { get; set; }
|
||||
}
|
||||
}
|
||||
105
src/ARKServerManager/Lib/Model/ResourceClassMultiplier.cs
Normal file
105
src/ARKServerManager/Lib/Model/ResourceClassMultiplier.cs
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
public class ResourceClassMultiplierList : AggregateIniValueList<ResourceClassMultiplier>
|
||||
{
|
||||
public ResourceClassMultiplierList(string aggregateValueName, Func<IEnumerable<ResourceClassMultiplier>> resetFunc)
|
||||
: base(aggregateValueName, resetFunc)
|
||||
{
|
||||
}
|
||||
|
||||
public override void FromIniValues(IEnumerable<string> iniValues)
|
||||
{
|
||||
var items = iniValues?.Select(AggregateIniValue.FromINIValue<ResourceClassMultiplier>).ToArray();
|
||||
|
||||
Clear();
|
||||
if (this._resetFunc != null)
|
||||
this.AddRange(this._resetFunc());
|
||||
|
||||
var itemsToAdd = items.Where(i => !this.Any(r => r.IsEquivalent(i))).ToArray();
|
||||
AddRange(itemsToAdd);
|
||||
|
||||
var itemsToUpdate = items.Where(i => this.Any(r => r.IsEquivalent(i))).ToArray();
|
||||
foreach (var item in itemsToUpdate)
|
||||
{
|
||||
this.FirstOrDefault(r => r.IsEquivalent(item)).Multiplier = item.Multiplier;
|
||||
}
|
||||
|
||||
IsEnabled = (items.Length > 0);
|
||||
|
||||
Sort(AggregateIniValue.SortKeySelector);
|
||||
}
|
||||
|
||||
public override IEnumerable<string> ToIniValues()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(IniCollectionKey))
|
||||
return this.Where(d => d.ShouldSave()).Select(d => d.ToINIValue());
|
||||
|
||||
return this.Where(d => d.ShouldSave()).Select(d => $"{this.IniCollectionKey}={d.ToINIValue()}");
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class ResourceClassMultiplier : ClassMultiplier
|
||||
{
|
||||
public static readonly DependencyProperty ModProperty = DependencyProperty.Register(nameof(Mod), typeof(string), typeof(ResourceClassMultiplier), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty KnownResourceProperty = DependencyProperty.Register(nameof(KnownResource), typeof(bool), typeof(ResourceClassMultiplier), new PropertyMetadata(false));
|
||||
|
||||
[DataMember]
|
||||
public string Mod
|
||||
{
|
||||
get { return (string)GetValue(ModProperty); }
|
||||
set { SetValue(ModProperty, value); }
|
||||
}
|
||||
|
||||
public bool KnownResource
|
||||
{
|
||||
get { return (bool)GetValue(KnownResourceProperty); }
|
||||
set { SetValue(KnownResourceProperty, value); }
|
||||
}
|
||||
|
||||
public override string DisplayName => GameData.FriendlyResourceNameForClass(ClassName);
|
||||
|
||||
public string DisplayMod => GameData.FriendlyNameForClass($"Mod_{Mod}", true) ?? Mod;
|
||||
|
||||
public new static ResourceClassMultiplier FromINIValue(string iniValue)
|
||||
{
|
||||
var newSpawn = new ResourceClassMultiplier();
|
||||
newSpawn.InitializeFromINIValue(iniValue);
|
||||
return newSpawn;
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return $"{DisplayName}|Mod";
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
base.InitializeFromINIValue(value);
|
||||
|
||||
if (!KnownResource)
|
||||
Mod = GameData.MOD_UNKNOWN;
|
||||
}
|
||||
|
||||
public override bool ShouldSave()
|
||||
{
|
||||
if (!KnownResource)
|
||||
return true;
|
||||
|
||||
var resource = GameData.GetResourceMultiplierForClass(ClassName);
|
||||
if (resource == null)
|
||||
return true;
|
||||
|
||||
return (!resource.Multiplier.Equals(Multiplier));
|
||||
}
|
||||
}
|
||||
}
|
||||
184
src/ARKServerManager/Lib/Model/StackSizeOverride.cs
Normal file
184
src/ARKServerManager/Lib/Model/StackSizeOverride.cs
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
using ServerManagerTool.Common.Attibutes;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
public class StackSizeOverrideList : AggregateIniValueList<StackSizeOverride>
|
||||
{
|
||||
public StackSizeOverrideList(string aggregateValueName)
|
||||
: base(aggregateValueName, null)
|
||||
{
|
||||
}
|
||||
|
||||
public string[] RenderToView()
|
||||
{
|
||||
List<string> errors = new List<string>();
|
||||
|
||||
foreach (var stackSize in this)
|
||||
{
|
||||
if (stackSize.Quantity != null)
|
||||
{
|
||||
stackSize.IgnoreMultiplier = stackSize.Quantity.IgnoreMultiplier;
|
||||
stackSize.MaxItemQuantity = stackSize.Quantity.MaxItemQuantity;
|
||||
}
|
||||
}
|
||||
|
||||
return errors.ToArray();
|
||||
}
|
||||
|
||||
public void RenderToModel()
|
||||
{
|
||||
foreach (var stackSize in this)
|
||||
{
|
||||
if (stackSize.Quantity != null)
|
||||
{
|
||||
stackSize.Quantity.IgnoreMultiplier = stackSize.IgnoreMultiplier;
|
||||
stackSize.Quantity.MaxItemQuantity = stackSize.MaxItemQuantity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateForLocalization()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class StackSizeOverride : AggregateIniValue
|
||||
{
|
||||
public StackSizeOverride()
|
||||
{
|
||||
Quantity = new StackSizeQuantity();
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemClassStringProperty = DependencyProperty.Register(nameof(ItemClassString), typeof(string), typeof(StackSizeOverride), new PropertyMetadata(string.Empty));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public string ItemClassString
|
||||
{
|
||||
get { return (string)GetValue(ItemClassStringProperty); }
|
||||
set { SetValue(ItemClassStringProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IgnoreMultiplierProperty = DependencyProperty.Register(nameof(IgnoreMultiplier), typeof(bool), typeof(StackSizeOverride), new PropertyMetadata(true));
|
||||
public bool IgnoreMultiplier
|
||||
{
|
||||
get { return (bool)GetValue(IgnoreMultiplierProperty); }
|
||||
set { SetValue(IgnoreMultiplierProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MaxItemQuantityProperty = DependencyProperty.Register(nameof(MaxItemQuantity), typeof(int), typeof(StackSizeOverride), new PropertyMetadata(1));
|
||||
public int MaxItemQuantity
|
||||
{
|
||||
get { return (int)GetValue(MaxItemQuantityProperty); }
|
||||
set { SetValue(MaxItemQuantityProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public StackSizeQuantity Quantity
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return;
|
||||
|
||||
var kvPair = value.Split(new[] { '=' }, 2);
|
||||
var kvValue = kvPair[1].Trim(' ');
|
||||
if (kvValue.StartsWith("("))
|
||||
kvValue = kvValue.Substring(1);
|
||||
if (kvValue.EndsWith(")"))
|
||||
kvValue = kvValue.Substring(0, kvValue.Length - 1);
|
||||
|
||||
base.FromComplexINIValue(kvValue);
|
||||
|
||||
if (Quantity != null)
|
||||
{
|
||||
IgnoreMultiplier = Quantity.IgnoreMultiplier;
|
||||
MaxItemQuantity = Quantity.MaxItemQuantity;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
if (Quantity != null)
|
||||
{
|
||||
Quantity.IgnoreMultiplier = IgnoreMultiplier;
|
||||
Quantity.MaxItemQuantity = MaxItemQuantity;
|
||||
}
|
||||
|
||||
return base.ToComplexINIValue(true);
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlyItemNameForClass(ItemClassString);
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(ItemClassString);
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class StackSizeQuantity : AggregateIniValue
|
||||
{
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public int MaxItemQuantity
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "bIgnoreMultiplier")]
|
||||
public bool IgnoreMultiplier
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return;
|
||||
|
||||
var kvValue = value;
|
||||
if (kvValue.StartsWith("("))
|
||||
kvValue = kvValue.Substring(1);
|
||||
if (kvValue.EndsWith(")"))
|
||||
kvValue = kvValue.Substring(0, kvValue.Length - 1);
|
||||
|
||||
base.FromComplexINIValue(kvValue);
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
return base.ToComplexINIValue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
88
src/ARKServerManager/Lib/Model/StatsMultiplierArray.cs
Normal file
88
src/ARKServerManager/Lib/Model/StatsMultiplierArray.cs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
using ServerManagerTool.Common.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ServerManagerTool.Lib.Model
|
||||
{
|
||||
public class StatsMultiplierArray : FloatIniValueArray
|
||||
{
|
||||
protected StatsMultiplierArray(string iniKeyName, Func<IEnumerable<float>> resetFunc, bool[] inclusions)
|
||||
: base(iniKeyName, resetFunc)
|
||||
{
|
||||
Inclusions = inclusions;
|
||||
}
|
||||
|
||||
public StatsMultiplierArray(string iniKeyName, Func<IEnumerable<float>> resetFunc, bool[] inclusions, bool onlyWriteNonDefaults)
|
||||
: base(iniKeyName, resetFunc)
|
||||
{
|
||||
Inclusions = inclusions;
|
||||
|
||||
if (onlyWriteNonDefaults && resetFunc != null)
|
||||
{
|
||||
DefaultValues = new StatsMultiplierArray(iniKeyName, null, inclusions);
|
||||
DefaultValues.AddRange(resetFunc());
|
||||
}
|
||||
}
|
||||
|
||||
public bool[] Inclusions { get; private set; } = null;
|
||||
|
||||
private StatsMultiplierArray DefaultValues { get; set; } = null;
|
||||
|
||||
public override void FromIniValues(IEnumerable<string> values)
|
||||
{
|
||||
this.Clear();
|
||||
|
||||
var list = new List<float>();
|
||||
if (this.ResetFunc != null)
|
||||
list.AddRange(this.ResetFunc());
|
||||
|
||||
foreach (var v in values)
|
||||
{
|
||||
var indexStart = v.IndexOf('[');
|
||||
var indexEnd = v.IndexOf(']');
|
||||
|
||||
if (indexStart >= indexEnd)
|
||||
{
|
||||
// Invalid format
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!int.TryParse(v.Substring(indexStart + 1, indexEnd - indexStart - 1), out int index))
|
||||
{
|
||||
// Invalid index
|
||||
continue;
|
||||
}
|
||||
|
||||
if (index >= list.Count)
|
||||
{
|
||||
// Unexpected size
|
||||
continue;
|
||||
}
|
||||
|
||||
list[index] = this.FromIniValue(v.Substring(v.IndexOf('=') + 1).Trim());
|
||||
this.IsEnabled = true;
|
||||
}
|
||||
|
||||
this.AddRange(list);
|
||||
}
|
||||
|
||||
public override IEnumerable<string> ToIniValues()
|
||||
{
|
||||
var values = new List<string>();
|
||||
for (var i = 0; i < this.Count; i++)
|
||||
{
|
||||
if (!(Inclusions?.ElementAtOrDefault(i) ?? true))
|
||||
continue;
|
||||
if (DefaultValues != null && Equals(DefaultValues[i], this[i]))
|
||||
continue;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(IniCollectionKey))
|
||||
values.Add(this.ToIniValue(this[i]));
|
||||
else
|
||||
values.Add($"{this.IniCollectionKey}[{i}]={this.ToIniValue(this[i])}");
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
src/ARKServerManager/Lib/Model/StatsMultipliers.cs
Normal file
34
src/ARKServerManager/Lib/Model/StatsMultipliers.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
public class StatsMultipliers
|
||||
{
|
||||
[DataMember]
|
||||
public float Player
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public float WildDino
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public float TamedDino
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
418
src/ARKServerManager/Lib/Model/SupplyCrateOverride.cs
Normal file
418
src/ARKServerManager/Lib/Model/SupplyCrateOverride.cs
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
using ServerManagerTool.Common.Attibutes;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Lib.ViewModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
[DataContract]
|
||||
public class SupplyCrateOverrideList : AggregateIniValueList<SupplyCrateOverride>
|
||||
{
|
||||
public SupplyCrateOverrideList(string aggregateValueName)
|
||||
: base(aggregateValueName, null)
|
||||
{
|
||||
}
|
||||
|
||||
public string[] RenderToView()
|
||||
{
|
||||
List<string> errors = new List<string>();
|
||||
|
||||
foreach (var supplyCrate in this)
|
||||
{
|
||||
foreach (var itemSet in supplyCrate.ItemSets)
|
||||
{
|
||||
foreach (var itemEntry in itemSet.ItemEntries)
|
||||
{
|
||||
itemEntry.Items = new ObservableCollection<SupplyCrateItemEntrySettings>();
|
||||
|
||||
for (var index = 0; index < itemEntry.ItemClassStrings.Count; index++)
|
||||
{
|
||||
var itemsWeight = 0.0f;
|
||||
if (index < itemEntry.ItemsWeights.Count)
|
||||
itemsWeight = itemEntry.ItemsWeights[index];
|
||||
else
|
||||
errors.Add($"Missing Supply Crate Item Weight: Crate '{supplyCrate.SupplyCrateClassString}'; Set '{itemSet.SetName}'; Entry '{itemEntry.ItemEntryName}'; Item '{itemEntry.ItemClassStrings[index]}'.");
|
||||
|
||||
itemEntry.Items.Add(new SupplyCrateItemEntrySettings {
|
||||
ItemClassString = itemEntry.ItemClassStrings[index],
|
||||
ItemWeight = itemsWeight,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors.ToArray();
|
||||
}
|
||||
|
||||
public void RenderToModel()
|
||||
{
|
||||
foreach (var supplyCrate in this)
|
||||
{
|
||||
foreach (var itemSet in supplyCrate.ItemSets)
|
||||
{
|
||||
foreach (var itemEntry in itemSet.ItemEntries)
|
||||
{
|
||||
itemEntry.ItemClassStrings = new StringIniValueList(null, null);
|
||||
itemEntry.ItemsWeights = new FloatIniValueList(null, null);
|
||||
|
||||
foreach (var itemClass in itemEntry.Items)
|
||||
{
|
||||
itemEntry.ItemClassStrings.Add(itemClass.ItemClassString);
|
||||
itemEntry.ItemsWeights.Add(itemClass.ItemWeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateForLocalization()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class SupplyCrateOverride : AggregateIniValue
|
||||
{
|
||||
public SupplyCrateOverride()
|
||||
{
|
||||
ItemSets = new AggregateIniValueList<SupplyCrateItemSet>(null, null);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SupplyCrateClassStringProperty = DependencyProperty.Register(nameof(SupplyCrateClassString), typeof(string), typeof(SupplyCrateOverride), new PropertyMetadata(string.Empty));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public string SupplyCrateClassString
|
||||
{
|
||||
get { return (string)GetValue(SupplyCrateClassStringProperty); }
|
||||
set { SetValue(SupplyCrateClassStringProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MinItemSetsProperty = DependencyProperty.Register(nameof(MinItemSets), typeof(float), typeof(SupplyCrateOverride), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MinItemSets
|
||||
{
|
||||
get { return (float)GetValue(MinItemSetsProperty); }
|
||||
set { SetValue(MinItemSetsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MaxItemSetsProperty = DependencyProperty.Register(nameof(MaxItemSets), typeof(float), typeof(SupplyCrateOverride), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MaxItemSets
|
||||
{
|
||||
get { return (float)GetValue(MaxItemSetsProperty); }
|
||||
set { SetValue(MaxItemSetsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NumItemSetsPowerProperty = DependencyProperty.Register(nameof(NumItemSetsPower), typeof(float), typeof(SupplyCrateOverride), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float NumItemSetsPower
|
||||
{
|
||||
get { return (float)GetValue(NumItemSetsPowerProperty); }
|
||||
set { SetValue(NumItemSetsPowerProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SetsRandomWithoutReplacementProperty = DependencyProperty.Register(nameof(SetsRandomWithoutReplacement), typeof(bool), typeof(SupplyCrateOverride), new PropertyMetadata(true));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "bSetsRandomWithoutReplacement")]
|
||||
public bool SetsRandomWithoutReplacement
|
||||
{
|
||||
get { return (bool)GetValue(SetsRandomWithoutReplacementProperty); }
|
||||
set { SetValue(SetsRandomWithoutReplacementProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty AppendItemSetsProperty = DependencyProperty.Register(nameof(AppendItemSets), typeof(bool), typeof(SupplyCrateOverride), new PropertyMetadata(false));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "bAppendItemSets", ExcludeIfFalse = true)]
|
||||
public bool AppendItemSets
|
||||
{
|
||||
get { return (bool)GetValue(AppendItemSetsProperty); }
|
||||
set { SetValue(AppendItemSetsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty AppendPreventIncreasingMinMaxItemSetsProperty = DependencyProperty.Register(nameof(AppendPreventIncreasingMinMaxItemSets), typeof(bool), typeof(SupplyCrateOverride), new PropertyMetadata(false));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "bAppendPreventIncreasingMinMaxItemSets", ExcludeIfFalse = true)]
|
||||
public bool AppendPreventIncreasingMinMaxItemSets
|
||||
{
|
||||
get { return (bool)GetValue(AppendPreventIncreasingMinMaxItemSetsProperty); }
|
||||
set { SetValue(AppendPreventIncreasingMinMaxItemSetsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemSetsProperty = DependencyProperty.Register(nameof(ItemSets), typeof(AggregateIniValueList<SupplyCrateItemSet>), typeof(SupplyCrateOverride), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(ValueWithinBrackets = true, ListValueWithinBrackets = true, BracketsAroundValueDelimiter = 2)]
|
||||
public AggregateIniValueList<SupplyCrateItemSet> ItemSets
|
||||
{
|
||||
get { return (AggregateIniValueList<SupplyCrateItemSet>)GetValue(ItemSetsProperty); }
|
||||
set { SetValue(ItemSetsProperty, value); }
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return;
|
||||
|
||||
var kvPair = value.Split(new[] { '=' }, 2);
|
||||
var kvValue = kvPair[1].Trim(' ');
|
||||
if (kvValue.StartsWith("("))
|
||||
kvValue = kvValue.Substring(1);
|
||||
if (kvValue.EndsWith(")"))
|
||||
kvValue = kvValue.Substring(0, kvValue.Length - 1);
|
||||
|
||||
base.FromComplexINIValue(kvValue);
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
return base.ToComplexINIValue(true);
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlySupplyCrateNameForClass(SupplyCrateClassString);
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(SupplyCrateClassString) && ItemSets.Count > 0;
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class SupplyCrateItemSet : AggregateIniValue
|
||||
{
|
||||
public SupplyCrateItemSet()
|
||||
{
|
||||
ItemEntries = new AggregateIniValueList<SupplyCrateItemSetEntry>(null, null);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SetNameProperty = DependencyProperty.Register(nameof(SetName), typeof(string), typeof(SupplyCrateItemSet), new PropertyMetadata(string.Empty));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(ExcludeIfEmpty = true)]
|
||||
public string SetName
|
||||
{
|
||||
get { return (string)GetValue(SetNameProperty); }
|
||||
set { SetValue(SetNameProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MinNumItemsProperty = DependencyProperty.Register(nameof(MinNumItems), typeof(float), typeof(SupplyCrateItemSet), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MinNumItems
|
||||
{
|
||||
get { return (float)GetValue(MinNumItemsProperty); }
|
||||
set { SetValue(MinNumItemsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MaxNumItemsProperty = DependencyProperty.Register(nameof(MaxNumItems), typeof(float), typeof(SupplyCrateItemSet), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MaxNumItems
|
||||
{
|
||||
get { return (float)GetValue(MaxNumItemsProperty); }
|
||||
set { SetValue(MaxNumItemsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NumItemsPowerProperty = DependencyProperty.Register(nameof(NumItemsPower), typeof(float), typeof(SupplyCrateItemSet), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float NumItemsPower
|
||||
{
|
||||
get { return (float)GetValue(NumItemsPowerProperty); }
|
||||
set { SetValue(NumItemsPowerProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SetWeightProperty = DependencyProperty.Register(nameof(SetWeight), typeof(float), typeof(SupplyCrateItemSet), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float SetWeight
|
||||
{
|
||||
get { return (float)GetValue(SetWeightProperty); }
|
||||
set { SetValue(SetWeightProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemsRandomWithoutReplacementProperty = DependencyProperty.Register(nameof(ItemsRandomWithoutReplacement), typeof(bool), typeof(SupplyCrateItemSet), new PropertyMetadata(true));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "bItemsRandomWithoutReplacement")]
|
||||
public bool ItemsRandomWithoutReplacement
|
||||
{
|
||||
get { return (bool)GetValue(ItemsRandomWithoutReplacementProperty); }
|
||||
set { SetValue(ItemsRandomWithoutReplacementProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemEntriesProperty = DependencyProperty.Register(nameof(ItemEntries), typeof(AggregateIniValueList<SupplyCrateItemSetEntry>), typeof(SupplyCrateItemSet), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(ValueWithinBrackets = true, ListValueWithinBrackets = true)]
|
||||
public AggregateIniValueList<SupplyCrateItemSetEntry> ItemEntries
|
||||
{
|
||||
get { return (AggregateIniValueList<SupplyCrateItemSetEntry>)GetValue(ItemEntriesProperty); }
|
||||
set { SetValue(ItemEntriesProperty, value); }
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
base.FromComplexINIValue(value);
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
return base.ToComplexINIValue(false);
|
||||
}
|
||||
|
||||
public bool IsValid => ItemEntries.Count > 0;
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class SupplyCrateItemSetEntry : AggregateIniValue
|
||||
{
|
||||
public SupplyCrateItemSetEntry()
|
||||
{
|
||||
ItemClassStrings = new StringIniValueList(null, null);
|
||||
ItemsWeights = new FloatIniValueList(null, null);
|
||||
|
||||
Items = new ObservableCollection<SupplyCrateItemEntrySettings>();
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemEntryNameProperty = DependencyProperty.Register(nameof(ItemEntryName), typeof(string), typeof(SupplyCrateItemSetEntry), new PropertyMetadata(string.Empty));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(ExcludeIfEmpty = true)]
|
||||
public string ItemEntryName
|
||||
{
|
||||
get { return (string)GetValue(ItemEntryNameProperty); }
|
||||
set { SetValue(ItemEntryNameProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EntryWeightProperty = DependencyProperty.Register(nameof(EntryWeight), typeof(float), typeof(SupplyCrateItemSetEntry), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float EntryWeight
|
||||
{
|
||||
get { return (float)GetValue(EntryWeightProperty); }
|
||||
set { SetValue(EntryWeightProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MinQuantityProperty = DependencyProperty.Register(nameof(MinQuantity), typeof(float), typeof(SupplyCrateItemSetEntry), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MinQuantity
|
||||
{
|
||||
get { return (float)GetValue(MinQuantityProperty); }
|
||||
set { SetValue(MinQuantityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MaxQuantityProperty = DependencyProperty.Register(nameof(MaxQuantity), typeof(float), typeof(SupplyCrateItemSetEntry), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MaxQuantity
|
||||
{
|
||||
get { return (float)GetValue(MaxQuantityProperty); }
|
||||
set { SetValue(MaxQuantityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MinQualityProperty = DependencyProperty.Register(nameof(MinQuality), typeof(float), typeof(SupplyCrateItemSetEntry), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MinQuality
|
||||
{
|
||||
get { return (float)GetValue(MinQualityProperty); }
|
||||
set { SetValue(MinQualityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MaxQualityProperty = DependencyProperty.Register(nameof(MaxQuality), typeof(float), typeof(SupplyCrateItemSetEntry), new PropertyMetadata(1.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float MaxQuality
|
||||
{
|
||||
get { return (float)GetValue(MaxQualityProperty); }
|
||||
set { SetValue(MaxQualityProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ForceBlueprintProperty = DependencyProperty.Register(nameof(ForceBlueprint), typeof(bool), typeof(SupplyCrateItemSetEntry), new PropertyMetadata(false));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(Key = "bForceBlueprint")]
|
||||
public bool ForceBlueprint
|
||||
{
|
||||
get { return (bool)GetValue(ForceBlueprintProperty); }
|
||||
set { SetValue(ForceBlueprintProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ChanceToBeBlueprintOverrideProperty = DependencyProperty.Register(nameof(ChanceToBeBlueprintOverride), typeof(float), typeof(SupplyCrateItemSetEntry), new PropertyMetadata(0.0f));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry]
|
||||
public float ChanceToBeBlueprintOverride
|
||||
{
|
||||
get { return (float)GetValue(ChanceToBeBlueprintOverrideProperty); }
|
||||
set { SetValue(ChanceToBeBlueprintOverrideProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemClassStringsProperty = DependencyProperty.Register(nameof(ItemClassStrings), typeof(StringIniValueList), typeof(SupplyCrateItemSetEntry), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(ValueWithinBrackets = true)]
|
||||
public StringIniValueList ItemClassStrings
|
||||
{
|
||||
get { return (StringIniValueList)GetValue(ItemClassStringsProperty); }
|
||||
set { SetValue(ItemClassStringsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemsWeightsProperty = DependencyProperty.Register(nameof(ItemsWeights), typeof(FloatIniValueList), typeof(SupplyCrateItemSetEntry), new PropertyMetadata(null));
|
||||
[DataMember]
|
||||
[AggregateIniValueEntry(ValueWithinBrackets = true)]
|
||||
public FloatIniValueList ItemsWeights
|
||||
{
|
||||
get { return (FloatIniValueList)GetValue(ItemsWeightsProperty); }
|
||||
set { SetValue(ItemsWeightsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(nameof(Items), typeof(ObservableCollection<SupplyCrateItemEntrySettings>), typeof(SupplyCrateItemSetEntry), new PropertyMetadata(null));
|
||||
public ObservableCollection<SupplyCrateItemEntrySettings> Items
|
||||
{
|
||||
get { return (ObservableCollection<SupplyCrateItemEntrySettings>)GetValue(ItemsProperty); }
|
||||
set { SetValue(ItemsProperty, value); }
|
||||
}
|
||||
|
||||
public override string GetSortKey()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool IsEquivalent(AggregateIniValue other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void InitializeFromINIValue(string value)
|
||||
{
|
||||
base.FromComplexINIValue(value);
|
||||
}
|
||||
|
||||
public override string ToINIValue()
|
||||
{
|
||||
return base.ToComplexINIValue(false);
|
||||
}
|
||||
|
||||
public bool IsModelValid => ItemClassStrings.Count > 0 && ItemClassStrings.Count == ItemsWeights.Count;
|
||||
|
||||
public bool IsViewValid => Items.Count > 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using ServerManagerTool.Common.Attibutes;
|
||||
using ServerManagerTool.Enums;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public class IniFileEntryAttribute : BaseIniFileEntryAttribute
|
||||
{
|
||||
public IniFileEntryAttribute(IniFiles file, IniSections section, ServerProfileCategory category, string key = "")
|
||||
: base(file, section, category, key)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/ARKServerManager/Lib/Serialization/IniFiles.cs
Normal file
9
src/ARKServerManager/Lib/Serialization/IniFiles.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public enum IniFiles
|
||||
{
|
||||
Engine,
|
||||
Game,
|
||||
GameUserSettings,
|
||||
}
|
||||
}
|
||||
20
src/ARKServerManager/Lib/Serialization/IniSections.cs
Normal file
20
src/ARKServerManager/Lib/Serialization/IniSections.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public enum IniSections
|
||||
{
|
||||
// GameUserSettings.ini
|
||||
GUS_ServerSettings,
|
||||
GUS_ShooterGameUserSettings,
|
||||
GUS_ScalabilityGroups,
|
||||
GUS_SessionSettings,
|
||||
GUS_GameSession,
|
||||
GUS_MultiHome,
|
||||
GUS_MessageOfTheDay,
|
||||
|
||||
// Game.ini
|
||||
Game_ShooterGameMode,
|
||||
|
||||
// Misc
|
||||
Custom,
|
||||
}
|
||||
}
|
||||
44
src/ARKServerManager/Lib/Serialization/SystemIniFile.cs
Normal file
44
src/ARKServerManager/Lib/Serialization/SystemIniFile.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
using ServerManagerTool.Common.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public class SystemIniFile : BaseSystemIniFile
|
||||
{
|
||||
public static readonly Dictionary<Enum, string> IniFileNames = new Dictionary<Enum, string>
|
||||
{
|
||||
{ IniFiles.GameUserSettings, Config.Default.ServerGameUserSettingsConfigFile },
|
||||
{ IniFiles.Game, Config.Default.ServerGameConfigFile },
|
||||
{ IniFiles.Engine, Config.Default.ServerEngineConfigFile },
|
||||
};
|
||||
|
||||
public static readonly Dictionary<Enum, string> IniSectionNames = new Dictionary<Enum, string>
|
||||
{
|
||||
// GameUserSettings sections, used by the server manager
|
||||
{ IniSections.GUS_ServerSettings, "ServerSettings" },
|
||||
{ IniSections.GUS_ShooterGameUserSettings, "/Script/ShooterGame.ShooterGameUserSettings" },
|
||||
{ IniSections.GUS_ScalabilityGroups, "ScalabilityGroups" },
|
||||
{ IniSections.GUS_SessionSettings, "SessionSettings" },
|
||||
{ IniSections.GUS_GameSession, "/Script/Engine.GameSession"},
|
||||
{ IniSections.GUS_MultiHome, "MultiHome" },
|
||||
{ IniSections.GUS_MessageOfTheDay, "MessageOfTheDay" },
|
||||
|
||||
// GameUserSettings sections, not used by server manager
|
||||
|
||||
// Game sections, used by the server manager
|
||||
{ IniSections.Game_ShooterGameMode, "/script/shootergame.shootergamemode" },
|
||||
|
||||
// Game sections, not used by server manager
|
||||
};
|
||||
|
||||
public override Dictionary<Enum, string> FileNames => IniFileNames;
|
||||
|
||||
public override Dictionary<Enum, string> SectionNames => IniSectionNames;
|
||||
|
||||
public SystemIniFile(string iniPath)
|
||||
: base(iniPath)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
105
src/ARKServerManager/Lib/Server.cs
Normal file
105
src/ARKServerManager/Lib/Server.cs
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
using ServerManagerTool.Common.Lib;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public class Server : DependencyObject, IDisposable
|
||||
{
|
||||
public static readonly DependencyProperty ProfileProperty = DependencyProperty.Register(nameof(Profile), typeof(ServerProfile), typeof(Server), new PropertyMetadata((ServerProfile)null));
|
||||
public static readonly DependencyProperty RuntimeProperty = DependencyProperty.Register(nameof(Runtime), typeof(ServerRuntime), typeof(Server), new PropertyMetadata((ServerRuntime)null));
|
||||
public static readonly DependencyProperty SelectedProperty = DependencyProperty.Register(nameof(Selected), typeof(bool), typeof(Server), new PropertyMetadata(false));
|
||||
|
||||
public ServerProfile Profile
|
||||
{
|
||||
get { return (ServerProfile)GetValue(ProfileProperty); }
|
||||
protected set { SetValue(ProfileProperty, value); }
|
||||
}
|
||||
|
||||
public ServerRuntime Runtime
|
||||
{
|
||||
get { return (ServerRuntime)GetValue(RuntimeProperty); }
|
||||
protected set { SetValue(RuntimeProperty, value); }
|
||||
}
|
||||
|
||||
public bool Selected
|
||||
{
|
||||
get { return (bool)GetValue(SelectedProperty); }
|
||||
set { SetValue(SelectedProperty, value); }
|
||||
}
|
||||
|
||||
private Server(ServerProfile profile)
|
||||
{
|
||||
InitializeFromProfile(profile);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Profile.DestroyServerFilesWatcher();
|
||||
|
||||
this.Runtime.StatusUpdate -= Runtime_StatusUpdate;
|
||||
this.Runtime.Dispose();
|
||||
}
|
||||
|
||||
private void Runtime_StatusUpdate(object sender, EventArgs eventArgs)
|
||||
{
|
||||
this.Profile.LastInstalledVersion = this.Runtime.Version.ToString();
|
||||
}
|
||||
|
||||
public void ImportFromPath(string path, ServerProfile profile = null)
|
||||
{
|
||||
var loadedProfile = ServerProfile.LoadFrom(path, profile);
|
||||
if (loadedProfile != null)
|
||||
InitializeFromProfile(loadedProfile);
|
||||
}
|
||||
|
||||
private void InitializeFromProfile(ServerProfile profile)
|
||||
{
|
||||
if (profile == null)
|
||||
return;
|
||||
|
||||
this.Profile = profile;
|
||||
this.Runtime = new ServerRuntime();
|
||||
this.Runtime.AttachToProfile(this.Profile).Wait();
|
||||
|
||||
this.Runtime.StatusUpdate += Runtime_StatusUpdate;
|
||||
}
|
||||
|
||||
public static Server FromPath(string path)
|
||||
{
|
||||
var loadedProfile = ServerProfile.LoadFrom(path);
|
||||
if (loadedProfile == null)
|
||||
return null;
|
||||
return new Server(loadedProfile);
|
||||
}
|
||||
|
||||
public static Server FromDefaults()
|
||||
{
|
||||
var loadedProfile = ServerProfile.FromDefaults();
|
||||
if (loadedProfile == null)
|
||||
return null;
|
||||
return new Server(loadedProfile);
|
||||
}
|
||||
|
||||
public async Task StartAsync()
|
||||
{
|
||||
await this.Runtime.AttachToProfile(this.Profile);
|
||||
await this.Runtime.StartAsync();
|
||||
}
|
||||
|
||||
public async Task StopAsync()
|
||||
{
|
||||
await this.Runtime.StopAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> UpgradeAsync(CancellationToken cancellationToken, bool updateServer, ServerBranchSnapshot branch, bool validate, bool updateMods, ProgressDelegate progressCallback)
|
||||
{
|
||||
await this.Runtime.AttachToProfile(this.Profile);
|
||||
var success = await this.Runtime.UpgradeAsync(cancellationToken, updateServer, branch, validate, updateMods, progressCallback);
|
||||
this.Profile.LastInstalledVersion = this.Runtime.Version.ToString();
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
3288
src/ARKServerManager/Lib/ServerApp.cs
Normal file
3288
src/ARKServerManager/Lib/ServerApp.cs
Normal file
File diff suppressed because it is too large
Load diff
36
src/ARKServerManager/Lib/ServerBranchSnapshot.cs
Normal file
36
src/ARKServerManager/Lib/ServerBranchSnapshot.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public class ServerBranchSnapshot
|
||||
{
|
||||
public string BranchName = string.Empty;
|
||||
public string BranchPassword = string.Empty;
|
||||
}
|
||||
|
||||
public class ServerBranchSnapshotComparer : IEqualityComparer<ServerBranchSnapshot>
|
||||
{
|
||||
public bool Equals(ServerBranchSnapshot x, ServerBranchSnapshot y)
|
||||
{
|
||||
//Check whether the compared objects reference the same data.
|
||||
if (Object.ReferenceEquals(x, y)) return true;
|
||||
|
||||
//Check whether any of the compared objects is null.
|
||||
if (x is null || y is null)
|
||||
return false;
|
||||
|
||||
//Check whether the snapshot' properties are equal.
|
||||
return x.BranchName == y.BranchName;
|
||||
}
|
||||
|
||||
public int GetHashCode(ServerBranchSnapshot snapshot)
|
||||
{
|
||||
//Check whether the object is null
|
||||
if (snapshot is null) return 0;
|
||||
|
||||
//Get hash code for the Name field if it is not null.
|
||||
return snapshot.BranchName == null ? 0 : snapshot.BranchName.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
135
src/ARKServerManager/Lib/ServerManager.cs
Normal file
135
src/ARKServerManager/Lib/ServerManager.cs
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Common.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is responsible for managing all of the servers the tool knows about.
|
||||
/// </summary>
|
||||
public class ServerManager : DependencyObject
|
||||
{
|
||||
static ServerManager()
|
||||
{
|
||||
ServerManager.Instance = new ServerManager();
|
||||
}
|
||||
|
||||
public static ServerManager Instance
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ServersProperty = DependencyProperty.Register(nameof(Servers), typeof(SortableObservableCollection<Server>), typeof(ServerManager), new PropertyMetadata(new SortableObservableCollection<Server>()));
|
||||
|
||||
public SortableObservableCollection<Server> Servers
|
||||
{
|
||||
get { return (SortableObservableCollection<Server>)GetValue(ServersProperty); }
|
||||
set { SetValue(ServersProperty, value); }
|
||||
}
|
||||
|
||||
public ServerManager()
|
||||
{
|
||||
this.Servers.CollectionChanged += Servers_CollectionChanged;
|
||||
}
|
||||
|
||||
void Servers_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if(e.Action == NotifyCollectionChangedAction.Remove)
|
||||
{
|
||||
foreach(Server server in e.OldItems)
|
||||
{
|
||||
server.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int AddFromPath(string path)
|
||||
{
|
||||
var server = Server.FromPath(path);
|
||||
if (server == null)
|
||||
return this.Servers.Count - 1;
|
||||
|
||||
this.Servers.Add(server);
|
||||
return this.Servers.Count - 1;
|
||||
}
|
||||
|
||||
public int AddNew()
|
||||
{
|
||||
var server = Server.FromDefaults();
|
||||
if (server == null)
|
||||
return this.Servers.Count - 1;
|
||||
|
||||
this.Servers.Add(server);
|
||||
return this.Servers.Count - 1;
|
||||
}
|
||||
|
||||
public void Remove(Server server, bool deleteProfile)
|
||||
{
|
||||
if (server == null)
|
||||
return;
|
||||
|
||||
// save the profile before deleting, just in case something needed has changed
|
||||
if (server.Profile != null)
|
||||
server.Profile.Save(false, false, null);
|
||||
|
||||
if (deleteProfile)
|
||||
{
|
||||
var profileFile = server.Profile?.GetProfileFile();
|
||||
if (!string.IsNullOrWhiteSpace(profileFile) && File.Exists(profileFile))
|
||||
{
|
||||
// set the file permissions
|
||||
SecurityUtils.SetFileOwnershipForAllUsers(profileFile);
|
||||
try
|
||||
{
|
||||
File.Delete(profileFile);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
var profileIniDir = server.Profile?.GetProfileConfigDir_Old();
|
||||
if (!string.IsNullOrWhiteSpace(profileIniDir) && Directory.Exists(profileIniDir))
|
||||
{
|
||||
// set the folder permissions
|
||||
SecurityUtils.SetDirectoryOwnershipForAllUsers(profileIniDir);
|
||||
try
|
||||
{
|
||||
Directory.Delete(profileIniDir, true);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
}
|
||||
|
||||
server.Runtime?.DeleteFirewallRules();
|
||||
server.Dispose();
|
||||
|
||||
this.Servers.Remove(server);
|
||||
}
|
||||
|
||||
public void CheckProfiles()
|
||||
{
|
||||
var serverIds = new Dictionary<string, bool>();
|
||||
foreach (var server in Servers)
|
||||
{
|
||||
if (server == null || server.Profile == null)
|
||||
continue;
|
||||
|
||||
while (serverIds.ContainsKey(server.Profile.ProfileID))
|
||||
{
|
||||
server.Profile.ResetProfileId();
|
||||
}
|
||||
|
||||
serverIds.Add(server.Profile.ProfileID, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void SortServers()
|
||||
{
|
||||
Servers.Sort(s => s.Profile?.SortKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
246
src/ARKServerManager/Lib/ServerPlayers.cs
Normal file
246
src/ARKServerManager/Lib/ServerPlayers.cs
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
using ArkData;
|
||||
using NLog;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Common.Utils;
|
||||
using ServerManagerTool.Enums;
|
||||
using ServerManagerTool.Lib.ViewModel.RCON;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public class ServerPlayers : DependencyObject
|
||||
{
|
||||
private const int PLAYER_LIST_INTERVAL = 5000;
|
||||
private const int STEAM_UPDATE_INTERVAL = 60;
|
||||
|
||||
public event EventHandler PlayersCollectionUpdated;
|
||||
|
||||
public static readonly DependencyProperty PlayersProperty = DependencyProperty.Register(nameof(Players), typeof(SortableObservableCollection<PlayerInfo>), typeof(ServerPlayers), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty CountPlayersProperty = DependencyProperty.Register(nameof(CountPlayers), typeof(int), typeof(ServerPlayers), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty CountInvalidPlayersProperty = DependencyProperty.Register(nameof(CountInvalidPlayers), typeof(int), typeof(ServerPlayers), new PropertyMetadata(0));
|
||||
|
||||
private readonly ConcurrentDictionary<string, PlayerInfo> _players = new ConcurrentDictionary<string, PlayerInfo>();
|
||||
private readonly object _updatePlayerCollectionLock = new object();
|
||||
private CancellationTokenSource _cancellationTokenSource = null;
|
||||
private PlayerListParameters _playerListParameters;
|
||||
|
||||
private Logger _allLogger;
|
||||
private Logger _eventLogger;
|
||||
private Logger _debugLogger;
|
||||
private Logger _errorLogger;
|
||||
private bool _disposed = false;
|
||||
|
||||
public ServerPlayers(PlayerListParameters parameters)
|
||||
{
|
||||
this.Players = new SortableObservableCollection<PlayerInfo>();
|
||||
|
||||
_playerListParameters = parameters;
|
||||
|
||||
_allLogger = App.GetProfileLogger(_playerListParameters.ProfileId, "PlayerList_All", LogLevel.Info, LogLevel.Info);
|
||||
_eventLogger = App.GetProfileLogger(_playerListParameters.ProfileId, "PlayerList_Event", LogLevel.Info, LogLevel.Info);
|
||||
_debugLogger = App.GetProfileLogger(_playerListParameters.ProfileId, "PlayerList_Debug", LogLevel.Trace, LogLevel.Debug);
|
||||
_errorLogger = App.GetProfileLogger(_playerListParameters.ProfileId, "PlayerList_Error", LogLevel.Error, LogLevel.Fatal);
|
||||
|
||||
UpdatePlayersAsync().DoNotWait();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_cancellationTokenSource != null)
|
||||
{
|
||||
_cancellationTokenSource.Cancel();
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public SortableObservableCollection<PlayerInfo> Players
|
||||
{
|
||||
get { return (SortableObservableCollection<PlayerInfo>)GetValue(PlayersProperty); }
|
||||
set { SetValue(PlayersProperty, value); }
|
||||
}
|
||||
|
||||
public int CountPlayers
|
||||
{
|
||||
get { return (int)GetValue(CountPlayersProperty); }
|
||||
set { SetValue(CountPlayersProperty, value); }
|
||||
}
|
||||
|
||||
public int CountInvalidPlayers
|
||||
{
|
||||
get { return (int)GetValue(CountInvalidPlayersProperty); }
|
||||
set { SetValue(CountInvalidPlayersProperty, value); }
|
||||
}
|
||||
|
||||
private void LogEvent(LogEventType eventType, string message)
|
||||
{
|
||||
switch (eventType)
|
||||
{
|
||||
case LogEventType.All:
|
||||
_allLogger?.Info(message);
|
||||
return;
|
||||
|
||||
case LogEventType.Event:
|
||||
_eventLogger?.Info(message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnPlayerCollectionUpdated()
|
||||
{
|
||||
PlayersCollectionUpdated?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private async Task UpdatePlayersAsync()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
var token = _cancellationTokenSource.Token;
|
||||
|
||||
await UpdatePlayerDetailsAsync(_cancellationTokenSource.Token)
|
||||
.ContinueWith(async t1 =>
|
||||
{
|
||||
await TaskUtils.RunOnUIThreadAsync(() =>
|
||||
{
|
||||
UpdatePlayerCollection();
|
||||
});
|
||||
}, TaskContinuationOptions.NotOnCanceled)
|
||||
.ContinueWith(t2 =>
|
||||
{
|
||||
var cancelled = _cancellationTokenSource.IsCancellationRequested;
|
||||
_cancellationTokenSource.Dispose();
|
||||
_cancellationTokenSource = null;
|
||||
|
||||
if (!cancelled)
|
||||
Task.Delay(PLAYER_LIST_INTERVAL).ContinueWith(t3 => UpdatePlayersAsync());
|
||||
});
|
||||
}
|
||||
|
||||
private async Task UpdatePlayerDetailsAsync(CancellationToken token)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(_playerListParameters.InstallDirectory))
|
||||
{
|
||||
var savedPath = ServerProfile.GetProfileSavePath(_playerListParameters.InstallDirectory, _playerListParameters.AltSaveDirectoryName, _playerListParameters.PGM_Enabled, _playerListParameters.PGM_Name);
|
||||
DataContainer dataContainer = null;
|
||||
DateTime lastSteamUpdateUtc = DateTime.MinValue;
|
||||
|
||||
try
|
||||
{
|
||||
// load the player data from the files.
|
||||
dataContainer = await DataContainer.CreateAsync(savedPath, savedPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_errorLogger?.Error($"{nameof(UpdatePlayerDetailsAsync)} - Error: CreateAsync. {ex.Message}\r\n{ex.StackTrace}");
|
||||
return;
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
await Task.Run(() =>
|
||||
{
|
||||
// update the player data with the latest steam update value from the players collection
|
||||
foreach (var playerData in dataContainer.Players)
|
||||
{
|
||||
var id = playerData.PlayerId;
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
continue;
|
||||
|
||||
_players.TryGetValue(id, out PlayerInfo player);
|
||||
player?.UpdatePlatformData(playerData);
|
||||
}
|
||||
}, token);
|
||||
|
||||
try
|
||||
{
|
||||
// load the player data from steam
|
||||
lastSteamUpdateUtc = await dataContainer.LoadSteamAsync(SteamUtils.SteamWebApiKey, STEAM_UPDATE_INTERVAL);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_errorLogger?.Error($"{nameof(UpdatePlayerDetailsAsync)} - Error: LoadSteamAsync. {ex.Message}\r\n{ex.StackTrace}");
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var totalPlayers = dataContainer.Players.Count;
|
||||
foreach (var playerData in dataContainer.Players)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
var id = playerData.PlayerId;
|
||||
if (!string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
var validPlayer = new PlayerInfo()
|
||||
{
|
||||
PlayerId = playerData.PlayerId,
|
||||
PlayerName = playerData.PlayerName,
|
||||
IsValid = true,
|
||||
};
|
||||
|
||||
_players.AddOrUpdate(id, validPlayer, (k, v) => { v.PlayerName = playerData.PlayerName; v.IsValid = true; return v; });
|
||||
}
|
||||
else
|
||||
{
|
||||
id = Path.GetFileNameWithoutExtension(playerData.Filename);
|
||||
if (!string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
var invalidPlayer = new PlayerInfo()
|
||||
{
|
||||
PlayerId = id,
|
||||
PlayerName = "< corrupted profile >",
|
||||
IsValid = false,
|
||||
};
|
||||
|
||||
_players.AddOrUpdate(id, invalidPlayer, (k, v) => { v.PlayerName = "< corrupted profile >"; v.IsValid = false; return v; });
|
||||
}
|
||||
else
|
||||
{
|
||||
_debugLogger?.Debug($"{nameof(UpdatePlayerDetailsAsync)} - Error: corrupted profile.\r\n{playerData.Filename}.");
|
||||
}
|
||||
}
|
||||
|
||||
if (_players.TryGetValue(id, out PlayerInfo player) && player != null)
|
||||
{
|
||||
player.UpdateData(playerData);
|
||||
|
||||
await TaskUtils.RunOnUIThreadAsync(() =>
|
||||
{
|
||||
player.IsAdmin = _playerListParameters?.Server?.Profile?.ServerFilesAdmins?.Any(u => u.PlayerId.Equals(player.PlayerId, StringComparison.OrdinalIgnoreCase)) ?? false;
|
||||
player.IsWhitelisted = _playerListParameters?.Server?.Profile?.ServerFilesWhitelisted?.Any(u => u.PlayerId.Equals(player.PlayerId, StringComparison.OrdinalIgnoreCase)) ?? false;
|
||||
});
|
||||
}
|
||||
}, token);
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
// remove any players that do not have a player file.
|
||||
var droppedPlayers = _players.Values.Where(p => dataContainer.Players.FirstOrDefault(pd => pd.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null).ToArray();
|
||||
foreach (var droppedPlayer in droppedPlayers)
|
||||
{
|
||||
_players.TryRemove(droppedPlayer.PlayerId, out PlayerInfo player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePlayerCollection()
|
||||
{
|
||||
lock (_updatePlayerCollectionLock)
|
||||
{
|
||||
this.Players = new SortableObservableCollection<PlayerInfo>(_players.Values);
|
||||
this.CountPlayers = this.Players.Count;
|
||||
this.CountInvalidPlayers = this.Players.Count(p => !p.IsValid);
|
||||
|
||||
OnPlayerCollectionUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
6291
src/ARKServerManager/Lib/ServerProfile.cs
Normal file
6291
src/ARKServerManager/Lib/ServerProfile.cs
Normal file
File diff suppressed because it is too large
Load diff
116
src/ARKServerManager/Lib/ServerProfileSnapshot.cs
Normal file
116
src/ARKServerManager/Lib/ServerProfileSnapshot.cs
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
using ServerManagerTool.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public class ServerProfileSnapshot
|
||||
{
|
||||
public string ProfileId;
|
||||
public string ProfileName;
|
||||
public string InstallDirectory;
|
||||
public string AltSaveDirectoryName;
|
||||
public bool PGM_Enabled;
|
||||
public string PGM_Name;
|
||||
public string AdminPassword;
|
||||
public string ServerName;
|
||||
public string ServerArgs;
|
||||
public string ServerIP;
|
||||
public int ServerPort;
|
||||
public int ServerPeerPort;
|
||||
public int QueryPort;
|
||||
public bool RCONEnabled;
|
||||
public int RCONPort;
|
||||
public string ServerMap;
|
||||
public string ServerMapModId;
|
||||
public string TotalConversionModId;
|
||||
public List<string> ServerModIds;
|
||||
public string MOTD;
|
||||
public int MotDDuration;
|
||||
public bool MOTDIntervalEnabled;
|
||||
public int MOTDInterval;
|
||||
public bool ForceRespawnDinos;
|
||||
|
||||
public string BranchName;
|
||||
public string BranchPassword;
|
||||
|
||||
public string SchedulerKey;
|
||||
public bool EnableAutoBackup;
|
||||
public bool EnableAutoUpdate;
|
||||
public bool EnableAutoShutdown1;
|
||||
public bool RestartAfterShutdown1;
|
||||
public bool UpdateAfterShutdown1;
|
||||
public bool EnableAutoShutdown2;
|
||||
public bool RestartAfterShutdown2;
|
||||
public bool UpdateAfterShutdown2;
|
||||
public bool AutoRestartIfShutdown;
|
||||
|
||||
public bool SotFEnabled;
|
||||
|
||||
public int MaxPlayerCount;
|
||||
|
||||
public bool ServerUpdated;
|
||||
public string LastInstalledVersion;
|
||||
public DateTime LastStarted;
|
||||
|
||||
public static ServerProfileSnapshot Create(ServerProfile profile)
|
||||
{
|
||||
return new ServerProfileSnapshot
|
||||
{
|
||||
ProfileId = profile.ProfileID,
|
||||
ProfileName = profile.ProfileName,
|
||||
InstallDirectory = profile.InstallDirectory,
|
||||
AltSaveDirectoryName = profile.AltSaveDirectoryName,
|
||||
PGM_Enabled = profile.PGM_Enabled,
|
||||
PGM_Name = profile.PGM_Name,
|
||||
AdminPassword = profile.AdminPassword,
|
||||
ServerName = profile.ServerName,
|
||||
ServerArgs = profile.GetServerArgs(),
|
||||
ServerIP = string.IsNullOrWhiteSpace(profile.ServerIP) ? IPAddress.Loopback.ToString() : profile.ServerIP.Trim(),
|
||||
ServerPort = profile.ServerPort,
|
||||
ServerPeerPort = profile.ServerPeerPort,
|
||||
QueryPort = profile.QueryPort,
|
||||
RCONEnabled = profile.RCONEnabled,
|
||||
RCONPort = profile.RCONPort,
|
||||
ServerMap = ServerProfile.GetProfileMapName(profile),
|
||||
ServerMapModId = ServerProfile.GetProfileMapModId(profile),
|
||||
TotalConversionModId = profile.TotalConversionModId ?? string.Empty,
|
||||
ServerModIds = ModUtils.GetModIdList(profile.ServerModIds),
|
||||
MOTD = profile.MOTD,
|
||||
MotDDuration = Math.Max(profile.MOTDDuration, 10),
|
||||
MOTDIntervalEnabled = profile.MOTDInterval.HasValue && !string.IsNullOrWhiteSpace(profile.MOTD),
|
||||
MOTDInterval = Math.Max(1, Math.Min(int.MaxValue, profile.MOTDInterval.Value)),
|
||||
ForceRespawnDinos = profile.ForceRespawnDinos,
|
||||
|
||||
BranchName = profile.BranchName,
|
||||
BranchPassword = profile.BranchPassword,
|
||||
|
||||
SchedulerKey = profile.GetProfileKey(),
|
||||
EnableAutoBackup = profile.EnableAutoBackup,
|
||||
EnableAutoUpdate = profile.EnableAutoUpdate,
|
||||
EnableAutoShutdown1 = profile.EnableAutoShutdown1,
|
||||
RestartAfterShutdown1 = profile.RestartAfterShutdown1,
|
||||
UpdateAfterShutdown1 = profile.UpdateAfterShutdown1,
|
||||
EnableAutoShutdown2 = profile.EnableAutoShutdown2,
|
||||
RestartAfterShutdown2 = profile.RestartAfterShutdown2,
|
||||
UpdateAfterShutdown2 = profile.UpdateAfterShutdown2,
|
||||
AutoRestartIfShutdown = profile.AutoRestartIfShutdown,
|
||||
|
||||
SotFEnabled = profile.SOTF_Enabled,
|
||||
|
||||
MaxPlayerCount = profile.MaxPlayers,
|
||||
|
||||
ServerUpdated = false,
|
||||
LastInstalledVersion = profile.LastInstalledVersion ?? new Version(0, 0).ToString(),
|
||||
LastStarted = profile.LastStarted,
|
||||
};
|
||||
}
|
||||
|
||||
public void Update(ServerProfile profile)
|
||||
{
|
||||
profile.LastInstalledVersion = LastInstalledVersion;
|
||||
profile.LastStarted = LastStarted;
|
||||
}
|
||||
}
|
||||
}
|
||||
628
src/ARKServerManager/Lib/ServerRCON.cs
Normal file
628
src/ARKServerManager/Lib/ServerRCON.cs
Normal file
|
|
@ -0,0 +1,628 @@
|
|||
using ArkData;
|
||||
using NLog;
|
||||
using ServerManagerTool.Common.Interfaces;
|
||||
using ServerManagerTool.Common.Lib;
|
||||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Common.Utils;
|
||||
using ServerManagerTool.Enums;
|
||||
using ServerManagerTool.Lib.ViewModel;
|
||||
using ServerManagerTool.Lib.ViewModel.RCON;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using WPFSharp.Globalizer;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
public class ServerRCON : DependencyObject, IAsyncDisposable
|
||||
{
|
||||
public event EventHandler PlayersCollectionUpdated;
|
||||
|
||||
private const int STEAM_UPDATE_INTERVAL = 60;
|
||||
private const int PLAYER_LIST_INTERVAL = 5000;
|
||||
private const int GET_CHAT_INTERVAL = 1000;
|
||||
private const string NoResponseMatch = "Server received, But no response!!";
|
||||
public const string NoResponseOutput = "NO_RESPONSE";
|
||||
|
||||
public const string RCON_COMMAND_BROADCAST = "broadcast";
|
||||
public const string RCON_COMMAND_LISTPLAYERS = "listplayers";
|
||||
public const string RCON_COMMAND_GETCHAT = "getchat";
|
||||
public const string RCON_COMMAND_SERVERCHAT = "serverchat";
|
||||
public const string RCON_COMMAND_WILDDINOWIPE = "DestroyWildDinos";
|
||||
|
||||
[TypeConverter(typeof(EnumDescriptionTypeConverter))]
|
||||
public enum ConsoleStatus
|
||||
{
|
||||
Disconnected,
|
||||
Connected,
|
||||
};
|
||||
|
||||
public class ConsoleCommand
|
||||
{
|
||||
public ConsoleStatus status;
|
||||
public string rawCommand;
|
||||
|
||||
public string command;
|
||||
public string args;
|
||||
|
||||
public bool suppressCommand;
|
||||
public bool suppressOutput;
|
||||
public IEnumerable<string> lines = new string[0];
|
||||
};
|
||||
|
||||
private class CommandListener : IDisposable
|
||||
{
|
||||
public Action<ConsoleCommand> Callback { get; set; }
|
||||
public Action<CommandListener> DisposeAction { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeAction(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty StatusProperty = DependencyProperty.Register(nameof(Status), typeof(ConsoleStatus), typeof(ServerRCON), new PropertyMetadata(ConsoleStatus.Disconnected));
|
||||
public static readonly DependencyProperty PlayersProperty = DependencyProperty.Register(nameof(Players), typeof(SortableObservableCollection<PlayerInfo>), typeof(ServerRCON), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty CountPlayersProperty = DependencyProperty.Register(nameof(CountPlayers), typeof(int), typeof(ServerRCON), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty CountInvalidPlayersProperty = DependencyProperty.Register(nameof(CountInvalidPlayers), typeof(int), typeof(ServerRCON), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty CountOnlinePlayersProperty = DependencyProperty.Register(nameof(CountOnlinePlayers), typeof(int), typeof(ServerRCON), new PropertyMetadata(0));
|
||||
|
||||
private static readonly char[] lineSplitChars = new char[] { '\n' };
|
||||
private static readonly char[] argsSplitChars = new char[] { ' ' };
|
||||
private readonly ActionQueue commandProcessor = new ActionQueue(TaskScheduler.Default);
|
||||
private readonly ActionQueue outputProcessor = new ActionQueue(TaskScheduler.FromCurrentSynchronizationContext());
|
||||
private readonly List<CommandListener> commandListeners = new List<CommandListener>();
|
||||
private readonly RCONParameters rconParams;
|
||||
private QueryMaster.Rcon console;
|
||||
private int maxCommandRetries = 3;
|
||||
|
||||
private readonly ConcurrentDictionary<string, PlayerInfo> players = new ConcurrentDictionary<string, PlayerInfo>();
|
||||
private readonly object updatePlayerCollectionLock = new object();
|
||||
private CancellationTokenSource cancellationTokenSource = null;
|
||||
|
||||
private readonly Logger _chatLogger;
|
||||
private readonly Logger _allLogger;
|
||||
private readonly Logger _eventLogger;
|
||||
private readonly Logger _debugLogger;
|
||||
private readonly Logger _errorLogger;
|
||||
private bool _disposed = false;
|
||||
|
||||
public ServerRCON(RCONParameters parameters)
|
||||
{
|
||||
this.rconParams = parameters;
|
||||
this.Players = new SortableObservableCollection<PlayerInfo>();
|
||||
|
||||
_allLogger = App.GetProfileLogger(this.rconParams.ProfileId, "RCON_All", LogLevel.Info, LogLevel.Info);
|
||||
_chatLogger = App.GetProfileLogger(this.rconParams.ProfileId, "RCON_Chat", LogLevel.Info, LogLevel.Info);
|
||||
_eventLogger = App.GetProfileLogger(this.rconParams.ProfileId, "RCON_Event", LogLevel.Info, LogLevel.Info);
|
||||
_debugLogger = App.GetProfileLogger(this.rconParams.ProfileId, "RCON_Debug", LogLevel.Trace, LogLevel.Debug);
|
||||
_errorLogger = App.GetProfileLogger(this.rconParams.ProfileId, "RCON_Error", LogLevel.Error, LogLevel.Fatal);
|
||||
}
|
||||
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
if (cancellationTokenSource != null)
|
||||
{
|
||||
cancellationTokenSource.Cancel();
|
||||
}
|
||||
await this.commandProcessor.DisposeAsync();
|
||||
await this.outputProcessor.DisposeAsync();
|
||||
|
||||
for (int index = this.commandListeners.Count - 1; index >= 0; index--)
|
||||
{
|
||||
this.commandListeners[index].Dispose();
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
#region Properties
|
||||
public ConsoleStatus Status
|
||||
{
|
||||
get { return (ConsoleStatus)GetValue(StatusProperty); }
|
||||
set { SetValue(StatusProperty, value); }
|
||||
}
|
||||
|
||||
public SortableObservableCollection<PlayerInfo> Players
|
||||
{
|
||||
get { return (SortableObservableCollection<PlayerInfo>)GetValue(PlayersProperty); }
|
||||
set { SetValue(PlayersProperty, value); }
|
||||
}
|
||||
|
||||
public int CountPlayers
|
||||
{
|
||||
get { return (int)GetValue(CountPlayersProperty); }
|
||||
set { SetValue(CountPlayersProperty, value); }
|
||||
}
|
||||
|
||||
public int CountInvalidPlayers
|
||||
{
|
||||
get { return (int)GetValue(CountInvalidPlayersProperty); }
|
||||
set { SetValue(CountInvalidPlayersProperty, value); }
|
||||
}
|
||||
|
||||
public int CountOnlinePlayers
|
||||
{
|
||||
get { return (int)GetValue(CountOnlinePlayersProperty); }
|
||||
set { SetValue(CountOnlinePlayersProperty, value); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public void Initialize()
|
||||
{
|
||||
commandProcessor.PostAction(AutoPlayerList);
|
||||
commandProcessor.PostAction(AutoGetChat);
|
||||
UpdatePlayersAsync().DoNotWait();
|
||||
}
|
||||
|
||||
private void LogEvent(LogEventType eventType, string message)
|
||||
{
|
||||
switch (eventType)
|
||||
{
|
||||
case LogEventType.All:
|
||||
_allLogger?.Info(message);
|
||||
return;
|
||||
|
||||
case LogEventType.Chat:
|
||||
_chatLogger?.Info(message);
|
||||
return;
|
||||
|
||||
case LogEventType.Event:
|
||||
_eventLogger?.Info(message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnPlayerCollectionUpdated()
|
||||
{
|
||||
PlayersCollectionUpdated?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private bool Reconnect()
|
||||
{
|
||||
if (this.console != null)
|
||||
{
|
||||
this.console.Dispose();
|
||||
this.console = null;
|
||||
}
|
||||
|
||||
var endpoint = new IPEndPoint(this.rconParams.RCONHostIP, this.rconParams.RCONPort);
|
||||
var server = QueryMaster.ServerQuery.GetServerInstance(QueryMaster.EngineType.Source, endpoint);
|
||||
this.console = server.GetControl(this.rconParams.AdminPassword);
|
||||
return this.console != null;
|
||||
}
|
||||
|
||||
public IDisposable RegisterCommandListener(Action<ConsoleCommand> callback)
|
||||
{
|
||||
var listener = new CommandListener { Callback = callback, DisposeAction = UnregisterCommandListener };
|
||||
this.commandListeners.Add(listener);
|
||||
return listener;
|
||||
}
|
||||
|
||||
private void UnregisterCommandListener(CommandListener listener)
|
||||
{
|
||||
this.commandListeners.Remove(listener);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Process Methods
|
||||
private Task AutoPlayerList()
|
||||
{
|
||||
return commandProcessor.PostAction(() =>
|
||||
{
|
||||
ProcessInput(new ConsoleCommand() { rawCommand = RCON_COMMAND_LISTPLAYERS, suppressCommand = true, suppressOutput = true });
|
||||
Task.Delay(PLAYER_LIST_INTERVAL).ContinueWith(t => commandProcessor.PostAction(AutoPlayerList)).DoNotWait();
|
||||
});
|
||||
}
|
||||
|
||||
private Task AutoGetChat()
|
||||
{
|
||||
return commandProcessor.PostAction(() =>
|
||||
{
|
||||
ProcessInput(new ConsoleCommand() { rawCommand = RCON_COMMAND_GETCHAT, suppressCommand = true, suppressOutput = true });
|
||||
Task.Delay(GET_CHAT_INTERVAL).ContinueWith(t => commandProcessor.PostAction(AutoGetChat)).DoNotWait();
|
||||
});
|
||||
}
|
||||
|
||||
private bool ProcessInput(ConsoleCommand command)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!command.suppressCommand)
|
||||
{
|
||||
LogEvent(LogEventType.All, command.rawCommand);
|
||||
}
|
||||
|
||||
var args = command.rawCommand.Split(argsSplitChars, 2);
|
||||
command.command = args[0];
|
||||
if (args.Length > 1)
|
||||
{
|
||||
command.args = args[1];
|
||||
}
|
||||
|
||||
var result = SendCommand(command.rawCommand);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
_debugLogger.Debug($"SendCommand '{command.rawCommand}' do not return any results.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var lines = result.Split(lineSplitChars, StringSplitOptions.RemoveEmptyEntries).Select(l => l.Trim()).ToArray();
|
||||
|
||||
if (!command.suppressOutput)
|
||||
{
|
||||
foreach (var line in lines)
|
||||
{
|
||||
LogEvent(LogEventType.All, line);
|
||||
}
|
||||
}
|
||||
|
||||
if (lines.Length == 1 && lines[0].StartsWith(NoResponseMatch))
|
||||
{
|
||||
lines[0] = NoResponseOutput;
|
||||
}
|
||||
|
||||
command.lines = lines;
|
||||
}
|
||||
|
||||
command.status = ConsoleStatus.Connected;
|
||||
|
||||
this.outputProcessor.PostAction(() => ProcessOutput(command));
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_errorLogger.Error($"Failed to send command '{command.rawCommand}'. {ex.Message}");
|
||||
command.status = ConsoleStatus.Disconnected;
|
||||
this.outputProcessor.PostAction(() => ProcessOutput(command));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// This is bound to the UI thread
|
||||
private void ProcessOutput(ConsoleCommand command)
|
||||
{
|
||||
//
|
||||
// Handle results
|
||||
//
|
||||
HandleCommand(command);
|
||||
NotifyCommand(command);
|
||||
}
|
||||
|
||||
public Task<bool> IssueCommand(string userCommand)
|
||||
{
|
||||
return this.commandProcessor.PostAction(() => ProcessInput(new ConsoleCommand() { rawCommand = userCommand }));
|
||||
}
|
||||
|
||||
// This is bound to the UI thread
|
||||
private void HandleCommand(ConsoleCommand command)
|
||||
{
|
||||
//
|
||||
// Change the connection state as appropriate
|
||||
//
|
||||
this.Status = command.status;
|
||||
|
||||
//
|
||||
// Perform per-command special processing to extract data
|
||||
//
|
||||
if (command.command.Equals(RCON_COMMAND_LISTPLAYERS, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
//
|
||||
// Update the visible player list
|
||||
//
|
||||
command.suppressOutput = false;
|
||||
command.lines = HandleListPlayersCommand(command.lines);
|
||||
}
|
||||
else if (command.command.Equals(RCON_COMMAND_GETCHAT, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// TODO: Extract the player name from the chat
|
||||
var lines = command.lines.Where(l => !String.IsNullOrEmpty(l) && l != NoResponseOutput).ToArray();
|
||||
if (lines.Length == 0 && command.suppressCommand)
|
||||
{
|
||||
command.suppressOutput = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
command.suppressOutput = false;
|
||||
command.lines = lines;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
LogEvent(LogEventType.Chat, line);
|
||||
LogEvent(LogEventType.All, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (command.command.Equals(RCON_COMMAND_BROADCAST, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
LogEvent(LogEventType.Chat, command.rawCommand);
|
||||
command.suppressOutput = true;
|
||||
}
|
||||
else if (command.command.Equals(RCON_COMMAND_SERVERCHAT, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
LogEvent(LogEventType.Chat, command.rawCommand);
|
||||
command.suppressOutput = true;
|
||||
}
|
||||
}
|
||||
|
||||
// This is bound to the UI thread
|
||||
private List<string> HandleListPlayersCommand(IEnumerable<string> commandLines)
|
||||
{
|
||||
var output = new List<string>();
|
||||
|
||||
if (commandLines != null)
|
||||
{
|
||||
var onlinePlayers = new List<PlayerInfo>();
|
||||
foreach (var line in commandLines)
|
||||
{
|
||||
var elements = line.Split(',');
|
||||
if (elements.Length != 2)
|
||||
// Invalid data. Ignore it.
|
||||
continue;
|
||||
|
||||
var id = elements[1]?.Trim();
|
||||
if (id.Any(c => !char.IsDigit(c)))
|
||||
// Invalid data. Ignore it.
|
||||
continue;
|
||||
|
||||
if (onlinePlayers.FirstOrDefault(p => p.PlayerId.Equals(id, StringComparison.OrdinalIgnoreCase)) != null)
|
||||
// Duplicate data. Ignore it.
|
||||
continue;
|
||||
|
||||
var newPlayer = new PlayerInfo()
|
||||
{
|
||||
PlayerId = id,
|
||||
PlayerName = elements[0].Substring(elements[0].IndexOf('.') + 1).Trim(),
|
||||
IsOnline = true,
|
||||
};
|
||||
onlinePlayers.Add(newPlayer);
|
||||
|
||||
var playerJoined = false;
|
||||
this.players.AddOrUpdate(newPlayer.PlayerId, (k) => { playerJoined = true; return newPlayer; }, (k, v) => { playerJoined = !v.IsOnline; v.IsOnline = true; return v; });
|
||||
|
||||
if (playerJoined)
|
||||
{
|
||||
var messageFormat = GlobalizedApplication.Instance.GetResourceString("Player_Join") ?? "Player '{0}' joined the game.";
|
||||
var message = string.Format(messageFormat, newPlayer.PlayerName);
|
||||
output.Add(message);
|
||||
LogEvent(LogEventType.Event, message);
|
||||
LogEvent(LogEventType.All, message);
|
||||
}
|
||||
}
|
||||
|
||||
var droppedPlayers = this.players.Values.Where(p => onlinePlayers.FirstOrDefault(np => np.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null).ToArray();
|
||||
foreach (var droppedPlayer in droppedPlayers)
|
||||
{
|
||||
if (droppedPlayer.IsOnline)
|
||||
{
|
||||
droppedPlayer.IsOnline = false;
|
||||
|
||||
var messageFormat = GlobalizedApplication.Instance.GetResourceString("Player_Leave") ?? "Player '{0}' left the game.";
|
||||
var message = string.Format(messageFormat, droppedPlayer.PlayerName);
|
||||
output.Add(message);
|
||||
LogEvent(LogEventType.Event, message);
|
||||
LogEvent(LogEventType.All, message);
|
||||
}
|
||||
}
|
||||
|
||||
UpdatePlayerCollection();
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// This is bound to the UI thread
|
||||
private void NotifyCommand(ConsoleCommand command)
|
||||
{
|
||||
foreach (var listener in commandListeners)
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.Callback(command);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_errorLogger.Error("Exception in command listener: {0}\n{1}", ex.Message, ex.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string SendCommand(string command)
|
||||
{
|
||||
const int RETRY_DELAY = 100;
|
||||
|
||||
Exception lastException = null;
|
||||
int retries = 0;
|
||||
|
||||
while (retries < maxCommandRetries)
|
||||
{
|
||||
if (this.console != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.console.SendCommand(command);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// we will simply retry
|
||||
lastException = ex;
|
||||
}
|
||||
|
||||
Task.Delay(RETRY_DELAY).Wait();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Reconnect();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lastException = ex;
|
||||
}
|
||||
|
||||
retries++;
|
||||
}
|
||||
|
||||
this.maxCommandRetries = 10;
|
||||
_errorLogger.Error($"Failed to connect to RCON at {this.rconParams.RCONHostIP}:{this.rconParams.RCONPort} with {this.rconParams.AdminPassword}. {lastException.Message}");
|
||||
throw new Exception($"Command failed to send after {maxCommandRetries} attempts. Last exception: {lastException.Message}", lastException);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private async Task UpdatePlayersAsync()
|
||||
{
|
||||
if (this._disposed)
|
||||
return;
|
||||
|
||||
cancellationTokenSource = new CancellationTokenSource();
|
||||
var token = cancellationTokenSource.Token;
|
||||
|
||||
await UpdatePlayerDetailsAsync(cancellationTokenSource.Token)
|
||||
.ContinueWith(async t1 =>
|
||||
{
|
||||
await TaskUtils.RunOnUIThreadAsync(() =>
|
||||
{
|
||||
UpdatePlayerCollection();
|
||||
});
|
||||
}, TaskContinuationOptions.NotOnCanceled)
|
||||
.ContinueWith(t2 =>
|
||||
{
|
||||
var cancelled = cancellationTokenSource.IsCancellationRequested;
|
||||
cancellationTokenSource.Dispose();
|
||||
cancellationTokenSource = null;
|
||||
|
||||
if (!cancelled)
|
||||
Task.Delay(PLAYER_LIST_INTERVAL).ContinueWith(t3 => UpdatePlayersAsync());
|
||||
});
|
||||
}
|
||||
|
||||
private async Task UpdatePlayerDetailsAsync(CancellationToken token)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(rconParams.InstallDirectory))
|
||||
{
|
||||
var savedPath = ServerProfile.GetProfileSavePath(rconParams.InstallDirectory, rconParams.AltSaveDirectoryName, rconParams.PGM_Enabled, rconParams.PGM_Name);
|
||||
DataContainer dataContainer = null;
|
||||
DateTime lastSteamUpdateUtc = DateTime.MinValue;
|
||||
|
||||
try
|
||||
{
|
||||
// load the player data from the files.
|
||||
dataContainer = await DataContainer.CreateAsync(savedPath, savedPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_errorLogger.Error($"{nameof(UpdatePlayerDetailsAsync)} - Error: CreateAsync. {ex.Message}\r\n{ex.StackTrace}");
|
||||
return;
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
await Task.Run(() =>
|
||||
{
|
||||
// update the player data with the latest update value from the players collection
|
||||
foreach (var playerData in dataContainer.Players)
|
||||
{
|
||||
var id = playerData.PlayerId;
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
continue;
|
||||
|
||||
this.players.TryGetValue(id, out PlayerInfo player);
|
||||
player?.UpdatePlatformData(playerData);
|
||||
}
|
||||
}, token);
|
||||
|
||||
try
|
||||
{
|
||||
// load the player data from steam
|
||||
lastSteamUpdateUtc = await dataContainer.LoadSteamAsync(SteamUtils.SteamWebApiKey, STEAM_UPDATE_INTERVAL);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_errorLogger.Error($"{nameof(UpdatePlayerDetailsAsync)} - Error: LoadSteamAsync. {ex.Message}\r\n{ex.StackTrace}");
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var totalPlayers = dataContainer.Players.Count;
|
||||
foreach (var playerData in dataContainer.Players)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
var id = playerData.PlayerId;
|
||||
if (!string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
var validPlayer = new PlayerInfo()
|
||||
{
|
||||
PlayerId = playerData.PlayerId,
|
||||
PlayerName = playerData.PlayerName,
|
||||
IsValid = true,
|
||||
};
|
||||
|
||||
this.players.AddOrUpdate(id, validPlayer, (k, v) => { v.PlayerName = playerData.PlayerName; v.IsValid = true; return v; });
|
||||
}
|
||||
else
|
||||
{
|
||||
id = Path.GetFileNameWithoutExtension(playerData.Filename);
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
var invalidPlayer = new PlayerInfo()
|
||||
{
|
||||
PlayerId = id,
|
||||
PlayerName = "< corrupted profile >",
|
||||
IsValid = false,
|
||||
};
|
||||
|
||||
this.players.AddOrUpdate(id, invalidPlayer, (k, v) => { v.PlayerName = "< corrupted profile >"; v.IsValid = false; return v; });
|
||||
}
|
||||
else
|
||||
{
|
||||
_debugLogger.Debug($"{nameof(UpdatePlayerDetailsAsync)} - Error: corrupted profile.\r\n{playerData.Filename}.");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.players.TryGetValue(id, out PlayerInfo player) && player != null)
|
||||
{
|
||||
player.UpdateData(playerData);
|
||||
|
||||
await TaskUtils.RunOnUIThreadAsync(() =>
|
||||
{
|
||||
player.IsAdmin = rconParams?.Server?.Profile?.ServerFilesAdmins?.Any(u => u.PlayerId.Equals(player.PlayerId, StringComparison.OrdinalIgnoreCase)) ?? false;
|
||||
player.IsWhitelisted = rconParams?.Server?.Profile?.ServerFilesWhitelisted?.Any(u => u.PlayerId.Equals(player.PlayerId, StringComparison.OrdinalIgnoreCase)) ?? false;
|
||||
});
|
||||
}
|
||||
}, token);
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
// remove any players that do not have a player file.
|
||||
var droppedPlayers = this.players.Values.Where(p => dataContainer.Players.FirstOrDefault(pd => pd.PlayerId.Equals(p.PlayerId, StringComparison.OrdinalIgnoreCase)) == null).ToArray();
|
||||
foreach (var droppedPlayer in droppedPlayers)
|
||||
{
|
||||
players.TryRemove(droppedPlayer.PlayerId, out PlayerInfo player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePlayerCollection()
|
||||
{
|
||||
lock (updatePlayerCollectionLock)
|
||||
{
|
||||
this.Players = new SortableObservableCollection<PlayerInfo>(players.Values);
|
||||
this.CountPlayers = this.Players.Count;
|
||||
this.CountInvalidPlayers = this.Players.Count(p => !p.IsValid);
|
||||
this.CountOnlinePlayers = this.Players.Count(p => p.IsOnline);
|
||||
|
||||
OnPlayerCollectionUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1165
src/ARKServerManager/Lib/ServerRuntime.cs
Normal file
1165
src/ARKServerManager/Lib/ServerRuntime.cs
Normal file
File diff suppressed because it is too large
Load diff
381
src/ARKServerManager/Lib/ServerStatusWatcher.cs
Normal file
381
src/ARKServerManager/Lib/ServerStatusWatcher.cs
Normal file
|
|
@ -0,0 +1,381 @@
|
|||
using ServerManagerTool.Common.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks.Dataflow;
|
||||
|
||||
namespace ServerManagerTool.Lib
|
||||
{
|
||||
using NLog;
|
||||
using ServerManagerTool;
|
||||
using ServerManagerTool.Common.Utils;
|
||||
using ServerManagerTool.Enums;
|
||||
using StatusCallback = Action<IAsyncDisposable, ServerStatusWatcher.ServerStatusUpdate>;
|
||||
|
||||
public class ServerStatusWatcher
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public struct ServerStatusUpdate
|
||||
{
|
||||
public Process Process;
|
||||
public WatcherServerStatus Status;
|
||||
public QueryMaster.ServerInfo ServerInfo;
|
||||
public int OnlinePlayerCount;
|
||||
}
|
||||
|
||||
private class ServerStatusUpdateRegistration : IAsyncDisposable
|
||||
{
|
||||
public string InstallDirectory;
|
||||
public IPEndPoint LocalEndpoint;
|
||||
public IPEndPoint SteamEndpoint;
|
||||
public StatusCallback UpdateCallback;
|
||||
public Func<Task> UnregisterAction;
|
||||
|
||||
public string AsmId;
|
||||
public string ProfileId;
|
||||
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
await UnregisterAction();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<ServerStatusUpdateRegistration> _serverRegistrations = new List<ServerStatusUpdateRegistration>();
|
||||
private readonly ActionBlock<Func<Task>> _eventQueue;
|
||||
private readonly Dictionary<string, DateTime> _nextExternalStatusQuery = new Dictionary<string, DateTime>();
|
||||
|
||||
private ServerStatusWatcher()
|
||||
{
|
||||
_eventQueue = new ActionBlock<Func<Task>>(async f => await f.Invoke(), new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 1 });
|
||||
_eventQueue.Post(DoLocalUpdate);
|
||||
}
|
||||
|
||||
static ServerStatusWatcher()
|
||||
{
|
||||
ServerStatusWatcher.Instance = new ServerStatusWatcher();
|
||||
}
|
||||
|
||||
public static ServerStatusWatcher Instance
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public IAsyncDisposable RegisterForUpdates(string installDirectory, string profileId, IPEndPoint localEndpoint, IPEndPoint steamEndpoint, Action<IAsyncDisposable, ServerStatusUpdate> updateCallback)
|
||||
{
|
||||
var registration = new ServerStatusUpdateRegistration
|
||||
{
|
||||
AsmId = Config.Default.ASMUniqueKey,
|
||||
InstallDirectory = installDirectory,
|
||||
ProfileId = profileId,
|
||||
LocalEndpoint = localEndpoint,
|
||||
SteamEndpoint = steamEndpoint,
|
||||
UpdateCallback = updateCallback,
|
||||
};
|
||||
|
||||
registration.UnregisterAction = async () =>
|
||||
{
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
_eventQueue.Post(() =>
|
||||
{
|
||||
if(_serverRegistrations.Contains(registration))
|
||||
{
|
||||
Logger.Debug($"{nameof(RegisterForUpdates)} Removing registration for L:{registration.LocalEndpoint} S:{registration.SteamEndpoint}");
|
||||
_serverRegistrations.Remove(registration);
|
||||
}
|
||||
tcs.TrySetResult(true);
|
||||
return Task.FromResult(true);
|
||||
});
|
||||
|
||||
await tcs.Task;
|
||||
};
|
||||
|
||||
_eventQueue.Post(() =>
|
||||
{
|
||||
if (!_serverRegistrations.Contains(registration))
|
||||
{
|
||||
Logger.Debug($"{nameof(RegisterForUpdates)} Adding registration for L:{registration.LocalEndpoint} S:{registration.SteamEndpoint}");
|
||||
_serverRegistrations.Add(registration);
|
||||
|
||||
var registrationKey = registration.SteamEndpoint.ToString();
|
||||
_nextExternalStatusQuery[registrationKey] = DateTime.MinValue;
|
||||
}
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
);
|
||||
|
||||
return registration;
|
||||
}
|
||||
|
||||
private static ServerProcessStatus GetServerProcessStatus(ServerStatusUpdateRegistration updateContext, out Process serverProcess)
|
||||
{
|
||||
serverProcess = null;
|
||||
if (String.IsNullOrWhiteSpace(updateContext.InstallDirectory))
|
||||
{
|
||||
return ServerProcessStatus.NotInstalled;
|
||||
}
|
||||
|
||||
var serverExePath = Path.Combine(updateContext.InstallDirectory, Config.Default.ServerBinaryRelativePath, Config.Default.ServerExe);
|
||||
if(!File.Exists(serverExePath))
|
||||
{
|
||||
return ServerProcessStatus.NotInstalled;
|
||||
}
|
||||
|
||||
//
|
||||
// The server appears to be installed, now determine if it is running or stopped.
|
||||
//
|
||||
try
|
||||
{
|
||||
foreach (var process in Process.GetProcessesByName(Config.Default.ServerProcessName))
|
||||
{
|
||||
var commandLine = ProcessUtils.GetCommandLineForProcess(process.Id)?.ToLower();
|
||||
|
||||
if (commandLine != null && commandLine.Contains(updateContext.InstallDirectory.ToLower()) && commandLine.Contains(Config.Default.ServerExe.ToLower()))
|
||||
{
|
||||
// Does this match our server exe and port?
|
||||
var serverArgMatch = String.Format(Config.Default.ServerCommandLineArgsMatchFormat, updateContext.LocalEndpoint.Port).ToLower();
|
||||
if (commandLine.Contains(serverArgMatch))
|
||||
{
|
||||
// Was an IP set on it?
|
||||
var anyIpArgMatch = String.Format(Config.Default.ServerCommandLineArgsIPMatchFormat, String.Empty).ToLower();
|
||||
if (commandLine.Contains(anyIpArgMatch))
|
||||
{
|
||||
// If we have a specific IP, check for it.
|
||||
var ipArgMatch = String.Format(Config.Default.ServerCommandLineArgsIPMatchFormat, updateContext.LocalEndpoint.Address.ToString()).ToLower();
|
||||
if (!commandLine.Contains(ipArgMatch))
|
||||
{
|
||||
// Specific IP set didn't match
|
||||
continue;
|
||||
}
|
||||
|
||||
// Specific IP matched
|
||||
}
|
||||
|
||||
// Either specific IP matched or no specific IP was set and we will claim this is ours.
|
||||
|
||||
process.EnableRaisingEvents = true;
|
||||
if (process.HasExited)
|
||||
{
|
||||
return ServerProcessStatus.Stopped;
|
||||
}
|
||||
|
||||
serverProcess = process;
|
||||
return ServerProcessStatus.Running;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Logger.Error($"{nameof(GetServerProcessStatus)}. {ex.Message}\r\n{ex.StackTrace}");
|
||||
}
|
||||
|
||||
return ServerProcessStatus.Stopped;
|
||||
}
|
||||
|
||||
private async Task DoLocalUpdate()
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var registration in this._serverRegistrations)
|
||||
{
|
||||
ServerStatusUpdate statusUpdate = new ServerStatusUpdate();
|
||||
try
|
||||
{
|
||||
Logger.Info($"{nameof(DoLocalUpdate)} Start: {registration.LocalEndpoint}");
|
||||
statusUpdate = await GenerateServerStatusUpdateAsync(registration);
|
||||
|
||||
PostServerStatusUpdate(registration, registration.UpdateCallback, statusUpdate);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// We don't want to stop other registration queries or break the ActionBlock
|
||||
Logger.Error($"{nameof(DoLocalUpdate)} - Exception in local update. {ex.Message}\r\n{ex.StackTrace}");
|
||||
Debugger.Break();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Logger.Info($"{nameof(DoLocalUpdate)} End: {registration.LocalEndpoint}: {statusUpdate.Status}");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Task.Delay(Config.Default.ServerStatusWatcher_LocalStatusQueryDelay).ContinueWith(_ => _eventQueue.Post(DoLocalUpdate)).DoNotWait();
|
||||
}
|
||||
}
|
||||
|
||||
private void PostServerStatusUpdate(ServerStatusUpdateRegistration registration, StatusCallback callback, ServerStatusUpdate statusUpdate)
|
||||
{
|
||||
_eventQueue.Post(() =>
|
||||
{
|
||||
if (this._serverRegistrations.Contains(registration))
|
||||
{
|
||||
try
|
||||
{
|
||||
callback(registration, statusUpdate);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
DebugUtils.WriteFormatThreadSafeAsync("Exception during local status update callback: {0}\n{1}", ex.Message, ex.StackTrace).DoNotWait();
|
||||
}
|
||||
}
|
||||
return TaskUtils.FinishedTask;
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<ServerStatusUpdate> GenerateServerStatusUpdateAsync(ServerStatusUpdateRegistration registration)
|
||||
{
|
||||
var registrationKey = registration.SteamEndpoint.ToString();
|
||||
|
||||
//
|
||||
// First check the process status
|
||||
//
|
||||
var processStatus = GetServerProcessStatus(registration, out Process process);
|
||||
switch(processStatus)
|
||||
{
|
||||
case ServerProcessStatus.NotInstalled:
|
||||
return new ServerStatusUpdate { Status = WatcherServerStatus.NotInstalled };
|
||||
|
||||
case ServerProcessStatus.Stopped:
|
||||
return new ServerStatusUpdate { Status = WatcherServerStatus.Stopped };
|
||||
|
||||
case ServerProcessStatus.Unknown:
|
||||
return new ServerStatusUpdate { Status = WatcherServerStatus.Unknown };
|
||||
|
||||
case ServerProcessStatus.Running:
|
||||
break;
|
||||
|
||||
default:
|
||||
Debugger.Break();
|
||||
break;
|
||||
}
|
||||
|
||||
var currentStatus = WatcherServerStatus.Initializing;
|
||||
|
||||
//
|
||||
// If the process was running do we then perform network checks.
|
||||
//
|
||||
Logger.Info($"{nameof(GenerateServerStatusUpdateAsync)} Checking server local network status at {registration.LocalEndpoint}");
|
||||
|
||||
// get the server information direct from the server using local connection.
|
||||
GetLocalNetworkStatus(registration.LocalEndpoint, out QueryMaster.ServerInfo localInfo, out int onlinePlayerCount);
|
||||
|
||||
if (localInfo != null)
|
||||
{
|
||||
currentStatus = WatcherServerStatus.RunningLocalCheck;
|
||||
|
||||
//
|
||||
// Now that it's running, we can check the publication status.
|
||||
//
|
||||
Logger.Info($"{nameof(GenerateServerStatusUpdateAsync)} Checking server public status direct at {registration.SteamEndpoint}");
|
||||
|
||||
// get the server information direct from the server using public connection.
|
||||
var serverStatus = CheckServerStatusDirect(registration.SteamEndpoint);
|
||||
// check if the server returned the information.
|
||||
if (!serverStatus)
|
||||
{
|
||||
// server did not return any information
|
||||
var nextExternalStatusQuery = _nextExternalStatusQuery.ContainsKey(registrationKey) ? _nextExternalStatusQuery[registrationKey] : DateTime.MinValue;
|
||||
if (DateTime.Now >= nextExternalStatusQuery)
|
||||
{
|
||||
currentStatus = WatcherServerStatus.RunningExternalCheck;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Config.Default.ServerStatusUrlFormat))
|
||||
{
|
||||
Logger.Info($"{nameof(GenerateServerStatusUpdateAsync)} Checking server public status via api at {registration.SteamEndpoint}");
|
||||
|
||||
// get the server information direct from the server using external connection.
|
||||
var uri = new Uri(string.Format(Config.Default.ServerStatusUrlFormat, Config.Default.ServerManagerCode, App.Instance.Version, registration.SteamEndpoint.Address, registration.SteamEndpoint.Port));
|
||||
serverStatus = await NetworkUtils.CheckServerStatusViaAPI(uri, registration.SteamEndpoint);
|
||||
}
|
||||
|
||||
_nextExternalStatusQuery[registrationKey] = DateTime.Now.AddMilliseconds(Config.Default.ServerStatusWatcher_RemoteStatusQueryDelay);
|
||||
}
|
||||
}
|
||||
|
||||
// check if the server returned the information.
|
||||
if (serverStatus)
|
||||
{
|
||||
currentStatus = WatcherServerStatus.Published;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var statusUpdate = new ServerStatusUpdate
|
||||
{
|
||||
Process = process,
|
||||
Status = currentStatus,
|
||||
ServerInfo = localInfo,
|
||||
OnlinePlayerCount = onlinePlayerCount
|
||||
};
|
||||
|
||||
return await Task.FromResult(statusUpdate);
|
||||
}
|
||||
|
||||
private static bool GetLocalNetworkStatus(IPEndPoint endpoint, out QueryMaster.ServerInfo serverInfo, out int onlinePlayerCount)
|
||||
{
|
||||
serverInfo = null;
|
||||
onlinePlayerCount = 0;
|
||||
|
||||
try
|
||||
{
|
||||
using (var server = QueryMaster.ServerQuery.GetServerInstance(QueryMaster.EngineType.Source, endpoint))
|
||||
{
|
||||
try
|
||||
{
|
||||
serverInfo = server?.GetInfo();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
serverInfo = null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var players = server?.GetPlayers()?.Where(p => !string.IsNullOrWhiteSpace(p.Name?.Trim()));
|
||||
onlinePlayerCount = players?.Count() ?? 0;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
onlinePlayerCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
Logger.Debug($"{nameof(GetLocalNetworkStatus)} failed: {endpoint.Address}:{endpoint.Port}. {ex.Message}");
|
||||
// Common when the server is unreachable. Ignore it.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool CheckServerStatusDirect(IPEndPoint endpoint)
|
||||
{
|
||||
try
|
||||
{
|
||||
QueryMaster.ServerInfo serverInfo;
|
||||
|
||||
using (var server = QueryMaster.ServerQuery.GetServerInstance(QueryMaster.EngineType.Source, endpoint))
|
||||
{
|
||||
serverInfo = server.GetInfo();
|
||||
}
|
||||
|
||||
return serverInfo != null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Debug($"{nameof(CheckServerStatusDirect)} - Failed checking status direct for: {endpoint.Address}:{endpoint.Port}. {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class DifficultyOffsetValueConverter : IValueConverter
|
||||
{
|
||||
public const double MinValue = 50;
|
||||
public const double MaxValue = 400;
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
double scaledValue = System.Convert.ToDouble(value); ;
|
||||
var sliderValue = MinValue + (scaledValue * (MaxValue - MinValue));
|
||||
sliderValue = Math.Max(MinValue, sliderValue);
|
||||
return sliderValue;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
var sliderValue = System.Convert.ToDouble(value);
|
||||
sliderValue = (double)sliderValue - (double)MinValue;
|
||||
var scaledValue = sliderValue / (double)(MaxValue - MinValue);
|
||||
scaledValue = Math.Max(0.01, scaledValue);
|
||||
return scaledValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class DinoNameValueConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var strVal = value as string;
|
||||
return strVal.Substring(0, strVal.IndexOf('_'));
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class EngramClassNameToDisplayNameConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return Convert(value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static object Convert(object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var strVal = value as string;
|
||||
var name = GameData.FriendlyNameForClass(strVal);
|
||||
if (!string.IsNullOrWhiteSpace(name) && !name.Equals(strVal))
|
||||
return name;
|
||||
|
||||
var firstIndex = strVal.IndexOf('_') + 1;
|
||||
var length = strVal.LastIndexOf('_') - firstIndex;
|
||||
return strVal.Substring(firstIndex, length);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using WPFSharp.Globalizer;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class EnumDescriptionTypeConverter : EnumConverter
|
||||
{
|
||||
public EnumDescriptionTypeConverter(Type type)
|
||||
: base(type)
|
||||
{
|
||||
}
|
||||
|
||||
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(string))
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
var strType = value.GetType().Name;
|
||||
var strVal = value.ToString();
|
||||
|
||||
return GlobalizedApplication.Instance.GetResourceString($"{strType}_{strVal}") ?? strVal;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using ServerManagerTool.Utils;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class ExtinctionEventDateConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
double scaledValue = System.Convert.ToInt32(value);
|
||||
|
||||
if (scaledValue <= 0)
|
||||
return string.Empty;
|
||||
|
||||
var displayValue = ModUtils.UnixTimeStampToDateTime(scaledValue);
|
||||
return displayValue.ToString(CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class ExtinctionEventTimeIntervalConverter : IValueConverter
|
||||
{
|
||||
public const int MIN_VALUE = 1;
|
||||
public const int MAX_VALUE = 1000;
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
double scaledValue = System.Convert.ToInt32(value);
|
||||
|
||||
var sliderValue = (int)TimeSpan.FromSeconds(scaledValue).TotalDays;
|
||||
sliderValue = Math.Max(MIN_VALUE, sliderValue);
|
||||
sliderValue = Math.Min(MAX_VALUE, sliderValue);
|
||||
return sliderValue;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var sliderValue = System.Convert.ToInt32(value);
|
||||
sliderValue = Math.Max(MIN_VALUE, sliderValue);
|
||||
sliderValue = Math.Min(MAX_VALUE, sliderValue);
|
||||
|
||||
var scaledValue = (int)TimeSpan.FromDays(sliderValue).TotalSeconds;
|
||||
return scaledValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
|
||||
public class PlayerLevelIndexToDisplayLevelConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return (int)value + 2;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class DinoLevelIndexToDisplayLevelConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return (int)value + 1;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
using ServerManagerTool.Utils;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using WPFSharp.Globalizer;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class MapNameValueConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
try
|
||||
{
|
||||
var valueString = value as string;
|
||||
if (valueString == null)
|
||||
return string.Empty;
|
||||
|
||||
var name = GlobalizedApplication.Instance.GetResourceString(valueString);
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
return name;
|
||||
|
||||
var mapName = ModUtils.GetMapName(valueString);
|
||||
|
||||
// check if the name is stored in the globalization file
|
||||
name = GlobalizedApplication.Instance.GetResourceString(mapName);
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
return name;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(mapName))
|
||||
return mapName;
|
||||
|
||||
return valueString;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return value ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class OfficialDifficultyValueConverter : IValueConverter
|
||||
{
|
||||
public const double DINO_LEVELS = 30.0f;
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
var scaledValue = System.Convert.ToDouble(value);
|
||||
scaledValue = Math.Max(1.0, scaledValue);
|
||||
|
||||
var sliderValue = scaledValue * DINO_LEVELS;
|
||||
sliderValue = Math.Max(DINO_LEVELS, sliderValue);
|
||||
|
||||
return (int)sliderValue;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
var sliderValue = System.Convert.ToDouble(value);
|
||||
sliderValue = Math.Max(DINO_LEVELS, sliderValue);
|
||||
|
||||
var scaledValue = sliderValue / DINO_LEVELS;
|
||||
scaledValue = Math.Max(1.0, scaledValue);
|
||||
|
||||
return scaledValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class PrimalItemClassNameToDisplayNameConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return Convert(value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static object Convert(object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var strVal = value as string;
|
||||
var name = GameData.FriendlyNameForClass(strVal);
|
||||
if (!string.IsNullOrWhiteSpace(name) && !name.Equals(strVal))
|
||||
return name;
|
||||
|
||||
var firstIndex = strVal.IndexOf('_');
|
||||
var lastIndex = strVal.LastIndexOf('_');
|
||||
return strVal.Substring(firstIndex + 1, lastIndex - firstIndex - 1).Replace('_', ' ');
|
||||
}
|
||||
catch
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class ResourceNameValueConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return Convert(value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static object Convert(object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var strVal = value as string;
|
||||
var name = GameData.FriendlyNameForClass(strVal);
|
||||
if (!string.IsNullOrWhiteSpace(name) && !name.Equals(strVal))
|
||||
return name;
|
||||
|
||||
var firstIndex = strVal.IndexOf('_');
|
||||
var lastIndex = strVal.LastIndexOf('_');
|
||||
return strVal.Substring(firstIndex + 1, lastIndex - firstIndex - 1).Replace('_', ' ');
|
||||
}
|
||||
catch
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class SupplyCrateClassNameToDisplayNameConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return Convert(value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static object Convert(object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var strVal = value as string;
|
||||
var name = GameData.FriendlyNameForClass(strVal);
|
||||
if (!string.IsNullOrWhiteSpace(name) && !name.Equals(strVal))
|
||||
return name;
|
||||
|
||||
var firstIndex = strVal.IndexOf('_');
|
||||
var lastIndex = strVal.LastIndexOf('_');
|
||||
return strVal.Substring(0, lastIndex - firstIndex - 1).Replace('_', ' ');
|
||||
}
|
||||
catch
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class TributeExpirationConverter : IValueConverter
|
||||
{
|
||||
public const int MIN_VALUE = 1;
|
||||
public const int MAX_VALUE = 20000;
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
double scaledValue = System.Convert.ToInt32(value);
|
||||
|
||||
var sliderValue = (int)TimeSpan.FromSeconds(scaledValue).TotalMinutes;
|
||||
sliderValue = Math.Max(MIN_VALUE, sliderValue);
|
||||
sliderValue = Math.Min(MAX_VALUE, sliderValue);
|
||||
return sliderValue;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var sliderValue = System.Convert.ToInt32(value);
|
||||
sliderValue = Math.Max(MIN_VALUE, sliderValue);
|
||||
sliderValue = Math.Min(MAX_VALUE, sliderValue);
|
||||
|
||||
var scaledValue = (int)TimeSpan.FromMinutes(sliderValue).TotalSeconds;
|
||||
return scaledValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
132
src/ARKServerManager/Lib/ViewModel/DinoSettings.cs
Normal file
132
src/ARKServerManager/Lib/ViewModel/DinoSettings.cs
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
using ServerManagerTool.Enums;
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
//
|
||||
// This class aggregates many settings related to dinos
|
||||
//
|
||||
public class DinoSettings : DependencyObject
|
||||
{
|
||||
public static readonly DependencyProperty ClassNameProperty = DependencyProperty.Register(nameof(ClassName), typeof(string), typeof(DinoSettings), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty ModProperty = DependencyProperty.Register(nameof(Mod), typeof(string), typeof(DinoSettings), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty KnownDinoProperty = DependencyProperty.Register(nameof(KnownDino), typeof(bool), typeof(DinoSettings), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty CanTameProperty = DependencyProperty.Register(nameof(CanTame), typeof(bool), typeof(DinoSettings), new PropertyMetadata(true));
|
||||
public static readonly DependencyProperty CanSpawnProperty = DependencyProperty.Register(nameof(CanSpawn), typeof(bool), typeof(DinoSettings), new PropertyMetadata(true));
|
||||
public static readonly DependencyProperty ReplacementClassProperty = DependencyProperty.Register(nameof(ReplacementClass), typeof(string), typeof(DinoSettings), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty SpawnWeightMultiplierProperty = DependencyProperty.Register(nameof(SpawnWeightMultiplier), typeof(float), typeof(DinoSettings), new PropertyMetadata(DinoSpawn.DEFAULT_SPAWN_WEIGHT_MULTIPLIER));
|
||||
public static readonly DependencyProperty OverrideSpawnLimitPercentageProperty = DependencyProperty.Register(nameof(OverrideSpawnLimitPercentage), typeof(bool), typeof(DinoSettings), new PropertyMetadata(DinoSpawn.DEFAULT_OVERRIDE_SPAWN_LIMIT_PERCENTAGE));
|
||||
public static readonly DependencyProperty SpawnLimitPercentageProperty = DependencyProperty.Register(nameof(SpawnLimitPercentage), typeof(float), typeof(DinoSettings), new PropertyMetadata(DinoSpawn.DEFAULT_SPAWN_LIMIT_PERCENTAGE));
|
||||
public static readonly DependencyProperty TamedDamageMultiplierProperty = DependencyProperty.Register(nameof(TamedDamageMultiplier), typeof(float), typeof(DinoSettings), new PropertyMetadata(ClassMultiplier.DEFAULT_MULTIPLIER));
|
||||
public static readonly DependencyProperty TamedResistanceMultiplierProperty = DependencyProperty.Register(nameof(TamedResistanceMultiplier), typeof(float), typeof(DinoSettings), new PropertyMetadata(ClassMultiplier.DEFAULT_MULTIPLIER));
|
||||
public static readonly DependencyProperty WildDamageMultiplierProperty = DependencyProperty.Register(nameof(WildDamageMultiplier), typeof(float), typeof(DinoSettings), new PropertyMetadata(ClassMultiplier.DEFAULT_MULTIPLIER));
|
||||
public static readonly DependencyProperty WildResistanceMultiplierProperty = DependencyProperty.Register(nameof(WildResistanceMultiplier), typeof(float), typeof(DinoSettings), new PropertyMetadata(ClassMultiplier.DEFAULT_MULTIPLIER));
|
||||
|
||||
public string ClassName
|
||||
{
|
||||
get { return (string)GetValue(ClassNameProperty); }
|
||||
set { SetValue(ClassNameProperty, value); }
|
||||
}
|
||||
|
||||
public string Mod
|
||||
{
|
||||
get { return (string)GetValue(ModProperty); }
|
||||
set { SetValue(ModProperty, value); }
|
||||
}
|
||||
|
||||
public bool KnownDino
|
||||
{
|
||||
get { return (bool)GetValue(KnownDinoProperty); }
|
||||
set { SetValue(KnownDinoProperty, value); }
|
||||
}
|
||||
|
||||
public bool CanTame
|
||||
{
|
||||
get { return (bool)GetValue(CanTameProperty); }
|
||||
set { SetValue(CanTameProperty, value); }
|
||||
}
|
||||
|
||||
public bool CanSpawn
|
||||
{
|
||||
get { return (bool)GetValue(CanSpawnProperty); }
|
||||
set { SetValue(CanSpawnProperty, value); }
|
||||
}
|
||||
|
||||
public string ReplacementClass
|
||||
{
|
||||
get { return (string)GetValue(ReplacementClassProperty); }
|
||||
set { SetValue(ReplacementClassProperty, value); }
|
||||
}
|
||||
|
||||
public float SpawnWeightMultiplier
|
||||
{
|
||||
get { return (float)GetValue(SpawnWeightMultiplierProperty); }
|
||||
set { SetValue(SpawnWeightMultiplierProperty, value); }
|
||||
}
|
||||
|
||||
public bool OverrideSpawnLimitPercentage
|
||||
{
|
||||
get { return (bool)GetValue(OverrideSpawnLimitPercentageProperty); }
|
||||
set { SetValue(OverrideSpawnLimitPercentageProperty, value); }
|
||||
}
|
||||
|
||||
public float SpawnLimitPercentage
|
||||
{
|
||||
get { return (float)GetValue(SpawnLimitPercentageProperty); }
|
||||
set { SetValue(SpawnLimitPercentageProperty, value); }
|
||||
}
|
||||
|
||||
public float TamedDamageMultiplier
|
||||
{
|
||||
get { return (float)GetValue(TamedDamageMultiplierProperty); }
|
||||
set { SetValue(TamedDamageMultiplierProperty, value); }
|
||||
}
|
||||
|
||||
public float TamedResistanceMultiplier
|
||||
{
|
||||
get { return (float)GetValue(TamedResistanceMultiplierProperty); }
|
||||
set { SetValue(TamedResistanceMultiplierProperty, value); }
|
||||
}
|
||||
|
||||
public float WildDamageMultiplier
|
||||
{
|
||||
get { return (float)GetValue(WildDamageMultiplierProperty); }
|
||||
set { SetValue(WildDamageMultiplierProperty, value); }
|
||||
}
|
||||
|
||||
public float WildResistanceMultiplier
|
||||
{
|
||||
get { return (float)GetValue(WildResistanceMultiplierProperty); }
|
||||
set { SetValue(WildResistanceMultiplierProperty, value); }
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlyCreatureNameForClass(ClassName);
|
||||
public string DisplayMod => GameData.FriendlyNameForClass($"Mod_{Mod}", true) ?? Mod;
|
||||
public string NameTag { get; internal set; }
|
||||
public bool HasNameTag { get; internal set; }
|
||||
public bool HasClassName { get; internal set; }
|
||||
public bool IsSpawnable { get; internal set; }
|
||||
public DinoTamable IsTameable { get; internal set; }
|
||||
public string DisplayReplacementName => GameData.FriendlyCreatureNameForClass(ReplacementClass);
|
||||
|
||||
public float OriginalSpawnWeightMultiplier { get; internal set; }
|
||||
public bool OriginalOverrideSpawnLimitPercentage { get; internal set; }
|
||||
public float OriginalSpawnLimitPercentage { get; internal set; }
|
||||
|
||||
#region Sort Properties
|
||||
public string NameSort => $"{DisplayName}|{Mod}";
|
||||
public string ModSort => $"{Mod}|{DisplayName}";
|
||||
public string CanSpawnSort => $"{IsSpawnable}|{CanSpawn}|{DisplayName}|{Mod}";
|
||||
public string CanTameSort => $"{IsTameable != DinoTamable.False}|{CanTame}|{DisplayName}|{Mod}";
|
||||
public string ReplacementNameSort => $"{DisplayReplacementName}|{Mod}";
|
||||
public string SpawnWeightMultiplierSort => $"{SpawnWeightMultiplier:0000000000.0000000000}|{DisplayName}|{Mod}";
|
||||
public string OverrideSpawnLimitPercentageSort => $"{OverrideSpawnLimitPercentage}|{DisplayName}|{Mod}";
|
||||
public string SpawnLimitPercentageSort => $"{SpawnLimitPercentage:0000000000.0000000000}|{DisplayName}|{Mod}";
|
||||
public string TamedDamageMultiplierSort => $"{TamedDamageMultiplier:0000000000.0000000000}|{DisplayName}|{Mod}";
|
||||
public string TamedResistanceMultiplierSort => $"{TamedResistanceMultiplier:0000000000.0000000000}|{DisplayName}|{Mod}";
|
||||
public string WildDamageMultiplierSort => $"{WildDamageMultiplier:0000000000.0000000000}|{DisplayName}|{Mod}";
|
||||
public string WildResistanceMultiplierSort => $"{WildResistanceMultiplier:0000000000.0000000000}|{DisplayName}|{Mod}";
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
316
src/ARKServerManager/Lib/ViewModel/DinoSettingsList.cs
Normal file
316
src/ARKServerManager/Lib/ViewModel/DinoSettingsList.cs
Normal file
|
|
@ -0,0 +1,316 @@
|
|||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Enums;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class DinoSettingsList : SortableObservableCollection<DinoSettings>
|
||||
{
|
||||
public AggregateIniValueList<DinoSpawn> DinoSpawnWeightMultipliers { get; }
|
||||
public StringIniValueList PreventDinoTameClassNames { get; }
|
||||
public AggregateIniValueList<NPCReplacement> NpcReplacements { get; }
|
||||
public AggregateIniValueList<ClassMultiplier> TamedDinoClassDamageMultipliers { get; }
|
||||
public AggregateIniValueList<ClassMultiplier> TamedDinoClassResistanceMultipliers { get; }
|
||||
public AggregateIniValueList<ClassMultiplier> DinoClassDamageMultipliers { get; }
|
||||
public AggregateIniValueList<ClassMultiplier> DinoClassResistanceMultipliers { get; }
|
||||
|
||||
public DinoSettingsList()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public DinoSettingsList(AggregateIniValueList<DinoSpawn> dinoSpawnWeightMultipliers, StringIniValueList preventDinoTameClassNames, AggregateIniValueList<NPCReplacement> npcReplacements,
|
||||
AggregateIniValueList<ClassMultiplier> tamedDinoClassDamageMultipliers, AggregateIniValueList<ClassMultiplier> tamedDinoClassResistanceMultipliers,
|
||||
AggregateIniValueList<ClassMultiplier> dinoClassDamageMultipliers, AggregateIniValueList<ClassMultiplier> dinoClassResistanceMultipliers)
|
||||
{
|
||||
this.DinoSpawnWeightMultipliers = dinoSpawnWeightMultipliers;
|
||||
this.PreventDinoTameClassNames = preventDinoTameClassNames;
|
||||
this.NpcReplacements = npcReplacements;
|
||||
this.TamedDinoClassDamageMultipliers = tamedDinoClassDamageMultipliers;
|
||||
this.TamedDinoClassResistanceMultipliers = tamedDinoClassResistanceMultipliers;
|
||||
this.DinoClassDamageMultipliers = dinoClassDamageMultipliers;
|
||||
this.DinoClassResistanceMultipliers = dinoClassResistanceMultipliers;
|
||||
Reset();
|
||||
}
|
||||
|
||||
private DinoSettings CreateDinoSetting(string className, string mod, bool knownDino, bool hasNameTag, bool hasClassName)
|
||||
{
|
||||
var nameTag = GameData.NameTagForClass(className);
|
||||
var isSpawnable = GameData.IsSpawnableForClass(className);
|
||||
var isTameable = GameData.IsTameableForClass(className);
|
||||
|
||||
return new DinoSettings()
|
||||
{
|
||||
ClassName = className,
|
||||
Mod = mod,
|
||||
KnownDino = knownDino,
|
||||
NameTag = nameTag,
|
||||
|
||||
CanSpawn = true,
|
||||
CanTame = isTameable != DinoTamable.False,
|
||||
ReplacementClass = className,
|
||||
|
||||
SpawnWeightMultiplier = DinoSpawn.DEFAULT_SPAWN_WEIGHT_MULTIPLIER,
|
||||
OverrideSpawnLimitPercentage = DinoSpawn.DEFAULT_OVERRIDE_SPAWN_LIMIT_PERCENTAGE,
|
||||
SpawnLimitPercentage = DinoSpawn.DEFAULT_SPAWN_LIMIT_PERCENTAGE,
|
||||
OriginalSpawnWeightMultiplier = DinoSpawn.DEFAULT_SPAWN_WEIGHT_MULTIPLIER,
|
||||
OriginalOverrideSpawnLimitPercentage = DinoSpawn.DEFAULT_OVERRIDE_SPAWN_LIMIT_PERCENTAGE,
|
||||
OriginalSpawnLimitPercentage = DinoSpawn.DEFAULT_SPAWN_LIMIT_PERCENTAGE,
|
||||
|
||||
TamedDamageMultiplier = ClassMultiplier.DEFAULT_MULTIPLIER,
|
||||
TamedResistanceMultiplier = ClassMultiplier.DEFAULT_MULTIPLIER,
|
||||
WildDamageMultiplier = ClassMultiplier.DEFAULT_MULTIPLIER,
|
||||
WildResistanceMultiplier = ClassMultiplier.DEFAULT_MULTIPLIER,
|
||||
|
||||
HasClassName = hasClassName,
|
||||
HasNameTag = hasNameTag,
|
||||
IsSpawnable = isSpawnable,
|
||||
IsTameable = isTameable,
|
||||
};
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.Clear();
|
||||
|
||||
var dinoSpawns = GameData.GetDinoSpawns();
|
||||
foreach (var entry in dinoSpawns)
|
||||
{
|
||||
this.Add(CreateDinoSetting(entry.ClassName, entry.Mod, entry.KnownDino, entry.DinoNameTag != null, true));
|
||||
}
|
||||
|
||||
Sort(d => d.NameSort);
|
||||
}
|
||||
|
||||
public void RenderToView()
|
||||
{
|
||||
Reset();
|
||||
|
||||
foreach(var entry in this.DinoSpawnWeightMultipliers)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entry.DinoNameTag))
|
||||
continue;
|
||||
|
||||
var dinoSettings = this.Where(vi => vi.NameTag == entry.DinoNameTag).ToArray();
|
||||
if (dinoSettings == null || dinoSettings.Length == 0)
|
||||
{
|
||||
this.Add(CreateDinoSetting(entry.DinoNameTag, entry.Mod, entry.KnownDino, true, false));
|
||||
}
|
||||
|
||||
dinoSettings = this.Where(vi => vi.NameTag == entry.DinoNameTag).ToArray();
|
||||
foreach (var dinoSetting in dinoSettings)
|
||||
{
|
||||
dinoSetting.SpawnWeightMultiplier = entry.SpawnWeightMultiplier;
|
||||
dinoSetting.OverrideSpawnLimitPercentage = entry.OverrideSpawnLimitPercentage;
|
||||
dinoSetting.SpawnLimitPercentage = entry.SpawnLimitPercentage;
|
||||
|
||||
dinoSetting.OriginalSpawnWeightMultiplier = entry.SpawnWeightMultiplier;
|
||||
dinoSetting.OriginalOverrideSpawnLimitPercentage = entry.OverrideSpawnLimitPercentage;
|
||||
dinoSetting.OriginalSpawnLimitPercentage = entry.SpawnLimitPercentage;
|
||||
}
|
||||
}
|
||||
|
||||
foreach(var entry in this.PreventDinoTameClassNames)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entry))
|
||||
continue;
|
||||
|
||||
var dinoSettings = this.Where(vi => vi.ClassName == entry).ToArray();
|
||||
if (dinoSettings == null || dinoSettings.Length == 0)
|
||||
{
|
||||
this.Add(CreateDinoSetting(entry, GameData.MOD_UNKNOWN, false, false, true));
|
||||
}
|
||||
|
||||
dinoSettings = this.Where(vi => vi.ClassName == entry).ToArray();
|
||||
foreach (var dinoSetting in dinoSettings)
|
||||
{
|
||||
dinoSetting.CanTame = false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach(var entry in this.NpcReplacements)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entry.FromClassName))
|
||||
continue;
|
||||
|
||||
var dinoSettings = this.Where(vi => vi.ClassName == entry.FromClassName).ToArray();
|
||||
if (dinoSettings == null || dinoSettings.Length == 0)
|
||||
{
|
||||
this.Add(CreateDinoSetting(entry.FromClassName, GameData.MOD_UNKNOWN, false, false, true));
|
||||
}
|
||||
|
||||
dinoSettings = this.Where(vi => vi.ClassName == entry.FromClassName).ToArray();
|
||||
foreach (var dinoSetting in dinoSettings)
|
||||
{
|
||||
dinoSetting.CanSpawn = !string.IsNullOrWhiteSpace(entry.ToClassName);
|
||||
dinoSetting.ReplacementClass = dinoSetting.CanSpawn ? entry.ToClassName : dinoSetting.ClassName;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var entry in this.TamedDinoClassDamageMultipliers)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entry.ClassName))
|
||||
continue;
|
||||
|
||||
var dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
|
||||
if (dinoSettings == null || dinoSettings.Length == 0)
|
||||
{
|
||||
this.Add(CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true));
|
||||
}
|
||||
|
||||
dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
|
||||
foreach (var dinoSetting in dinoSettings)
|
||||
{
|
||||
dinoSetting.TamedDamageMultiplier = entry.Multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
foreach(var entry in this.TamedDinoClassResistanceMultipliers)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entry.ClassName))
|
||||
continue;
|
||||
|
||||
var dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
|
||||
if (dinoSettings == null || dinoSettings.Length == 0)
|
||||
{
|
||||
this.Add(CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true));
|
||||
}
|
||||
|
||||
dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
|
||||
foreach (var dinoSetting in dinoSettings)
|
||||
{
|
||||
dinoSetting.TamedResistanceMultiplier = entry.Multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var entry in this.DinoClassDamageMultipliers)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entry.ClassName))
|
||||
continue;
|
||||
|
||||
var dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
|
||||
if (dinoSettings == null || dinoSettings.Length == 0)
|
||||
{
|
||||
this.Add(CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true));
|
||||
}
|
||||
|
||||
dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
|
||||
foreach (var dinoSetting in dinoSettings)
|
||||
{
|
||||
dinoSetting.WildDamageMultiplier = entry.Multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var entry in this.DinoClassResistanceMultipliers)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entry.ClassName))
|
||||
continue;
|
||||
|
||||
var dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
|
||||
if (dinoSettings == null || dinoSettings.Length == 0)
|
||||
{
|
||||
this.Add(CreateDinoSetting(entry.ClassName, GameData.MOD_UNKNOWN, false, false, true));
|
||||
}
|
||||
|
||||
dinoSettings = this.Where(vi => vi.ClassName == entry.ClassName).ToArray();
|
||||
foreach (var dinoSetting in dinoSettings)
|
||||
{
|
||||
dinoSetting.WildResistanceMultiplier = entry.Multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
Sort(d => d.NameSort);
|
||||
}
|
||||
|
||||
public void RenderToModel()
|
||||
{
|
||||
this.DinoSpawnWeightMultipliers.Clear();
|
||||
this.PreventDinoTameClassNames.Clear();
|
||||
this.PreventDinoTameClassNames.IsEnabled = true;
|
||||
this.NpcReplacements.Clear();
|
||||
this.NpcReplacements.IsEnabled = true;
|
||||
this.TamedDinoClassDamageMultipliers.Clear();
|
||||
this.TamedDinoClassResistanceMultipliers.Clear();
|
||||
this.DinoClassDamageMultipliers.Clear();
|
||||
this.DinoClassResistanceMultipliers.Clear();
|
||||
|
||||
foreach(var entry in this)
|
||||
{
|
||||
if (entry.HasNameTag && !string.IsNullOrWhiteSpace(entry.NameTag))
|
||||
{
|
||||
if (!entry.KnownDino ||
|
||||
!entry.OverrideSpawnLimitPercentage.Equals(DinoSpawn.DEFAULT_OVERRIDE_SPAWN_LIMIT_PERCENTAGE) ||
|
||||
!entry.SpawnLimitPercentage.Equals(DinoSpawn.DEFAULT_SPAWN_LIMIT_PERCENTAGE) ||
|
||||
!entry.SpawnWeightMultiplier.Equals(DinoSpawn.DEFAULT_SPAWN_WEIGHT_MULTIPLIER))
|
||||
{
|
||||
|
||||
var dinoSpawns = this.DinoSpawnWeightMultipliers.Where(d => d.DinoNameTag.Equals(entry.NameTag, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
if (dinoSpawns == null || dinoSpawns.Length == 0)
|
||||
{
|
||||
this.DinoSpawnWeightMultipliers.Add(new DinoSpawn()
|
||||
{
|
||||
ClassName = entry.ClassName,
|
||||
DinoNameTag = entry.NameTag,
|
||||
OverrideSpawnLimitPercentage = entry.OverrideSpawnLimitPercentage,
|
||||
SpawnLimitPercentage = entry.SpawnLimitPercentage,
|
||||
SpawnWeightMultiplier = entry.SpawnWeightMultiplier
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var dinoSpawn in dinoSpawns)
|
||||
{
|
||||
if (entry.SpawnWeightMultiplier != entry.OriginalSpawnWeightMultiplier ||
|
||||
entry.OverrideSpawnLimitPercentage != entry.OriginalOverrideSpawnLimitPercentage ||
|
||||
entry.SpawnLimitPercentage != entry.OriginalSpawnLimitPercentage)
|
||||
{
|
||||
dinoSpawn.OverrideSpawnLimitPercentage = entry.OverrideSpawnLimitPercentage;
|
||||
dinoSpawn.SpawnLimitPercentage = entry.SpawnLimitPercentage;
|
||||
dinoSpawn.SpawnWeightMultiplier = entry.SpawnWeightMultiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.HasClassName && !string.IsNullOrWhiteSpace(entry.ClassName))
|
||||
{
|
||||
if ((entry.IsTameable != DinoTamable.False) && !entry.CanTame)
|
||||
{
|
||||
this.PreventDinoTameClassNames.Add(entry.ClassName);
|
||||
}
|
||||
|
||||
this.NpcReplacements.Add(new NPCReplacement() { FromClassName = entry.ClassName, ToClassName = entry.CanSpawn ? entry.ReplacementClass : string.Empty });
|
||||
|
||||
if (entry.IsTameable != DinoTamable.False)
|
||||
{
|
||||
// check if the value has changed.
|
||||
if (!entry.TamedDamageMultiplier.Equals(ClassMultiplier.DEFAULT_MULTIPLIER))
|
||||
this.TamedDinoClassDamageMultipliers.Add(new ClassMultiplier() { ClassName = entry.ClassName, Multiplier = entry.TamedDamageMultiplier });
|
||||
|
||||
// check if the value has changed.
|
||||
if (!entry.TamedResistanceMultiplier.Equals(ClassMultiplier.DEFAULT_MULTIPLIER))
|
||||
this.TamedDinoClassResistanceMultipliers.Add(new ClassMultiplier() { ClassName = entry.ClassName, Multiplier = entry.TamedResistanceMultiplier });
|
||||
}
|
||||
|
||||
// check if the value has changed.
|
||||
if (!entry.WildDamageMultiplier.Equals(ClassMultiplier.DEFAULT_MULTIPLIER))
|
||||
this.DinoClassDamageMultipliers.Add(new ClassMultiplier() { ClassName = entry.ClassName, Multiplier = entry.WildDamageMultiplier });
|
||||
|
||||
// check if the value has changed.
|
||||
if (!entry.WildResistanceMultiplier.Equals(ClassMultiplier.DEFAULT_MULTIPLIER))
|
||||
this.DinoClassResistanceMultipliers.Add(new ClassMultiplier() { ClassName = entry.ClassName, Multiplier = entry.WildResistanceMultiplier });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateForLocalization()
|
||||
{
|
||||
//foreach (var dinoSetting in this)
|
||||
//{
|
||||
// dinoSetting.FriendlyName = GameData.FriendlyNameForClass(dinoSetting.ClassName);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
74
src/ARKServerManager/Lib/ViewModel/Engram.cs
Normal file
74
src/ARKServerManager/Lib/ViewModel/Engram.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class Engram : DependencyObject
|
||||
{
|
||||
public static readonly DependencyProperty EngramClassNameProperty = DependencyProperty.Register(nameof(EngramClassName), typeof(string), typeof(Engram), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty EngramLevelRequirementProperty = DependencyProperty.Register(nameof(EngramLevelRequirement), typeof(int), typeof(Engram), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty EngramPointsCostProperty = DependencyProperty.Register(nameof(EngramPointsCost), typeof(int), typeof(Engram), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty ModProperty = DependencyProperty.Register(nameof(Mod), typeof(string), typeof(Engram), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty KnownEngramProperty = DependencyProperty.Register(nameof(KnownEngram), typeof(bool), typeof(Engram), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty IsTekgramProperty = DependencyProperty.Register(nameof(IsTekgram), typeof(bool), typeof(EngramEntry), new PropertyMetadata(false));
|
||||
|
||||
public string EngramClassName
|
||||
{
|
||||
get { return (string)GetValue(EngramClassNameProperty); }
|
||||
set { SetValue(EngramClassNameProperty, value); }
|
||||
}
|
||||
|
||||
public int EngramLevelRequirement
|
||||
{
|
||||
get { return (int)GetValue(EngramLevelRequirementProperty); }
|
||||
set { SetValue(EngramLevelRequirementProperty, value); }
|
||||
}
|
||||
|
||||
public int EngramPointsCost
|
||||
{
|
||||
get { return (int)GetValue(EngramPointsCostProperty); }
|
||||
set { SetValue(EngramPointsCostProperty, value); }
|
||||
}
|
||||
|
||||
public string Mod
|
||||
{
|
||||
get { return (string)GetValue(ModProperty); }
|
||||
set { SetValue(ModProperty, value); }
|
||||
}
|
||||
|
||||
public bool KnownEngram
|
||||
{
|
||||
get { return (bool)GetValue(KnownEngramProperty); }
|
||||
set { SetValue(KnownEngramProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsTekgram
|
||||
{
|
||||
get { return (bool)GetValue(IsTekgramProperty); }
|
||||
set { SetValue(IsTekgramProperty, value); }
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlyEngramNameForClass(EngramClassName);
|
||||
|
||||
public string DisplayMod => GameData.FriendlyNameForClass($"Mod_{Mod}", true) ?? Mod;
|
||||
|
||||
public Engram Duplicate()
|
||||
{
|
||||
var properties = this.GetType().GetProperties();
|
||||
|
||||
var result = new Engram();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.CanWrite)
|
||||
prop.SetValue(result, prop.GetValue(this));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
362
src/ARKServerManager/Lib/ViewModel/EngramSettings.cs
Normal file
362
src/ARKServerManager/Lib/ViewModel/EngramSettings.cs
Normal file
|
|
@ -0,0 +1,362 @@
|
|||
using ServerManagerTool.Common.Model;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
[DataContract]
|
||||
public class EngramSettingsList : SortableObservableCollection<EngramSettings>, INotifyPropertyChanged
|
||||
{
|
||||
internal EngramSettingsList()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public EngramSettingsList(EngramEntryList overrideNamedEngramEntries, EngramAutoUnlockList engramEntryAutoUnlocks)
|
||||
{
|
||||
OverrideNamedEngramEntries = overrideNamedEngramEntries;
|
||||
EngramEntryAutoUnlocks = engramEntryAutoUnlocks;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get { return Get<bool>(); }
|
||||
set { Set(value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public bool OnlyAllowSpecifiedEngrams
|
||||
{
|
||||
get { return Get<bool>(); }
|
||||
set { Set(value); }
|
||||
}
|
||||
|
||||
public EngramEntryList OverrideNamedEngramEntries { get; }
|
||||
|
||||
public EngramAutoUnlockList EngramEntryAutoUnlocks { get; }
|
||||
|
||||
public EngramSettings CreateEngramSetting(string className, string mod, bool knownEngram, bool isTekgram)
|
||||
{
|
||||
return new EngramSettings()
|
||||
{
|
||||
EngramClassName = className,
|
||||
Mod = mod,
|
||||
KnownEngram = knownEngram,
|
||||
IsTekgram = isTekgram,
|
||||
};
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.Clear();
|
||||
|
||||
IsEnabled = false;
|
||||
|
||||
var engrams = GameData.GetEngrams();
|
||||
foreach (var engram in engrams)
|
||||
{
|
||||
var engramSetting = CreateEngramSetting(engram.EngramClassName, engram.Mod, engram.KnownEngram, engram.IsTekgram);
|
||||
engramSetting.EngramLevelRequirement = engram.EngramLevelRequirement;
|
||||
engramSetting.EngramPointsCost = engram.EngramPointsCost;
|
||||
engramSetting.LevelToAutoUnlock = engram.EngramLevelRequirement;
|
||||
this.Add(engramSetting);
|
||||
}
|
||||
}
|
||||
|
||||
public void RenderToView()
|
||||
{
|
||||
Reset();
|
||||
|
||||
if (this.OverrideNamedEngramEntries != null)
|
||||
{
|
||||
foreach (var entry in this.OverrideNamedEngramEntries)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entry.EngramClassName))
|
||||
continue;
|
||||
|
||||
var engramSettings = this.Where(vi => vi.EngramClassName == entry.EngramClassName).ToArray();
|
||||
if (engramSettings == null || engramSettings.Length == 0)
|
||||
{
|
||||
var engram = GameData.GetEngramForClass(entry.EngramClassName);
|
||||
this.Add(CreateEngramSetting(entry.EngramClassName, engram?.Mod ?? GameData.MOD_UNKNOWN, engram?.KnownEngram ?? false, engram?.IsTekgram ?? false));
|
||||
}
|
||||
|
||||
engramSettings = this.Where(vi => vi.EngramClassName == entry.EngramClassName).ToArray();
|
||||
foreach (var engramSetting in engramSettings)
|
||||
{
|
||||
engramSetting.EngramLevelRequirement = entry.EngramLevelRequirement;
|
||||
engramSetting.EngramPointsCost = entry.EngramPointsCost;
|
||||
engramSetting.EngramHidden = entry.EngramHidden;
|
||||
engramSetting.RemoveEngramPreReq = entry.RemoveEngramPreReq;
|
||||
engramSetting.LevelToAutoUnlock = entry.EngramLevelRequirement;
|
||||
engramSetting.SaveEngramOverride = true;
|
||||
|
||||
if (engramSetting.IsTekgram)
|
||||
{
|
||||
// always make sure that the tekgrams have default values.
|
||||
engramSetting.EngramLevelRequirement = 0;
|
||||
engramSetting.EngramPointsCost = 0;
|
||||
engramSetting.LevelToAutoUnlock = 0;
|
||||
}
|
||||
|
||||
IsEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.EngramEntryAutoUnlocks != null)
|
||||
{
|
||||
foreach (var entry in this.EngramEntryAutoUnlocks)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entry.EngramClassName))
|
||||
continue;
|
||||
|
||||
var engramSettings = this.Where(vi => vi.EngramClassName == entry.EngramClassName).ToArray();
|
||||
if (engramSettings == null || engramSettings.Length == 0)
|
||||
{
|
||||
var engram = GameData.GetEngramForClass(entry.EngramClassName);
|
||||
this.Add(CreateEngramSetting(entry.EngramClassName, engram?.Mod ?? GameData.MOD_UNKNOWN, engram?.KnownEngram ?? false, engram?.IsTekgram ?? false));
|
||||
}
|
||||
|
||||
engramSettings = this.Where(vi => vi.EngramClassName == entry.EngramClassName).ToArray();
|
||||
foreach (var engramSetting in engramSettings)
|
||||
{
|
||||
engramSetting.EngramAutoUnlock = true;
|
||||
engramSetting.LevelToAutoUnlock = entry.LevelToAutoUnlock;
|
||||
engramSetting.SaveEngramOverride = true;
|
||||
|
||||
IsEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RenderToModel()
|
||||
{
|
||||
if (this.OverrideNamedEngramEntries != null)
|
||||
{
|
||||
this.OverrideNamedEngramEntries.Clear();
|
||||
this.OverrideNamedEngramEntries.IsEnabled = false;
|
||||
}
|
||||
|
||||
if (this.EngramEntryAutoUnlocks != null)
|
||||
{
|
||||
this.EngramEntryAutoUnlocks.Clear();
|
||||
this.EngramEntryAutoUnlocks.IsEnabled = false;
|
||||
}
|
||||
|
||||
if (!IsEnabled)
|
||||
return;
|
||||
|
||||
foreach (var entry in this)
|
||||
{
|
||||
if (!entry.IsValid)
|
||||
continue;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(entry.EngramClassName))
|
||||
{
|
||||
if (this.OverrideNamedEngramEntries != null && entry.ShouldSaveEngramEntry(OnlyAllowSpecifiedEngrams))
|
||||
{
|
||||
this.OverrideNamedEngramEntries.Add(entry.GetEngramEntry());
|
||||
this.OverrideNamedEngramEntries.IsEnabled = true;
|
||||
}
|
||||
|
||||
if (this.EngramEntryAutoUnlocks != null && entry.ShouldSaveEngramAutoUnlock(OnlyAllowSpecifiedEngrams))
|
||||
{
|
||||
this.EngramEntryAutoUnlocks.Add(entry.GetEngramAutoUnlock());
|
||||
this.EngramEntryAutoUnlocks.IsEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateForLocalization()
|
||||
{
|
||||
}
|
||||
|
||||
#region INotifyPropertyChanged
|
||||
private Dictionary<string, object> _properties = new Dictionary<string, object>();
|
||||
|
||||
protected T Get<T>([CallerMemberName] string name = null)
|
||||
{
|
||||
object value = null;
|
||||
if (_properties?.TryGetValue(name, out value) ?? false)
|
||||
return value == null ? default : (T)value;
|
||||
return default;
|
||||
}
|
||||
|
||||
protected void Set<T>(T value, [CallerMemberName] string name = null)
|
||||
{
|
||||
if (Equals(value, Get<T>(name)))
|
||||
return;
|
||||
if (_properties == null)
|
||||
_properties = new Dictionary<string, object>();
|
||||
_properties[name] = value;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(name));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class EngramSettings : DependencyObject
|
||||
{
|
||||
public static readonly DependencyProperty EngramClassNameProperty = DependencyProperty.Register(nameof(EngramClassName), typeof(string), typeof(EngramSettings), new PropertyMetadata(string.Empty));
|
||||
public static readonly DependencyProperty ModProperty = DependencyProperty.Register(nameof(Mod), typeof(string), typeof(EngramSettings), new PropertyMetadata(GameData.MOD_UNKNOWN));
|
||||
public static readonly DependencyProperty KnownEngramProperty = DependencyProperty.Register(nameof(KnownEngram), typeof(bool), typeof(EngramSettings), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty IsTekgramProperty = DependencyProperty.Register(nameof(IsTekgram), typeof(bool), typeof(EngramSettings), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty EngramLevelRequirementProperty = DependencyProperty.Register(nameof(EngramLevelRequirement), typeof(int), typeof(EngramSettings), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty EngramPointsCostProperty = DependencyProperty.Register(nameof(EngramPointsCost), typeof(int), typeof(EngramSettings), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty EngramHiddenProperty = DependencyProperty.Register(nameof(EngramHidden), typeof(bool), typeof(EngramSettings), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty RemoveEngramPreReqProperty = DependencyProperty.Register(nameof(RemoveEngramPreReq), typeof(bool), typeof(EngramSettings), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty EngramAutoUnlockProperty = DependencyProperty.Register(nameof(EngramAutoUnlock), typeof(bool), typeof(EngramSettings), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty LevelToAutoUnlockProperty = DependencyProperty.Register(nameof(LevelToAutoUnlock), typeof(int), typeof(EngramSettings), new PropertyMetadata(0));
|
||||
public static readonly DependencyProperty SaveEngramOverrideProperty = DependencyProperty.Register(nameof(SaveEngramOverride), typeof(bool), typeof(EngramSettings), new PropertyMetadata(false));
|
||||
|
||||
[DataMember]
|
||||
public string EngramClassName
|
||||
{
|
||||
get { return (string)GetValue(EngramClassNameProperty); }
|
||||
set { SetValue(EngramClassNameProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public string Mod
|
||||
{
|
||||
get { return (string)GetValue(ModProperty); }
|
||||
set { SetValue(ModProperty, value); }
|
||||
}
|
||||
|
||||
public bool KnownEngram
|
||||
{
|
||||
get { return (bool)GetValue(KnownEngramProperty); }
|
||||
set { SetValue(KnownEngramProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public bool IsTekgram
|
||||
{
|
||||
get { return (bool)GetValue(IsTekgramProperty); }
|
||||
set { SetValue(IsTekgramProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(EngramClassName);
|
||||
|
||||
[DataMember]
|
||||
public int EngramLevelRequirement
|
||||
{
|
||||
get { return (int)GetValue(EngramLevelRequirementProperty); }
|
||||
set { SetValue(EngramLevelRequirementProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public int EngramPointsCost
|
||||
{
|
||||
get { return (int)GetValue(EngramPointsCostProperty); }
|
||||
set { SetValue(EngramPointsCostProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public bool EngramHidden
|
||||
{
|
||||
get { return (bool)GetValue(EngramHiddenProperty); }
|
||||
set { SetValue(EngramHiddenProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public bool RemoveEngramPreReq
|
||||
{
|
||||
get { return (bool)GetValue(RemoveEngramPreReqProperty); }
|
||||
set { SetValue(RemoveEngramPreReqProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public bool EngramAutoUnlock
|
||||
{
|
||||
get { return (bool)GetValue(EngramAutoUnlockProperty); }
|
||||
set { SetValue(EngramAutoUnlockProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public int LevelToAutoUnlock
|
||||
{
|
||||
get { return (int)GetValue(LevelToAutoUnlockProperty); }
|
||||
set { SetValue(LevelToAutoUnlockProperty, value); }
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public bool SaveEngramOverride
|
||||
{
|
||||
get { return (bool)GetValue(SaveEngramOverrideProperty); }
|
||||
set { SetValue(SaveEngramOverrideProperty, value); }
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlyEngramNameForClass(EngramClassName);
|
||||
|
||||
public string DisplayMod => GameData.FriendlyNameForClass($"Mod_{Mod}", true) ?? Mod;
|
||||
|
||||
public bool ShouldSaveEngramEntry(bool onlyAllowSpecifiedEngrams)
|
||||
{
|
||||
if (onlyAllowSpecifiedEngrams)
|
||||
return SaveEngramOverride;
|
||||
|
||||
var engramEntry = GameData.GetEngramForClass(EngramClassName);
|
||||
if (engramEntry == null)
|
||||
engramEntry = new Engram();
|
||||
|
||||
var engramLevelRequirement = IsTekgram ? 0 : EngramLevelRequirement;
|
||||
var engramPointsCost = IsTekgram ? 0 : EngramPointsCost;
|
||||
var engramHidden = EngramHidden;
|
||||
var removeEngramPreReq = RemoveEngramPreReq;
|
||||
|
||||
return (!engramLevelRequirement.Equals(engramEntry.EngramLevelRequirement) ||
|
||||
!engramPointsCost.Equals(engramEntry.EngramPointsCost) ||
|
||||
engramHidden ||
|
||||
removeEngramPreReq);
|
||||
}
|
||||
|
||||
public bool ShouldSaveEngramAutoUnlock(bool onlyAllowSpecifiedEngrams)
|
||||
{
|
||||
if (onlyAllowSpecifiedEngrams && !SaveEngramOverride)
|
||||
return false;
|
||||
|
||||
return EngramAutoUnlock;
|
||||
}
|
||||
|
||||
public EngramEntry GetEngramEntry()
|
||||
{
|
||||
var engramEntry = new EngramEntry() { EngramClassName = this.EngramClassName, EngramLevelRequirement = this.EngramLevelRequirement, EngramPointsCost = this.EngramPointsCost, EngramHidden = this.EngramHidden, RemoveEngramPreReq = this.RemoveEngramPreReq };
|
||||
if (IsTekgram)
|
||||
{
|
||||
// always make sure that the tekgrams have default values.
|
||||
engramEntry.EngramLevelRequirement = 0;
|
||||
engramEntry.EngramPointsCost = 0;
|
||||
}
|
||||
return engramEntry;
|
||||
}
|
||||
|
||||
public EngramAutoUnlock GetEngramAutoUnlock()
|
||||
{
|
||||
var engramEntry = new EngramAutoUnlock() { EngramClassName = this.EngramClassName, LevelToAutoUnlock = this.LevelToAutoUnlock };
|
||||
return engramEntry;
|
||||
}
|
||||
|
||||
#region Sort Properties
|
||||
public string SaveEngramOverrideSort => $"{SaveEngramOverride}|{IsTekgram}|{DisplayName}|{Mod}";
|
||||
public string NameSort => $"{DisplayName}|{Mod}";
|
||||
public string ModSort => $"{Mod}|{IsTekgram}|{DisplayName}";
|
||||
public string IsTekgramSort => $"{IsTekgram}|{DisplayName}|{Mod}";
|
||||
public string EngramLevelRequirementSort => $"{EngramLevelRequirement:0000000000}|{IsTekgram}|{DisplayName}|{Mod}";
|
||||
public string EngramPointsCostSort => $"{EngramPointsCost:0000000000}|{IsTekgram}|{DisplayName}|{Mod}";
|
||||
public string EngramHiddenSort => $"{EngramHidden}|{IsTekgram}|{DisplayName}|{Mod}";
|
||||
public string RemoveEngramPreReqSort => $"{RemoveEngramPreReq}|{IsTekgram}|{DisplayName}|{Mod}";
|
||||
public string EngramAutoUnlockSort => $"{EngramAutoUnlock}|{IsTekgram}|{DisplayName}|{Mod}";
|
||||
public string LevelToAutoUnlockSort => $"{LevelToAutoUnlock:0000000000}|{IsTekgram}|{DisplayName}|{Mod}";
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
48
src/ARKServerManager/Lib/ViewModel/MapSpawner.cs
Normal file
48
src/ARKServerManager/Lib/ViewModel/MapSpawner.cs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class MapSpawner : DependencyObject
|
||||
{
|
||||
public static readonly DependencyProperty ClassNameProperty = DependencyProperty.Register(nameof(ClassName), typeof(string), typeof(MapSpawner), new PropertyMetadata(string.Empty));
|
||||
public static readonly DependencyProperty ModProperty = DependencyProperty.Register(nameof(Mod), typeof(string), typeof(MapSpawner), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty KnownSpawnerProperty = DependencyProperty.Register(nameof(KnownSpawner), typeof(bool), typeof(MapSpawner), new PropertyMetadata(false));
|
||||
|
||||
public string ClassName
|
||||
{
|
||||
get { return (string)GetValue(ClassNameProperty); }
|
||||
set { SetValue(ClassNameProperty, value); }
|
||||
}
|
||||
|
||||
public string Mod
|
||||
{
|
||||
get { return (string)GetValue(ModProperty); }
|
||||
set { SetValue(ModProperty, value); }
|
||||
}
|
||||
|
||||
public bool KnownSpawner
|
||||
{
|
||||
get { return (bool)GetValue(KnownSpawnerProperty); }
|
||||
set { SetValue(KnownSpawnerProperty, value); }
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlyMapSpawnerNameForClass(ClassName);
|
||||
|
||||
public string DisplayMod => GameData.FriendlyNameForClass($"Mod_{Mod}", true) ?? Mod;
|
||||
|
||||
public MapSpawner Duplicate()
|
||||
{
|
||||
var properties = this.GetType().GetProperties();
|
||||
|
||||
var result = new MapSpawner();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.CanWrite)
|
||||
prop.SetValue(result, prop.GetValue(this));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
319
src/ARKServerManager/Lib/ViewModel/NPCSpawnSettings.cs
Normal file
319
src/ARKServerManager/Lib/ViewModel/NPCSpawnSettings.cs
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
using ServerManagerTool.Common.Model;
|
||||
using ServerManagerTool.Enums;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class NPCSpawnSettingsList : SortableObservableCollection<NPCSpawnSettings>
|
||||
{
|
||||
public NPCSpawnContainerList<NPCSpawnContainer> ConfigAddNPCSpawnEntriesContainer { get; }
|
||||
public NPCSpawnContainerList<NPCSpawnContainer> ConfigSubtractNPCSpawnEntriesContainer { get; }
|
||||
public NPCSpawnContainerList<NPCSpawnContainer> ConfigOverrideNPCSpawnEntriesContainer { get; }
|
||||
|
||||
public NPCSpawnSettingsList()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public NPCSpawnSettingsList(NPCSpawnContainerList<NPCSpawnContainer> configAddNPCSpawnEntriesContainer,
|
||||
NPCSpawnContainerList<NPCSpawnContainer> configSubtractNPCSpawnEntriesContainer,
|
||||
NPCSpawnContainerList<NPCSpawnContainer> configOverrideNPCSpawnEntriesContainer)
|
||||
{
|
||||
ConfigAddNPCSpawnEntriesContainer = configAddNPCSpawnEntriesContainer;
|
||||
ConfigSubtractNPCSpawnEntriesContainer = configSubtractNPCSpawnEntriesContainer;
|
||||
ConfigOverrideNPCSpawnEntriesContainer = configOverrideNPCSpawnEntriesContainer;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
this.Clear();
|
||||
}
|
||||
|
||||
public void RenderToView()
|
||||
{
|
||||
Reset();
|
||||
|
||||
foreach (var entry in this.ConfigAddNPCSpawnEntriesContainer)
|
||||
{
|
||||
if (!entry.IsValid)
|
||||
continue;
|
||||
|
||||
var spawnSettings = new NPCSpawnSettings
|
||||
{
|
||||
UniqueId = entry.UniqueId,
|
||||
ContainerType = NPCSpawnContainerType.Add,
|
||||
NPCSpawnEntriesContainerClassString = entry.NPCSpawnEntriesContainerClassString,
|
||||
};
|
||||
foreach (var item in entry.NPCSpawnEntries)
|
||||
{
|
||||
spawnSettings.NPCSpawnEntrySettings.Add(new NPCSpawnEntrySettings
|
||||
{
|
||||
AnEntryName = item.AnEntryName,
|
||||
NPCClassString = item.NPCsToSpawnStrings,
|
||||
EntryWeight = item.EntryWeight,
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var item in entry.NPCSpawnLimits)
|
||||
{
|
||||
var temp = spawnSettings.NPCSpawnEntrySettings.FirstOrDefault(i => i.NPCClassString.Equals(item.NPCClassString));
|
||||
if (temp == null)
|
||||
continue;
|
||||
|
||||
temp.MaxPercentageOfDesiredNumToAllow = item.MaxPercentageOfDesiredNumToAllow;
|
||||
}
|
||||
|
||||
this.Add(spawnSettings);
|
||||
}
|
||||
|
||||
foreach (var entry in this.ConfigSubtractNPCSpawnEntriesContainer)
|
||||
{
|
||||
if (!entry.IsValid)
|
||||
continue;
|
||||
|
||||
var spawnSettings = new NPCSpawnSettings
|
||||
{
|
||||
UniqueId = entry.UniqueId,
|
||||
ContainerType = NPCSpawnContainerType.Subtract,
|
||||
NPCSpawnEntriesContainerClassString = entry.NPCSpawnEntriesContainerClassString,
|
||||
};
|
||||
foreach (var item in entry.NPCSpawnEntries)
|
||||
{
|
||||
spawnSettings.NPCSpawnEntrySettings.Add(new NPCSpawnEntrySettings
|
||||
{
|
||||
AnEntryName = item.AnEntryName,
|
||||
NPCClassString = item.NPCsToSpawnStrings,
|
||||
EntryWeight = item.EntryWeight,
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var item in entry.NPCSpawnLimits)
|
||||
{
|
||||
var temp = spawnSettings.NPCSpawnEntrySettings.FirstOrDefault(i => i.NPCClassString.Equals(item.NPCClassString));
|
||||
if (temp == null)
|
||||
continue;
|
||||
|
||||
temp.MaxPercentageOfDesiredNumToAllow = item.MaxPercentageOfDesiredNumToAllow;
|
||||
}
|
||||
|
||||
this.Add(spawnSettings);
|
||||
}
|
||||
|
||||
foreach (var entry in this.ConfigOverrideNPCSpawnEntriesContainer)
|
||||
{
|
||||
if (!entry.IsValid)
|
||||
continue;
|
||||
|
||||
var spawnSettings = new NPCSpawnSettings
|
||||
{
|
||||
UniqueId = entry.UniqueId,
|
||||
ContainerType = NPCSpawnContainerType.Override,
|
||||
NPCSpawnEntriesContainerClassString = entry.NPCSpawnEntriesContainerClassString,
|
||||
};
|
||||
foreach (var item in entry.NPCSpawnEntries)
|
||||
{
|
||||
spawnSettings.NPCSpawnEntrySettings.Add(new NPCSpawnEntrySettings
|
||||
{
|
||||
AnEntryName = item.AnEntryName,
|
||||
NPCClassString = item.NPCsToSpawnStrings,
|
||||
EntryWeight = item.EntryWeight,
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var item in entry.NPCSpawnLimits)
|
||||
{
|
||||
var temp = spawnSettings.NPCSpawnEntrySettings.FirstOrDefault(i => i.NPCClassString.Equals(item.NPCClassString));
|
||||
if (temp == null)
|
||||
continue;
|
||||
|
||||
temp.MaxPercentageOfDesiredNumToAllow = item.MaxPercentageOfDesiredNumToAllow;
|
||||
}
|
||||
|
||||
this.Add(spawnSettings);
|
||||
}
|
||||
}
|
||||
|
||||
public void RenderToModel()
|
||||
{
|
||||
this.ConfigAddNPCSpawnEntriesContainer.Clear();
|
||||
this.ConfigSubtractNPCSpawnEntriesContainer.Clear();
|
||||
this.ConfigOverrideNPCSpawnEntriesContainer.Clear();
|
||||
|
||||
this.ConfigAddNPCSpawnEntriesContainer.IsEnabled = false;
|
||||
this.ConfigSubtractNPCSpawnEntriesContainer.IsEnabled = false;
|
||||
this.ConfigOverrideNPCSpawnEntriesContainer.IsEnabled = false;
|
||||
|
||||
foreach (var entry in this)
|
||||
{
|
||||
if (!entry.IsValid)
|
||||
continue;
|
||||
|
||||
var spawnContainer = new NPCSpawnContainer
|
||||
{
|
||||
UniqueId = entry.UniqueId,
|
||||
NPCSpawnEntriesContainerClassString = entry.NPCSpawnEntriesContainerClassString,
|
||||
};
|
||||
spawnContainer.NPCSpawnEntries.AddRange(entry.NPCSpawnEntrySettings.Where(s => s.IsValid).Select(s => new NPCSpawnEntry
|
||||
{
|
||||
AnEntryName = string.IsNullOrWhiteSpace(s.AnEntryName) ? string.Empty : s.AnEntryName,
|
||||
EntryWeight = s.EntryWeight,
|
||||
NPCsToSpawnStrings = s.NPCClassString
|
||||
}));
|
||||
spawnContainer.NPCSpawnLimits.AddRange(entry.NPCSpawnEntrySettings.Where(s => s.IsValid).Select(s => new NPCSpawnLimit
|
||||
{
|
||||
NPCClassString = s.NPCClassString,
|
||||
MaxPercentageOfDesiredNumToAllow = s.MaxPercentageOfDesiredNumToAllow
|
||||
}));
|
||||
|
||||
switch (entry.ContainerType)
|
||||
{
|
||||
case NPCSpawnContainerType.Add:
|
||||
this.ConfigAddNPCSpawnEntriesContainer.Add(spawnContainer);
|
||||
this.ConfigAddNPCSpawnEntriesContainer.IsEnabled = true;
|
||||
break;
|
||||
|
||||
case NPCSpawnContainerType.Subtract:
|
||||
this.ConfigSubtractNPCSpawnEntriesContainer.Add(spawnContainer);
|
||||
this.ConfigSubtractNPCSpawnEntriesContainer.IsEnabled = true;
|
||||
break;
|
||||
|
||||
case NPCSpawnContainerType.Override:
|
||||
this.ConfigOverrideNPCSpawnEntriesContainer.Add(spawnContainer);
|
||||
this.ConfigOverrideNPCSpawnEntriesContainer.IsEnabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateForLocalization()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class NPCSpawnSettings : DependencyObject, IEnumerable<NPCSpawnEntrySettings>
|
||||
{
|
||||
public NPCSpawnSettings()
|
||||
{
|
||||
NPCSpawnEntrySettings = new ObservableCollection<NPCSpawnEntrySettings>();
|
||||
}
|
||||
|
||||
public Guid UniqueId = Guid.NewGuid();
|
||||
|
||||
public static readonly DependencyProperty ContainerTypeProperty = DependencyProperty.Register(nameof(ContainerType), typeof(NPCSpawnContainerType), typeof(NPCSpawnSettings), new PropertyMetadata(NPCSpawnContainerType.Override));
|
||||
public NPCSpawnContainerType ContainerType
|
||||
{
|
||||
get { return (NPCSpawnContainerType)GetValue(ContainerTypeProperty); }
|
||||
set
|
||||
{
|
||||
SetValue(ContainerTypeProperty, value);
|
||||
SetShowColumns();
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NPCSpawnEntriesContainerClassStringProperty = DependencyProperty.Register(nameof(NPCSpawnEntriesContainerClassString), typeof(string), typeof(NPCSpawnSettings), new PropertyMetadata(string.Empty));
|
||||
public string NPCSpawnEntriesContainerClassString
|
||||
{
|
||||
get { return (string)GetValue(NPCSpawnEntriesContainerClassStringProperty); }
|
||||
set { SetValue(NPCSpawnEntriesContainerClassStringProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NPCSpawnEntrySettingsProperty = DependencyProperty.Register(nameof(NPCSpawnEntrySettings), typeof(ObservableCollection<NPCSpawnEntrySettings>), typeof(NPCSpawnSettings), new PropertyMetadata(null));
|
||||
public ObservableCollection<NPCSpawnEntrySettings> NPCSpawnEntrySettings
|
||||
{
|
||||
get { return (ObservableCollection<NPCSpawnEntrySettings>)GetValue(NPCSpawnEntrySettingsProperty); }
|
||||
set { SetValue(NPCSpawnEntrySettingsProperty, value); }
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlyMapSpawnerNameForClass(NPCSpawnEntriesContainerClassString);
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(NPCSpawnEntriesContainerClassString);
|
||||
|
||||
public static readonly DependencyProperty ShowEntryNameColumnProperty = DependencyProperty.Register(nameof(ShowEntryNameColumn), typeof(bool), typeof(NPCSpawnSettings), new PropertyMetadata(true));
|
||||
public bool ShowEntryNameColumn
|
||||
{
|
||||
get { return (bool)GetValue(ShowEntryNameColumnProperty); }
|
||||
set { SetValue(ShowEntryNameColumnProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShowClassStringColumnProperty = DependencyProperty.Register(nameof(ShowClassStringColumn), typeof(bool), typeof(NPCSpawnSettings), new PropertyMetadata(true));
|
||||
public bool ShowClassStringColumn
|
||||
{
|
||||
get { return (bool)GetValue(ShowClassStringColumnProperty); }
|
||||
set { SetValue(ShowClassStringColumnProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShowEntryWeightColumnProperty = DependencyProperty.Register(nameof(ShowEntryWeightColumn), typeof(bool), typeof(NPCSpawnSettings), new PropertyMetadata(true));
|
||||
public bool ShowEntryWeightColumn
|
||||
{
|
||||
get { return (bool)GetValue(ShowEntryWeightColumnProperty); }
|
||||
set { SetValue(ShowEntryWeightColumnProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShowMaxPercentageColumnProperty = DependencyProperty.Register(nameof(ShowMaxPercentageColumn), typeof(bool), typeof(NPCSpawnSettings), new PropertyMetadata(true));
|
||||
public bool ShowMaxPercentageColumn
|
||||
{
|
||||
get { return (bool)GetValue(ShowMaxPercentageColumnProperty); }
|
||||
set { SetValue(ShowMaxPercentageColumnProperty, value); }
|
||||
}
|
||||
|
||||
private void SetShowColumns()
|
||||
{
|
||||
ShowEntryNameColumn = ContainerType != NPCSpawnContainerType.Subtract;
|
||||
ShowClassStringColumn = true;
|
||||
ShowEntryWeightColumn = ContainerType != NPCSpawnContainerType.Subtract;
|
||||
ShowMaxPercentageColumn = ContainerType != NPCSpawnContainerType.Subtract;
|
||||
}
|
||||
|
||||
public IEnumerator<NPCSpawnEntrySettings> GetEnumerator()
|
||||
{
|
||||
return NPCSpawnEntrySettings.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return NPCSpawnEntrySettings.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
public class NPCSpawnEntrySettings : DependencyObject
|
||||
{
|
||||
public static readonly DependencyProperty AnEntryNameProperty = DependencyProperty.Register(nameof(AnEntryName), typeof(string), typeof(NPCSpawnEntrySettings), new PropertyMetadata(string.Empty));
|
||||
public string AnEntryName
|
||||
{
|
||||
get { return (string)GetValue(AnEntryNameProperty); }
|
||||
set { SetValue(AnEntryNameProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty NPCClassStringProperty = DependencyProperty.Register(nameof(NPCClassString), typeof(string), typeof(NPCSpawnEntrySettings), new PropertyMetadata(string.Empty));
|
||||
public string NPCClassString
|
||||
{
|
||||
get { return (string)GetValue(NPCClassStringProperty); }
|
||||
set { SetValue(NPCClassStringProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty EntryWeightProperty = DependencyProperty.Register(nameof(EntryWeight), typeof(float), typeof(NPCSpawnEntrySettings), new PropertyMetadata(1.0f));
|
||||
public float EntryWeight
|
||||
{
|
||||
get { return (float)GetValue(EntryWeightProperty); }
|
||||
set { SetValue(EntryWeightProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MaxPercentageOfDesiredNumToAllowProperty = DependencyProperty.Register(nameof(MaxPercentageOfDesiredNumToAllow), typeof(float), typeof(NPCSpawnEntrySettings), new PropertyMetadata(1.0f));
|
||||
public float MaxPercentageOfDesiredNumToAllow
|
||||
{
|
||||
get { return (float)GetValue(MaxPercentageOfDesiredNumToAllowProperty); }
|
||||
set { SetValue(MaxPercentageOfDesiredNumToAllowProperty, value); }
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlyCreatureNameForClass(NPCClassString);
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(NPCClassString);
|
||||
}
|
||||
}
|
||||
160
src/ARKServerManager/Lib/ViewModel/PlayerInfo.cs
Normal file
160
src/ARKServerManager/Lib/ViewModel/PlayerInfo.cs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
using ArkData;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel.RCON
|
||||
{
|
||||
public class PlayerInfo : INotifyPropertyChanged
|
||||
{
|
||||
public PlayerInfo()
|
||||
{
|
||||
PlayerId = string.Empty;
|
||||
PlayerName = string.Empty;
|
||||
CharacterName = string.Empty;
|
||||
IsOnline = false;
|
||||
IsAdmin = false;
|
||||
IsWhitelisted = false;
|
||||
TribeName = string.Empty;
|
||||
LastUpdated = DateTime.MinValue;
|
||||
IsValid = true;
|
||||
PlayerData = null;
|
||||
}
|
||||
|
||||
public string PlayerId
|
||||
{
|
||||
get { return Get<string>(); }
|
||||
set { Set(value); }
|
||||
}
|
||||
public string PlayerName
|
||||
{
|
||||
get { return Get<string>(); }
|
||||
set
|
||||
{
|
||||
Set(value);
|
||||
|
||||
PlayerNameFilterString = value?.ToLower();
|
||||
}
|
||||
}
|
||||
public string PlayerNameFilterString
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public long CharacterId
|
||||
{
|
||||
get { return Get<long>(); }
|
||||
set { Set(value); }
|
||||
}
|
||||
public string CharacterName
|
||||
{
|
||||
get { return Get<string>(); }
|
||||
set
|
||||
{
|
||||
Set(value);
|
||||
|
||||
CharacterNameFilterString = value?.ToLower();
|
||||
}
|
||||
}
|
||||
public string CharacterNameFilterString
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public bool IsOnline
|
||||
{
|
||||
get { return Get<bool>(); }
|
||||
set { Set(value); }
|
||||
}
|
||||
public bool IsAdmin
|
||||
{
|
||||
get { return Get<bool>(); }
|
||||
set { Set(value); }
|
||||
}
|
||||
public bool IsWhitelisted
|
||||
{
|
||||
get { return Get<bool>(); }
|
||||
set { Set(value); }
|
||||
}
|
||||
public string TribeName
|
||||
{
|
||||
get { return Get<string>(); }
|
||||
set
|
||||
{
|
||||
Set(value);
|
||||
|
||||
TribeNameFilterString = value?.ToLower();
|
||||
}
|
||||
}
|
||||
public string TribeNameFilterString
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public DateTime LastUpdated
|
||||
{
|
||||
get { return Get<DateTime>(); }
|
||||
set { Set(value); }
|
||||
}
|
||||
public bool IsValid
|
||||
{
|
||||
get { return Get<bool>(); }
|
||||
set { Set(value); }
|
||||
}
|
||||
public PlayerData PlayerData
|
||||
{
|
||||
get { return Get<PlayerData>(); }
|
||||
set { Set(value); }
|
||||
}
|
||||
|
||||
public void UpdateData(PlayerData playerData)
|
||||
{
|
||||
this.PlayerData = playerData;
|
||||
this.PlayerId = playerData?.PlayerId;
|
||||
this.CharacterId = playerData?.CharacterId ?? 0L;
|
||||
this.CharacterName = playerData?.CharacterName;
|
||||
this.TribeName = playerData?.Tribe?.Name;
|
||||
this.LastUpdated = playerData?.FileUpdated ?? DateTime.MinValue;
|
||||
}
|
||||
|
||||
public void UpdatePlatformData(PlayerData playerData)
|
||||
{
|
||||
if (playerData == null)
|
||||
return;
|
||||
|
||||
playerData.PlayerName = PlayerData?.PlayerName;
|
||||
playerData.LastPlatformUpdateUtc = PlayerData?.LastPlatformUpdateUtc ?? DateTime.MinValue;
|
||||
}
|
||||
|
||||
#region INotifyPropertyChanged
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private Dictionary<string, object> _properties = new Dictionary<string, object>();
|
||||
|
||||
protected T Get<T>([CallerMemberName] string name = null)
|
||||
{
|
||||
object value = null;
|
||||
if (_properties?.TryGetValue(name, out value) ?? false)
|
||||
return value == null ? default : (T)value;
|
||||
return default;
|
||||
}
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
protected void Set<T>(T value, [CallerMemberName] string name = null)
|
||||
{
|
||||
if (Equals(value, Get<T>(name)))
|
||||
return;
|
||||
if (_properties == null)
|
||||
_properties = new Dictionary<string, object>();
|
||||
_properties[name] = value;
|
||||
OnPropertyChanged(name);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
56
src/ARKServerManager/Lib/ViewModel/PrimalItem.cs
Normal file
56
src/ARKServerManager/Lib/ViewModel/PrimalItem.cs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
using ServerManagerTool.Enums;
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class PrimalItem : DependencyObject
|
||||
{
|
||||
public static readonly DependencyProperty ClassNameProperty = DependencyProperty.Register(nameof(ClassName), typeof(string), typeof(PrimalItem), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty ModProperty = DependencyProperty.Register(nameof(Mod), typeof(string), typeof(PrimalItem), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty KnownItemProperty = DependencyProperty.Register(nameof(KnownItem), typeof(bool), typeof(PrimalItem), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty CategoryProperty = DependencyProperty.Register(nameof(Category), typeof(string), typeof(PrimalItem), new PropertyMetadata(String.Empty));
|
||||
|
||||
public string ClassName
|
||||
{
|
||||
get { return (string)GetValue(ClassNameProperty); }
|
||||
set { SetValue(ClassNameProperty, value); }
|
||||
}
|
||||
|
||||
public string Mod
|
||||
{
|
||||
get { return (string)GetValue(ModProperty); }
|
||||
set { SetValue(ModProperty, value); }
|
||||
}
|
||||
|
||||
public bool KnownItem
|
||||
{
|
||||
get { return (bool)GetValue(KnownItemProperty); }
|
||||
set { SetValue(KnownItemProperty, value); }
|
||||
}
|
||||
|
||||
public string Category
|
||||
{
|
||||
get { return (string)GetValue(CategoryProperty); }
|
||||
set { SetValue(CategoryProperty, value); }
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlyItemNameForClass(ClassName);
|
||||
|
||||
public string DisplayMod => GameData.FriendlyNameForClass($"Mod_{Mod}", true) ?? Mod;
|
||||
|
||||
public PrimalItem Duplicate()
|
||||
{
|
||||
var properties = this.GetType().GetProperties();
|
||||
|
||||
var result = new PrimalItem();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.CanWrite)
|
||||
prop.SetValue(result, prop.GetValue(this));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/ARKServerManager/Lib/ViewModel/SupplyCrate.cs
Normal file
48
src/ARKServerManager/Lib/ViewModel/SupplyCrate.cs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class SupplyCrate : DependencyObject
|
||||
{
|
||||
public static readonly DependencyProperty ClassNameProperty = DependencyProperty.Register(nameof(ClassName), typeof(string), typeof(SupplyCrate), new PropertyMetadata(string.Empty));
|
||||
public static readonly DependencyProperty ModProperty = DependencyProperty.Register(nameof(Mod), typeof(string), typeof(SupplyCrate), new PropertyMetadata(String.Empty));
|
||||
public static readonly DependencyProperty KnownSupplyCrateProperty = DependencyProperty.Register(nameof(KnownSupplyCrate), typeof(bool), typeof(SupplyCrate), new PropertyMetadata(false));
|
||||
|
||||
public string ClassName
|
||||
{
|
||||
get { return (string)GetValue(ClassNameProperty); }
|
||||
set { SetValue(ClassNameProperty, value); }
|
||||
}
|
||||
|
||||
public string Mod
|
||||
{
|
||||
get { return (string)GetValue(ModProperty); }
|
||||
set { SetValue(ModProperty, value); }
|
||||
}
|
||||
|
||||
public bool KnownSupplyCrate
|
||||
{
|
||||
get { return (bool)GetValue(KnownSupplyCrateProperty); }
|
||||
set { SetValue(KnownSupplyCrateProperty, value); }
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlySupplyCrateNameForClass(ClassName);
|
||||
|
||||
public string DisplayMod => GameData.FriendlyNameForClass($"Mod_{Mod}", true) ?? Mod;
|
||||
|
||||
public SupplyCrate Duplicate()
|
||||
{
|
||||
var properties = this.GetType().GetProperties();
|
||||
|
||||
var result = new SupplyCrate();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.CanWrite)
|
||||
prop.SetValue(result, prop.GetValue(this));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/ARKServerManager/Lib/ViewModel/SupplyCrateSettings.cs
Normal file
25
src/ARKServerManager/Lib/ViewModel/SupplyCrateSettings.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
using System.Windows;
|
||||
|
||||
namespace ServerManagerTool.Lib.ViewModel
|
||||
{
|
||||
public class SupplyCrateItemEntrySettings : DependencyObject
|
||||
{
|
||||
public static readonly DependencyProperty ItemClassStringProperty = DependencyProperty.Register(nameof(ItemClassString), typeof(string), typeof(SupplyCrateItemEntrySettings), new PropertyMetadata(string.Empty));
|
||||
public string ItemClassString
|
||||
{
|
||||
get { return (string)GetValue(ItemClassStringProperty); }
|
||||
set { SetValue(ItemClassStringProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemWeightProperty = DependencyProperty.Register(nameof(ItemWeight), typeof(float), typeof(SupplyCrateItemEntrySettings), new PropertyMetadata(1.0f));
|
||||
public float ItemWeight
|
||||
{
|
||||
get { return (float)GetValue(ItemWeightProperty); }
|
||||
set { SetValue(ItemWeightProperty, value); }
|
||||
}
|
||||
|
||||
public string DisplayName => GameData.FriendlySupplyCrateNameForClass(ItemClassString);
|
||||
|
||||
public bool IsValid => !string.IsNullOrWhiteSpace(ItemClassString);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue