source code checkin

This commit is contained in:
Brett Hewitson 2021-01-07 16:23:23 +10:00
parent 5f8fb2c825
commit 7e57b72e35
675 changed files with 168433 additions and 0 deletions

View file

@ -0,0 +1,331 @@
using ServerManagerTool.Common.Attibutes;
using ServerManagerTool.Common.Interfaces;
using ServerManagerTool.Common.Utils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
namespace ServerManagerTool.Common.Model
{
/// <summary>
/// An INI style value of the form AggregateName=(Key1=val1, Key2=val2...)
/// </summary>
public abstract class AggregateIniValue : DependencyObject
{
protected const char DELIMITER = ',';
protected readonly List<PropertyInfo> Properties = new List<PropertyInfo>();
public T Duplicate<T>() where T : AggregateIniValue, new()
{
GetPropertyInfos(true);
var result = new T();
foreach (var prop in this.Properties.Where(prop => prop.CanWrite))
{
prop.SetValue(result, prop.GetValue(this));
}
return result;
}
public static T FromINIValue<T>(string value) where T : AggregateIniValue, new()
{
var result = new T();
result.InitializeFromINIValue(value);
return result;
}
protected void GetPropertyInfos(bool allProperties = false)
{
if (this.Properties.Count != 0)
return;
if (allProperties)
this.Properties.AddRange(this.GetType().GetProperties());
else
this.Properties.AddRange(this.GetType().GetProperties().Where(p => p.GetCustomAttribute(typeof(AggregateIniValueEntryAttribute)) != null));
}
public abstract string GetSortKey();
public virtual void InitializeFromINIValue(string value)
{
if (string.IsNullOrWhiteSpace(value))
return;
GetPropertyInfos();
if (this.Properties.Count == 0)
return;
var kvPair = value.Split(new[] { '=' }, 2);
value = kvPair[1].Trim('(', ')', ' ');
var pairs = value.Split(DELIMITER);
foreach (var pair in pairs)
{
kvPair = pair.Split('=');
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 abstract bool IsEquivalent(AggregateIniValue other);
public virtual bool ShouldSave() { return true; }
public static object SortKeySelector(AggregateIniValue arg)
{
return arg.GetSortKey();
}
public virtual 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)
{
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);
if ((attr?.ExcludeIfEmpty ?? false) && string.IsNullOrWhiteSpace(propValue))
{
Debug.WriteLine($"{propName} skipped, ExcludeIfEmpty = true and value is empty");
}
else
{
result.Append($"{propName}={propValue}");
delimiter = DELIMITER.ToString();
}
}
result.Append(")");
return result.ToString();
}
public override string ToString()
{
return ToINIValue();
}
protected virtual void FromComplexINIValue(string value)
{
if (string.IsNullOrWhiteSpace(value))
return;
GetPropertyInfos();
if (this.Properties.Count == 0)
return;
var kvValue = value.Trim(' ');
var propertyValues = SplitCollectionValues(kvValue, DELIMITER);
foreach (var property in this.Properties)
{
var attr = property.GetCustomAttributes(typeof(AggregateIniValueEntryAttribute), false).OfType<AggregateIniValueEntryAttribute>().FirstOrDefault();
var propertyName = string.IsNullOrWhiteSpace(attr?.Key) ? property.Name : attr.Key;
var propertyValue = propertyValues.FirstOrDefault(p => p.StartsWith($"{propertyName}="));
if (propertyValue == null)
continue;
var kvPropertyPair = propertyValue.Split(new[] { '=' }, 2);
var kvPropertyValue = kvPropertyPair[1].Trim(DELIMITER, ' ');
if (attr?.ValueWithinBrackets ?? false)
{
if (kvPropertyValue.StartsWith("("))
kvPropertyValue = kvPropertyValue.Substring(1);
if (kvPropertyValue.EndsWith(")"))
kvPropertyValue = kvPropertyValue.Substring(0, kvPropertyValue.Length - 1);
}
var collection = property.GetValue(this) as IIniValuesCollection;
if (collection != null)
{
var values = SplitCollectionValues(kvPropertyValue, DELIMITER);
values = values.Where(v => !string.IsNullOrWhiteSpace(v)).ToArray();
if (attr?.ListValueWithinBrackets ?? false)
{
values = values.Select(v => v.Substring(1)).ToArray();
values = values.Select(v => v.Substring(0, v.Length - 1)).ToArray();
}
collection.FromIniValues(values);
}
else
StringUtils.SetPropertyValue(kvPropertyValue, this, property);
}
}
protected virtual string ToComplexINIValue(bool resultWithinBrackets)
{
GetPropertyInfos();
if (this.Properties.Count == 0)
return string.Empty;
var result = new StringBuilder();
if (resultWithinBrackets)
result.Append("(");
var delimiter = "";
foreach (var prop in this.Properties)
{
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 collection = val as IIniValuesCollection;
if (collection != null)
{
result.Append(delimiter);
result.Append($"{propName}=");
if (attr?.ValueWithinBrackets ?? false)
result.Append("(");
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();
}
if (attr?.ValueWithinBrackets ?? false)
result.Append(")");
delimiter = DELIMITER.ToString();
}
else
{
if ((attr?.ExcludeIfEmpty ?? false) && val is string && string.IsNullOrWhiteSpace(val.ToString()))
{
Debug.WriteLine($"{propName} skipped, ExcludeIfEmpty = true and value is null or empty");
}
else if ((attr?.ExcludeIfFalse ?? false) && val is bool && !((bool)val))
{
Debug.WriteLine($"{propName} skipped, ExcludeIfFalse = true and value is false");
}
else
{
var propValue = StringUtils.GetPropertyValue(val, prop);
result.Append(delimiter);
result.Append($"{propName}=");
if (attr?.ValueWithinBrackets ?? false)
result.Append("(");
result.Append(propValue);
if (attr?.ValueWithinBrackets ?? false)
result.Append(")");
delimiter = DELIMITER.ToString();
}
}
}
if (resultWithinBrackets)
result.Append(")");
return result.ToString();
}
protected string[] SplitCollectionValues(string valueString, char delimiter)
{
if (string.IsNullOrWhiteSpace(valueString))
return new string[0];
// string any leading or trailing spaces
var tempString = valueString.Trim();
// check if any delimiters
var total1 = tempString.Count(c => c.Equals(delimiter));
if (total1 == 0)
return new[] {tempString};
var result = new List<string>();
var bracketCount = 0;
var startIndex = 0;
for (var index = 0; index < tempString.Length; index++)
{
var charValue = tempString[index];
if (charValue == '(')
{
bracketCount++;
continue;
}
if (charValue == ')')
{
bracketCount--;
continue;
}
if (charValue != delimiter || bracketCount != 0)
continue;
result.Add(tempString.Substring(startIndex, index - startIndex));
startIndex = index + 1;
}
result.Add(tempString.Substring(startIndex));
return result.ToArray();
}
public void Update(AggregateIniValue other)
{
if (other == null)
return;
GetPropertyInfos();
other.GetPropertyInfos();
foreach (var propInfo in this.Properties)
{
var otherPropInfo = other.Properties.FirstOrDefault(p => p.Name.Equals(propInfo.Name, StringComparison.OrdinalIgnoreCase));
if (otherPropInfo == null)
continue;
var val = otherPropInfo.GetValue(other);
var propValue = StringUtils.GetPropertyValue(val, propInfo);
StringUtils.SetPropertyValue(propValue, this, propInfo);
}
}
}
}

View file

@ -0,0 +1,86 @@
using ServerManagerTool.Common.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ServerManagerTool.Common.Model
{
public class AggregateIniValueList<T> : SortableObservableCollection<T>, IIniValuesCollection
where T : AggregateIniValue, new()
{
protected readonly Func<IEnumerable<T>> _resetFunc;
private bool _isEnabled;
public AggregateIniValueList(string aggregateValueName, Func<IEnumerable<T>> resetFunc)
{
this.IniCollectionKey = aggregateValueName;
this._resetFunc = resetFunc;
}
public string IniCollectionKey { get; }
public bool IsEnabled
{
get { return this._isEnabled; }
set
{
this._isEnabled = value;
OnPropertyChanged(new System.ComponentModel.PropertyChangedEventArgs(nameof(IsEnabled)));
}
}
public bool IsArray => false;
public void AddRange(IEnumerable<T> values)
{
if (values == null)
return;
foreach (var value in values)
{
var item = this.FirstOrDefault(i => i.IsEquivalent(value));
if (item == null)
base.Add(value);
else
item.Update(value);
}
this.Sort(AggregateIniValue.SortKeySelector);
}
public void Reset()
{
this.Clear();
if (this._resetFunc != null)
this.AddRange(this._resetFunc());
this.Sort(AggregateIniValue.SortKeySelector);
}
public virtual void FromIniValues(IEnumerable<string> iniValues)
{
var items = iniValues?.Select(AggregateIniValue.FromINIValue<T>).ToArray();
Clear();
AddRange(items);
IsEnabled = (Count != 0);
// Add any default values which were missing
if (_resetFunc != null)
{
var defaultItemsToAdd = _resetFunc().Where(r => !this.Any(v => v.IsEquivalent(r))).ToArray();
AddRange(defaultItemsToAdd);
}
Sort(AggregateIniValue.SortKeySelector);
}
public virtual 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()}");
}
}
}

View file

@ -0,0 +1,56 @@
using System.Windows;
namespace ServerManagerTool.Common.Model
{
public class ComboBoxItem : DependencyObject
{
public static readonly DependencyProperty ValueMemberProperty = DependencyProperty.Register(nameof(ValueMember), typeof(string), typeof(ComboBoxItem), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty DisplayMemberProperty = DependencyProperty.Register(nameof(DisplayMember), typeof(string), typeof(ComboBoxItem), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty GroupMemberProperty = DependencyProperty.Register(nameof(GroupMember), typeof(string), typeof(ComboBoxItem), new PropertyMetadata(string.Empty));
public ComboBoxItem()
{
}
public ComboBoxItem(string valueMember, string displayMember)
{
ValueMember = valueMember;
DisplayMember = displayMember;
}
public ComboBoxItem(string valueMember, string displayMember, string groupMember)
{
ValueMember = valueMember;
DisplayMember = displayMember;
GroupMember = groupMember;
}
public string ValueMember
{
get { return (string)GetValue(ValueMemberProperty); }
set { SetValue(ValueMemberProperty, value); }
}
public string DisplayMember
{
get { return (string)GetValue(DisplayMemberProperty); }
set { SetValue(DisplayMemberProperty, value); }
}
public string GroupMember
{
get { return (string)GetValue(GroupMemberProperty); }
set { SetValue(GroupMemberProperty, value); }
}
public ComboBoxItem Duplicate()
{
return new ComboBoxItem
{
DisplayMember = this.DisplayMember,
ValueMember = this.ValueMember,
GroupMember = this.GroupMember,
};
}
}
}

View file

@ -0,0 +1,11 @@
using System.Collections.Specialized;
namespace ServerManagerTool.Common.Model
{
public class ComboBoxItemList : SortableObservableCollection<ComboBoxItem>
{
public ComboBoxItemList()
{
}
}
}

View file

@ -0,0 +1,55 @@
using System.Windows;
namespace ServerManagerTool.Common.Model
{
public class CustomItem : DependencyObject
{
public static readonly DependencyProperty ItemKeyProperty = DependencyProperty.Register(nameof(ItemKey), typeof(string), typeof(CustomItem), new PropertyMetadata(string.Empty));
public string ItemKey
{
get { return (string)GetValue(ItemKeyProperty); }
set { SetValue(ItemKeyProperty, value); }
}
public static readonly DependencyProperty ItemValueProperty = DependencyProperty.Register(nameof(ItemValue), typeof(string), typeof(CustomItem), new PropertyMetadata(string.Empty));
public string ItemValue
{
get { return (string)GetValue(ItemValueProperty); }
set { SetValue(ItemValueProperty, value); }
}
public static CustomItem FromINIValue(string value)
{
var result = new CustomItem();
result.InitializeFromINIValue(value);
return result;
}
protected virtual void InitializeFromINIValue(string value)
{
var kvPair = value.Split(new[] { '=' }, 2);
if (kvPair.Length > 1)
{
ItemKey = kvPair[0];
ItemValue = kvPair[1];
}
else if (kvPair.Length > 0)
{
ItemKey = kvPair[0];
ItemValue = string.Empty;
}
}
public virtual string ToINIValue()
{
return this.ToString();
}
public override string ToString()
{
if (string.IsNullOrWhiteSpace(ItemKey))
return null;
return $"{ItemKey}={ItemValue}";
}
}
}

View file

@ -0,0 +1,112 @@
using ServerManagerTool.Common.Interfaces;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
namespace ServerManagerTool.Common.Model
{
public class CustomSection : DependencyObject, IIniValuesCollection, IEnumerable<CustomItem>
{
public CustomSection()
{
SectionItems = new ObservableCollection<CustomItem>();
Update();
}
public static readonly DependencyProperty IsDeletedProperty = DependencyProperty.Register(nameof(IsDeleted), typeof(bool), typeof(CustomSection), new PropertyMetadata(false));
public bool IsDeleted
{
get { return (bool)GetValue(IsDeletedProperty); }
set { SetValue(IsDeletedProperty, value); }
}
public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.Register(nameof(IsEnabled), typeof(bool), typeof(CustomSection), new PropertyMetadata(false));
public bool IsEnabled
{
get { return (bool)GetValue(IsEnabledProperty); }
set { SetValue(IsEnabledProperty, value); }
}
public static readonly DependencyProperty SectionItemsProperty = DependencyProperty.Register(nameof(SectionItems), typeof(ObservableCollection<CustomItem>), typeof(CustomSection), new PropertyMetadata(null));
public ObservableCollection<CustomItem> SectionItems
{
get { return (ObservableCollection<CustomItem>)GetValue(SectionItemsProperty); }
set { SetValue(SectionItemsProperty, value); }
}
public static readonly DependencyProperty SectionNameProperty = DependencyProperty.Register(nameof(SectionName), typeof(string), typeof(CustomSection), new PropertyMetadata(string.Empty));
public string SectionName
{
get { return (string)GetValue(SectionNameProperty); }
set { SetValue(SectionNameProperty, value); }
}
public bool IsArray => false;
public string IniCollectionKey => SectionName;
public void Add(string itemKey, string itemValue)
{
var item = new CustomItem();
item.ItemKey = itemKey;
item.ItemValue = itemValue;
SectionItems.Add(item);
Update();
}
public void AddRange(IEnumerable<CustomItem> values)
{
foreach (var value in values)
{
SectionItems.Add(value);
}
Update();
}
public void Clear()
{
SectionItems.Clear();
}
public void FromIniValues(IEnumerable<string> values)
{
AddRange(values.Select(v => CustomItem.FromINIValue(v)));
}
public IEnumerator<CustomItem> GetEnumerator()
{
return SectionItems.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return SectionItems.GetEnumerator();
}
public bool Remove(CustomItem item)
{
return SectionItems.Remove(item);
}
public IEnumerable<string> ToIniValues()
{
var values = new List<string>();
values.AddRange(SectionItems.Select(i => i.ToINIValue()).Where(i => i != null));
return values;
}
public override string ToString()
{
return $"{SectionName}; Count={SectionItems.Count}";
}
public void Update()
{
this.IsEnabled = (!IsDeleted && SectionItems.Count != 0);
}
}
}

View file

@ -0,0 +1,69 @@
using ServerManagerTool.Common.Interfaces;
using System;
using System.Linq;
namespace ServerManagerTool.Common.Model
{
public class CustomList : SortableObservableCollection<CustomSection>, IIniSectionCollection
{
public IIniValuesCollection[] Sections
{
get
{
return this.ToArray();
}
}
public void Add(string sectionName, string[] values)
{
Add(sectionName, values, true);
}
public void Add(string sectionName, string[] values, bool clearExisting)
{
var section = this.Items.FirstOrDefault(s => s.SectionName.Equals(sectionName, StringComparison.OrdinalIgnoreCase) && !s.IsDeleted);
if (section == null)
{
section = new CustomSection();
section.SectionName = sectionName;
this.Add(section);
}
if (clearExisting)
section.Clear();
section.FromIniValues(values);
}
public new void Clear()
{
foreach (var section in this)
{
section.IsDeleted = true;
}
Update();
}
public new void Remove(CustomSection item)
{
if (item != null)
item.IsDeleted = true;
Update();
}
public override string ToString()
{
return $"Count={Count}";
}
public void Update()
{
foreach (var section in this)
{
section.Update();
}
this.Sort(s => s.SectionName);
}
}
}

View file

@ -0,0 +1,47 @@
using ServerManagerTool.Common.Interfaces;
using ServerManagerTool.Common.Utils;
using System;
using System.Collections.Generic;
using System.Globalization;
namespace ServerManagerTool.Common.Model
{
public class FloatIniValueArray : IniValueList<float>, IIniValuesList
{
public FloatIniValueArray(string iniKeyName, Func<IEnumerable<float>> resetFunc) :
base(iniKeyName, resetFunc, (a, b) => a == b, m => m, ToIniValueInternal, FromIniValueInternal)
{
}
public override bool IsArray => true;
private static string ToIniValueInternal(float val)
{
return val.ToString("0.0#########", CultureInfo.GetCultureInfo(StringUtils.DEFAULT_CULTURE_CODE));
}
private static float FromIniValueInternal(string iniVal)
{
var tempValue = iniVal.Replace("f", "");
return float.Parse(tempValue, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.GetCultureInfo(StringUtils.DEFAULT_CULTURE_CODE));
}
public IEnumerable<string> ToIniValues(object excludeIfValue)
{
var excludeIfFloatValue = excludeIfValue is float ? (float)excludeIfValue : float.NaN;
var values = new List<string>();
for (var i = 0; i < this.Count; i++)
{
if (!EquivalencyFunc(this[i], excludeIfFloatValue))
{
if (string.IsNullOrWhiteSpace(IniCollectionKey))
values.Add(this.ToIniValue(this[i]));
else
values.Add($"{this.IniCollectionKey}[{i}]={this.ToIniValue(this[i])}");
}
}
return values;
}
}
}

View file

@ -0,0 +1,41 @@
using ServerManagerTool.Common.Interfaces;
using ServerManagerTool.Common.Utils;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace ServerManagerTool.Common.Model
{
public class FloatIniValueList : IniValueList<float>, IIniValuesList
{
public FloatIniValueList(string iniKeyName, Func<IEnumerable<float>> resetFunc) :
base(iniKeyName, resetFunc, (a, b) => a == b, m => m, ToIniValueInternal, FromIniValueInternal)
{
}
public override bool IsArray => false;
private static string ToIniValueInternal(float val)
{
return val.ToString("0.0#########", CultureInfo.GetCultureInfo(StringUtils.DEFAULT_CULTURE_CODE));
}
private static float FromIniValueInternal(string iniVal)
{
return float.Parse(iniVal, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.GetCultureInfo(StringUtils.DEFAULT_CULTURE_CODE));
}
public IEnumerable<string> ToIniValues(object excludeIfValue)
{
var excludeIfFloatValue = excludeIfValue is float ? (float)excludeIfValue : float.NaN;
var values = new List<string>();
if (string.IsNullOrWhiteSpace(IniCollectionKey))
values.AddRange(this.Where(v => !EquivalencyFunc(v, excludeIfFloatValue)).Select(d => ToIniValueInternal(d)));
else
values.AddRange(this.Where(v => !EquivalencyFunc(v, excludeIfFloatValue)).Select(d => $"{this.IniCollectionKey}={ToIniValueInternal(d)}"));
return values;
}
}
}

View file

@ -0,0 +1,6 @@
namespace ServerManagerTool.Common.Model
{
public class IniValueArray
{
}
}

View file

@ -0,0 +1,138 @@
using ServerManagerTool.Common.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ServerManagerTool.Common.Model
{
public abstract class IniValueList<T> : SortableObservableCollection<T>, IIniValuesCollection
{
private bool _isEnabled;
protected IniValueList(string aggregateValueName, Func<IEnumerable<T>> resetFunc, Func<T, T, bool> equivalencyFunc, Func<T, object> sortKeySelectorFunc, Func<T, string> toIniValue, Func<string, T> fromIniValue)
{
this.ToIniValue = toIniValue;
this.FromIniValue = fromIniValue;
this.ResetFunc = resetFunc;
this.EquivalencyFunc = equivalencyFunc;
this.SortKeySelectorFunc = sortKeySelectorFunc;
this.IniCollectionKey = aggregateValueName;
this.Reset();
this.IsEnabled = false;
}
public Func<T, string> ToIniValue { get; }
public Func<string, T> FromIniValue { get; }
protected Func<IEnumerable<T>> ResetFunc { get; }
public Func<T, T, bool> EquivalencyFunc { get; private set; }
protected Func<T, object> SortKeySelectorFunc { get; }
public bool IsEnabled
{
get { return this._isEnabled; }
set
{
this._isEnabled = value;
OnPropertyChanged(new System.ComponentModel.PropertyChangedEventArgs(nameof(IsEnabled)));
}
}
public abstract bool IsArray { get; }
public string IniCollectionKey { get; }
public void AddRange(IEnumerable<T> values)
{
foreach (var value in values)
{
base.Add(value);
}
}
public virtual void FromIniValues(IEnumerable<string> values)
{
this.Clear();
if (this.IsArray)
{
var list = new List<T>();
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;
}
int index;
if(!int.TryParse(v.Substring(indexStart + 1, indexEnd - indexStart - 1), out 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);
}
else
{
this.AddRange(values.Select(v => v.Substring(v.IndexOf('=') + 1)).Select(this.FromIniValue));
this.IsEnabled = (this.Count != 0);
// Add any default values which were missing
if (this.ResetFunc != null)
{
var defaultItemsToAdd = this.ResetFunc().Where(r => !this.Any(v => this.EquivalencyFunc(v, r))).ToArray();
this.AddRange(defaultItemsToAdd);
this.Sort(this.SortKeySelectorFunc);
}
}
}
public virtual IEnumerable<string> ToIniValues()
{
var values = new List<string>();
if (this.IsArray)
{
for(var i = 0; i < this.Count; i++)
{
if (string.IsNullOrWhiteSpace(IniCollectionKey))
values.Add(this.ToIniValue(this[i]));
else
values.Add($"{this.IniCollectionKey}[{i}]={this.ToIniValue(this[i])}");
}
}
else
{
if (string.IsNullOrWhiteSpace(IniCollectionKey))
values.AddRange(this.Select(d => this.ToIniValue(d)));
else
values.AddRange(this.Select(d => $"{this.IniCollectionKey}={this.ToIniValue(d)}"));
}
return values;
}
public void Reset()
{
this.Clear();
if (this.ResetFunc != null)
this.AddRange(this.ResetFunc());
}
}
}

View file

@ -0,0 +1,41 @@
using ServerManagerTool.Common.Interfaces;
using ServerManagerTool.Common.Utils;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace ServerManagerTool.Common.Model
{
public class IntegerIniValueList : IniValueList<int>, IIniValuesList
{
public IntegerIniValueList(string iniKeyName, Func<IEnumerable<int>> resetFunc) :
base(iniKeyName, resetFunc, (a, b) => a == b, m => m, ToIniValueInternal, FromIniValueInternal)
{
}
public override bool IsArray => false;
private static string ToIniValueInternal(int val)
{
return val.ToString(CultureInfo.GetCultureInfo(StringUtils.DEFAULT_CULTURE_CODE));
}
private static int FromIniValueInternal(string iniVal)
{
return int.Parse(iniVal, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.GetCultureInfo(StringUtils.DEFAULT_CULTURE_CODE));
}
public IEnumerable<string> ToIniValues(object excludeIfValue)
{
var excludeIfIntegerValue = excludeIfValue is int ? (int)excludeIfValue : int.MinValue;
var values = new List<string>();
if (string.IsNullOrWhiteSpace(IniCollectionKey))
values.AddRange(this.Where(v => !EquivalencyFunc(v, excludeIfIntegerValue)).Select(d => ToIniValueInternal(d)));
else
values.AddRange(this.Where(v => !EquivalencyFunc(v, excludeIfIntegerValue)).Select(d => $"{this.IniCollectionKey}={ToIniValueInternal(d)}"));
return values;
}
}
}

View file

@ -0,0 +1,45 @@
using System.Runtime.Serialization;
using System.Windows;
namespace ServerManagerTool.Common.Model
{
[DataContract]
public class PlayerUserItem : DependencyObject
{
public static readonly DependencyProperty PlayerIdProperty = DependencyProperty.Register(nameof(PlayerId), typeof(string), typeof(PlayerUserItem), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty PlayerNameProperty = DependencyProperty.Register(nameof(PlayerName), typeof(string), typeof(PlayerUserItem), new PropertyMetadata(string.Empty));
[DataMember]
public string PlayerId
{
get { return (string)GetValue(PlayerIdProperty); }
set { SetValue(PlayerIdProperty, value); }
}
[DataMember]
public string PlayerName
{
get { return (string)GetValue(PlayerNameProperty); }
set { SetValue(PlayerNameProperty, value); }
}
public static PlayerUserItem GetItem(SteamUserDetail detail)
{
if (string.IsNullOrWhiteSpace(detail.steamid))
return null;
var result = new PlayerUserItem
{
PlayerId = detail.steamid,
PlayerName = detail.personaname ?? string.Empty,
};
return result;
}
public override string ToString()
{
return $"{PlayerId} - {PlayerName}";
}
}
}

View file

@ -0,0 +1,93 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;
namespace ServerManagerTool.Common.Model
{
[DataContract]
public class PlayerUserList : ObservableCollection<PlayerUserItem>
{
public void AddRange(PlayerUserList list)
{
if (list == null)
return;
foreach (var item in list)
{
if (string.IsNullOrWhiteSpace(item?.PlayerId))
continue;
if (!this.Any(i => i.PlayerId.Equals(item.PlayerId)))
this.Add(item);
}
}
public static PlayerUserList GetList(SteamUserDetailResponse response, string[] ids)
{
var result = new PlayerUserList();
if (ids != null)
{
foreach (var id in ids)
{
result.Add(new PlayerUserItem()
{
PlayerId = id,
PlayerName = "<not available>",
});
}
}
if (response?.players != null)
{
foreach (var detail in response.players)
{
var item = result.FirstOrDefault(i => i.PlayerId == detail.steamid);
if (item == null)
{
var newItem = PlayerUserItem.GetItem(detail);
if (!string.IsNullOrWhiteSpace(newItem?.PlayerId))
result.Add(newItem);
}
else
{
item.PlayerId = detail.steamid;
item.PlayerName = detail.personaname ?? string.Empty;
}
}
}
// remove all NULL records.
for(int index = result.Count - 1; index >= 0; index--)
{
if (result[index] == null)
result.RemoveAt(index);
}
return result;
}
public void Remove(string steamId)
{
var items = this.Where(i => i.PlayerId.Equals(steamId, System.StringComparison.OrdinalIgnoreCase)).ToArray();
foreach (var item in items)
{
this.Remove(item);
}
}
public string[] ToArray()
{
return this.Select(i => i.PlayerId).ToArray();
}
public string ToDelimitedString(string delimiter)
{
return string.Join(delimiter, this.Select(i => i.PlayerId));
}
public override string ToString()
{
return $"{nameof(PlayerUserList)} - {Count}";
}
}
}

View file

@ -0,0 +1,29 @@
using System.Numerics;
using System.Windows;
namespace ServerManagerTool.Common.Model
{
public class ProcessorAffinityItem : DependencyObject
{
public static readonly DependencyProperty SelectedProperty = DependencyProperty.Register(nameof(Selected), typeof(bool), typeof(ProcessorAffinityItem), new PropertyMetadata(false));
public bool Selected
{
get { return (bool)GetValue(SelectedProperty); }
set { SetValue(SelectedProperty, value); }
}
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(nameof(Description), typeof(string), typeof(ProcessorAffinityItem), new PropertyMetadata(string.Empty));
public string Description
{
get { return (string)GetValue(DescriptionProperty); }
set { SetValue(DescriptionProperty, value); }
}
public static readonly DependencyProperty AffinityValueProperty = DependencyProperty.Register(nameof(AffinityValue), typeof(BigInteger), typeof(ProcessorAffinityItem), new PropertyMetadata(BigInteger.Zero));
public BigInteger AffinityValue
{
get { return (BigInteger)GetValue(AffinityValueProperty); }
set { SetValue(AffinityValueProperty, value); }
}
}
}

View file

@ -0,0 +1,67 @@
using ServerManagerTool.Common.Utils;
using System.Linq;
using System.Numerics;
namespace ServerManagerTool.Common.Model
{
public class ProcessorAffinityList : SortableObservableCollection<ProcessorAffinityItem>
{
private bool _allProcessors;
public ProcessorAffinityList(BigInteger affinityValue)
{
AllProcessors = true;
PopulateAffinities(affinityValue);
}
public bool AllProcessors
{
get { return this._allProcessors; }
set
{
this._allProcessors = value;
OnPropertyChanged(new System.ComponentModel.PropertyChangedEventArgs(nameof(AllProcessors)));
}
}
public BigInteger AffinityValue
{
get
{
if (AllProcessors || this.Count(i => i.Selected) == this.Count)
return BigInteger.Zero;
var affinity = BigInteger.Zero;
foreach (var value in this.Where(i => i.Selected).Select(i => i.AffinityValue))
affinity += value;
return affinity;
}
}
private void PopulateAffinities(BigInteger affinityValue)
{
var list = ProcessUtils.GetProcessorAffinityList();
var index = 0;
if (!ProcessUtils.IsProcessorAffinityValid(affinityValue))
affinityValue = BigInteger.Zero;
foreach (var item in list)
{
if (item == 0)
continue;
this.Add(new ProcessorAffinityItem() { Selected = affinityValue == BigInteger.Zero || ((affinityValue & item) == item), AffinityValue = item, Description = $"{index}" });
index++;
}
var affinity = BigInteger.Zero;
if (this.Count(i => i.Selected) != this.Count)
{
foreach (var value in this.Where(i => i.Selected).Select(i => i.AffinityValue))
affinity += value;
}
AllProcessors = affinity == BigInteger.Zero;
}
}
}

View file

@ -0,0 +1,55 @@
using System.Collections.Generic;
namespace ServerManagerTool.Common.Model
{
public class PublishedFileDetail
{
public string publishedfileid { get; set; }
public int result { get; set; }
public string creator { get; set; }
public string creator_app_id { get; set; }
public string consumer_app_id { get; set; }
public string filename { get; set; }
public string file_size { get; set; }
public string file_url { get; set; }
public string hcontent_file { get; set; }
public string preview_url { get; set; }
public string hcontent_preview { get; set; }
public string title { get; set; }
public string description { get; set; }
public int time_created { get; set; }
public int time_updated { get; set; }
public int visibility { get; set; }
public int banned { get; set; }
public string ban_reason { get; set; }
public int subscriptions { get; set; }
public int favorited { get; set; }
public int lifetime_subscriptions { get; set; }
public int lifetime_favorited { get; set; }
public int views { get; set; }
public List<object> tags { get; set; }
}
}

View file

@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace ServerManagerTool.Common.Model
{
public class PublishedFileDetailsResponse
{
public int result { get; set; }
public int resultcount { get; set; }
public List<PublishedFileDetail> publishedfiledetails { get; set; }
}
}

View file

@ -0,0 +1,7 @@
namespace ServerManagerTool.Common.Model
{
public class PublishedFileDetailsResult
{
public PublishedFileDetailsResponse response { get; set; }
}
}

View file

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace ServerManagerTool.Common.Model
{
/// <summary>
/// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed and allows sorting.
/// </summary>
/// <typeparam name="T">The type of elements in the collection.</typeparam>
public class SortableObservableCollection<T> : ObservableCollection<T>
{
public SortableObservableCollection()
{
}
public SortableObservableCollection(List<T> list)
: base(list)
{
}
public SortableObservableCollection(IEnumerable<T> collection)
: base(collection)
{
}
/// <summary>
/// Sorts the items of the collection in ascending order according to a key.
/// </summary>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
/// <param name="keySelector">A function to extract a key from an item.</param>
public void Sort<TKey>(Func<T, TKey> keySelector)
{
InternalSort(Items.OrderBy(keySelector));
}
/// <summary>
/// Sorts the items of the collection in ascending order according to a key.
/// </summary>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
/// <param name="keySelector">A function to extract a key from an item.</param>
/// <param name="comparer">An <see cref="IComparer{T}"/> to compare keys.</param>
public void Sort<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer)
{
InternalSort(Items.OrderBy(keySelector, comparer));
}
/// <summary>
/// Sorts the items of the collection in descending order according to a key.
/// </summary>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
/// <param name="keySelector">A function to extract a key from an item.</param>
public void SortDescending<TKey>(Func<T, TKey> keySelector)
{
InternalSort(Items.OrderByDescending(keySelector));
}
/// <summary>
/// Sorts the items of the collection in descending order according to a key.
/// </summary>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
/// <param name="keySelector">A function to extract a key from an item.</param>
/// <param name="comparer">An <see cref="IComparer{T}"/> to compare keys.</param>
public void SortDescending<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer)
{
InternalSort(Items.OrderByDescending(keySelector, comparer));
}
/// <summary>
/// Moves the items of the collection so that their orders are the same as those of the items provided.
/// </summary>
/// <param name="sortedItems">An <see cref="IEnumerable{T}"/> to provide item orders.</param>
private void InternalSort(IEnumerable<T> sortedItems)
{
var sortedItemsList = sortedItems.ToList();
foreach (var item in sortedItemsList)
{
Move(IndexOf(item), sortedItemsList.IndexOf(item));
}
}
}
}

View file

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace ServerManagerTool.Common.Model
{
public class SteamCmdAppManifest
{
public string appid { get; set; }
public List<SteamCmdManifestUserConfig> UserConfig { get; set; }
}
}

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
namespace ServerManagerTool.Common.Model
{
public class SteamCmdAppWorkshop
{
public string appid { get; set; }
public string SizeOnDisk { get; set; }
public string NeedsUpdate { get; set; }
public string NeedsDownload { get; set; }
public string TimeLastUpdated { get; set; }
public string TimeLastAppRan { get; set; }
public List<SteamCmdWorkshopItemsInstalled> WorkshopItemsInstalled { get; set; }
public List<SteamCmdWorkshopItemDetails> WorkshopItemDetails { get; set; }
}
}

View file

@ -0,0 +1,83 @@
using NeXt.Vdf;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ServerManagerTool.Common.Model
{
public class SteamCmdManifestDetailsResult
{
public static bool ClearUserConfigBetaKeys(VdfValue data)
{
var updated = false;
var vdfTable = data as VdfTable;
if (vdfTable != null)
{
var value = vdfTable.FirstOrDefault(v => v.Name.Equals("UserConfig", StringComparison.OrdinalIgnoreCase));
var tableValue = value as VdfTable;
if (tableValue != null && tableValue.Count > 0)
{
var betaKeyItems = tableValue.Where(v => v.Name.Equals("betakey", StringComparison.OrdinalIgnoreCase)).ToArray();
foreach (var item in betaKeyItems)
{
tableValue.Remove(item);
updated = true;
}
}
}
return updated;
}
public static SteamCmdAppManifest Deserialize(VdfValue data)
{
var result = new SteamCmdAppManifest();
var vdfTable = data as VdfTable;
if (vdfTable != null)
{
var value = vdfTable.FirstOrDefault(v => v.Name.Equals("appid", StringComparison.OrdinalIgnoreCase));
if (value != null) result.appid = GetValue(value);
value = vdfTable.FirstOrDefault(v => v.Name.Equals("UserConfig", StringComparison.OrdinalIgnoreCase));
var tableValue = value as VdfTable;
if (tableValue != null && tableValue.Count > 0)
{
result.UserConfig = new List<SteamCmdManifestUserConfig>();
foreach (var item in tableValue)
{
if (item is VdfTable)
{
var temp = new SteamCmdManifestUserConfig();
temp.betakey = item.Name;
result.UserConfig.Add(temp);
}
}
}
}
return result;
}
public static string GetValue(VdfValue data)
{
if (data == null)
return null;
switch (data.Type)
{
case VdfValueType.Decimal:
return ((VdfDecimal)data).Content.ToString("G0");
case VdfValueType.Long:
return ((VdfLong)data).Content.ToString("G0");
case VdfValueType.String:
return ((VdfString)data).Content;
default:
return null;
}
}
}
}

View file

@ -0,0 +1,7 @@
namespace ServerManagerTool.Common.Model
{
public class SteamCmdManifestUserConfig
{
public string betakey { get; set; }
}
}

View file

@ -0,0 +1,111 @@
using NeXt.Vdf;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ServerManagerTool.Common.Model
{
public class SteamCmdWorkshopDetailsResult
{
public static SteamCmdAppWorkshop Deserialize(VdfValue data)
{
var result = new SteamCmdAppWorkshop();
var vdfTable = data as VdfTable;
if (vdfTable != null)
{
var value = vdfTable.FirstOrDefault(v => v.Name.Equals("appid", StringComparison.OrdinalIgnoreCase));
if (value != null) result.appid = GetValue(value);
value = vdfTable.FirstOrDefault(v => v.Name.Equals("SizeOnDisk", StringComparison.OrdinalIgnoreCase));
if (value != null) result.SizeOnDisk = GetValue(value);
value = vdfTable.FirstOrDefault(v => v.Name.Equals("NeedsUpdate", StringComparison.OrdinalIgnoreCase));
if (value != null) result.NeedsUpdate = GetValue(value);
value = vdfTable.FirstOrDefault(v => v.Name.Equals("NeedsDownload", StringComparison.OrdinalIgnoreCase));
if (value != null) result.NeedsDownload = GetValue(value);
value = vdfTable.FirstOrDefault(v => v.Name.Equals("TimeLastUpdated", StringComparison.OrdinalIgnoreCase));
if (value != null) result.TimeLastUpdated = GetValue(value);
value = vdfTable.FirstOrDefault(v => v.Name.Equals("TimeLastAppRan", StringComparison.OrdinalIgnoreCase));
if (value != null) result.TimeLastAppRan = GetValue(value);
value = vdfTable.FirstOrDefault(v => v.Name.Equals("WorkshopItemsInstalled", StringComparison.OrdinalIgnoreCase));
var tableValue = value as VdfTable;
if (tableValue != null && tableValue.Count > 0)
{
result.WorkshopItemsInstalled = new List<SteamCmdWorkshopItemsInstalled>();
foreach (var item in tableValue)
{
if (item is VdfTable)
{
var temp = new SteamCmdWorkshopItemsInstalled();
temp.publishedfileid = item.Name;
value = ((VdfTable)item).FirstOrDefault(v => v.Name.Equals("manifest", StringComparison.OrdinalIgnoreCase));
if (value != null) temp.manifest = GetValue(value);
value = ((VdfTable)item).FirstOrDefault(v => v.Name.Equals("size", StringComparison.OrdinalIgnoreCase));
if (value != null) temp.size = GetValue(value);
value = ((VdfTable)item).FirstOrDefault(v => v.Name.Equals("timeupdated", StringComparison.OrdinalIgnoreCase));
if (value != null) temp.timeupdated = GetValue(value);
result.WorkshopItemsInstalled.Add(temp);
}
}
}
value = vdfTable.FirstOrDefault(v => v.Name.Equals("WorkshopItemDetails", StringComparison.OrdinalIgnoreCase));
tableValue = value as VdfTable;
if (tableValue != null && tableValue.Count > 0)
{
result.WorkshopItemDetails = new List<SteamCmdWorkshopItemDetails>();
foreach (var item in tableValue)
{
if (item is VdfTable)
{
var temp = new SteamCmdWorkshopItemDetails();
temp.publishedfileid = item.Name;
value = ((VdfTable)item).FirstOrDefault(v => v.Name.Equals("manifest", StringComparison.OrdinalIgnoreCase));
if (value != null) temp.manifest = GetValue(value);
value = ((VdfTable)item).FirstOrDefault(v => v.Name.Equals("timeupdated", StringComparison.OrdinalIgnoreCase));
if (value != null) temp.timeupdated = GetValue(value);
value = ((VdfTable)item).FirstOrDefault(v => v.Name.Equals("timetouched", StringComparison.OrdinalIgnoreCase));
if (value != null) temp.timetouched = GetValue(value);
result.WorkshopItemDetails.Add(temp);
}
}
}
}
return result;
}
public static string GetValue(VdfValue data)
{
if (data == null)
return null;
switch (data.Type)
{
case VdfValueType.Decimal:
return ((VdfDecimal)data).Content.ToString("G0");
case VdfValueType.Long:
return ((VdfLong)data).Content.ToString("G0");
case VdfValueType.String:
return ((VdfString)data).Content;
default:
return null;
}
}
}
}

View file

@ -0,0 +1,13 @@
namespace ServerManagerTool.Common.Model
{
public class SteamCmdWorkshopItemDetails
{
public string publishedfileid { get; set; }
public string manifest { get; set; }
public string timeupdated { get; set; }
public string timetouched { get; set; }
}
}

View file

@ -0,0 +1,13 @@
namespace ServerManagerTool.Common.Model
{
public class SteamCmdWorkshopItemsInstalled
{
public string publishedfileid { get; set; }
public string manifest { get; set; }
public string size { get; set; }
public string timeupdated { get; set; }
}
}

View file

@ -0,0 +1,23 @@
namespace ServerManagerTool.Common.Model
{
public class SteamServerDetail
{
public string addr { get; set; }
public int gmsindex { get; set; }
public string appid { get; set; }
public string gamedir { get; set; }
public int region { get; set; }
public string secure { get; set; }
public string lan { get; set; }
public int gameport { get; set; }
public int specport { get; set; }
}
}

View file

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace ServerManagerTool.Common.Model
{
public class SteamServerDetailResponse
{
public string success { get; set; }
public List<SteamServerDetail> servers { get; set; }
}
}

View file

@ -0,0 +1,7 @@
namespace ServerManagerTool.Common.Model
{
public class SteamServerDetailResult
{
public SteamServerDetailResponse response { get; set; }
}
}

View file

@ -0,0 +1,25 @@
namespace ServerManagerTool.Common.Model
{
public class SteamUserDetail
{
public string steamid { get; set; }
public int communityvisibilitystate { get; set; }
public int profilestate { get; set; }
public string personaname { get; set; }
public int lastlogoff { get; set; }
public string profileurl { get; set; }
public string avatar { get; set; }
public string avatarmedium { get; set; }
public string avatarfull { get; set; }
public int personastate { get; set; }
}
}

View file

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace ServerManagerTool.Common.Model
{
public class SteamUserDetailResponse
{
public List<SteamUserDetail> players { get; set; }
}
}

View file

@ -0,0 +1,7 @@
namespace ServerManagerTool.Common.Model
{
public class SteamUserDetailResult
{
public SteamUserDetailResponse response { get; set; }
}
}

View file

@ -0,0 +1,39 @@
using ServerManagerTool.Common.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ServerManagerTool.Common.Model
{
public class StringIniValueList : IniValueList<string>, IIniValuesList
{
public StringIniValueList(string iniKeyName, Func<IEnumerable<string>> resetFunc) :
base(iniKeyName, resetFunc, string.Equals, m => m, ToIniValueInternal, FromIniValueInternal)
{
}
public override bool IsArray => false;
private static string ToIniValueInternal(string val)
{
return "\"" + val + "\"";
}
private static string FromIniValueInternal(string iniVal)
{
return iniVal.Trim('"');
}
public IEnumerable<string> ToIniValues(object excludeIfValue)
{
var excludeIfStringValue = excludeIfValue is string ? (string)excludeIfValue : null;
var values = new List<string>();
if (string.IsNullOrWhiteSpace(IniCollectionKey))
values.AddRange(this.Where(v => !EquivalencyFunc(v, excludeIfStringValue)).Select(d => ToIniValueInternal(d)));
else
values.AddRange(this.Where(v => !EquivalencyFunc(v, excludeIfStringValue)).Select(d => $"{this.IniCollectionKey}={ToIniValueInternal(d)}"));
return values;
}
}
}

View file

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
namespace ServerManagerTool.Common.Model
{
public class VersionFeed
{
public string Id { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public string SubTitle { get; set; } = string.Empty;
public Uri Link { get; set; } = null;
public DateTimeOffset Updated { get; set; } = DateTimeOffset.Now;
public List<VersionFeedEntry> Entries { get; set; } = new List<VersionFeedEntry>();
}
}

View file

@ -0,0 +1,17 @@
using System;
namespace ServerManagerTool.Common.Model
{
public class VersionFeedEntry
{
public string Id { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public string Summary { get; set; } = string.Empty;
public Uri Link { get; set; } = null;
public DateTimeOffset Updated { get; set; } = DateTimeOffset.Now;
public string Content { get; set; } = string.Empty;
public string Author { get; set; } = string.Empty;
public bool IsCurrent { get; set; } = false;
}
}

View file

@ -0,0 +1,97 @@
using System;
namespace ServerManagerTool.Common.Model
{
public class WorkshopFileDetail
{
public int result { get; set; }
public string publishedfileid { get; set; }
public string creator { get; set; }
public string creator_appid { get; set; }
public string consumer_appid { get; set; }
public int consumer_shortcutid { get; set; }
public string filename { get; set; }
public string file_size { get; set; }
public string preview_file_size { get; set; }
public string file_url { get; set; }
public string preview_url { get; set; }
public string url { get; set; }
public string hcontent_file { get; set; }
public string hcontent_preview { get; set; }
public string title { get; set; }
public string file_description { get; set; }
public int time_created { get; set; }
public int time_updated { get; set; }
public int visibility { get; set; }
public int flags { get; set; }
public bool workshop_file { get; set; }
public bool workshop_accepted { get; set; }
public bool show_subscribe_all { get; set; }
public int num_comments_developer { get; set; }
public int num_comments_public { get; set; }
public bool banned { get; set; }
public string ban_reason { get; set; }
public string banner { get; set; }
public bool can_be_deleted { get; set; }
public bool incompatible { get; set; }
public string app_name { get; set; }
public int file_type { get; set; }
public bool can_subscribe { get; set; }
public int subscriptions { get; set; }
public int favorited { get; set; }
public int followers { get; set; }
public int lifetime_subscriptions { get; set; }
public int lifetime_favorited { get; set; }
public int lifetime_followers { get; set; }
public int views { get; set; }
public bool spoiler_tag { get; set; }
public int num_children { get; set; }
public int num_reports { get; set; }
public int language { get; set; }
public bool IsAdded { get; set; }
}
}

View file

@ -0,0 +1,32 @@
using ServerManagerTool.Common.Utils;
using System;
using System.Collections.Generic;
using System.IO;
namespace ServerManagerTool.Common.Model
{
public class WorkshopFileDetailResponse
{
public DateTime cached = DateTime.UtcNow;
public int total { get; set; }
public List<WorkshopFileDetail> publishedfiledetails { get; set; }
public static WorkshopFileDetailResponse Load(string file)
{
if (string.IsNullOrWhiteSpace(file) || !File.Exists(file))
return null;
return JsonUtils.DeserializeFromFile<WorkshopFileDetailResponse>(file);
}
public bool Save(string file)
{
if (string.IsNullOrWhiteSpace(file))
return false;
return JsonUtils.SerializeToFile(this, file);
}
}
}

View file

@ -0,0 +1,7 @@
namespace ServerManagerTool.Common.Model
{
public class WorkshopFileDetailResult
{
public WorkshopFileDetailResponse response { get; set; }
}
}

View file

@ -0,0 +1,107 @@
using ServerManagerTool.Common.Utils;
using System;
using System.Windows;
namespace ServerManagerTool.Common.Model
{
public class WorkshopFileItem : DependencyObject
{
public static readonly DependencyProperty AppIdProperty = DependencyProperty.Register(nameof(AppId), typeof(string), typeof(WorkshopFileItem), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty CreatedDateProperty = DependencyProperty.Register(nameof(CreatedDate), typeof(DateTime), typeof(WorkshopFileItem), new PropertyMetadata(DateTime.MinValue));
public static readonly DependencyProperty FileSizeProperty = DependencyProperty.Register(nameof(FileSize), typeof(long), typeof(WorkshopFileItem), new PropertyMetadata(-1L));
public static readonly DependencyProperty SubscriptionsProperty = DependencyProperty.Register(nameof(Subscriptions), typeof(int), typeof(WorkshopFileItem), new PropertyMetadata(0));
public static readonly DependencyProperty TimeUpdatedProperty = DependencyProperty.Register(nameof(TimeUpdated), typeof(int), typeof(WorkshopFileItem), new PropertyMetadata(0));
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(WorkshopFileItem), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty UpdatedDateProperty = DependencyProperty.Register(nameof(UpdatedDate), typeof(DateTime), typeof(WorkshopFileItem), new PropertyMetadata(DateTime.MinValue));
public static readonly DependencyProperty WorkshopIdProperty = DependencyProperty.Register(nameof(WorkshopId), typeof(string), typeof(WorkshopFileItem), new PropertyMetadata(string.Empty));
public string AppId
{
get { return (string)GetValue(AppIdProperty); }
set { SetValue(AppIdProperty, value); }
}
public DateTime CreatedDate
{
get { return (DateTime)GetValue(CreatedDateProperty); }
set { SetValue(CreatedDateProperty, value); }
}
public long FileSize
{
get { return (long)GetValue(FileSizeProperty); }
set { SetValue(FileSizeProperty, value); }
}
public int Subscriptions
{
get { return (int)GetValue(SubscriptionsProperty); }
set { SetValue(SubscriptionsProperty, 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 DateTime UpdatedDate
{
get { return (DateTime)GetValue(UpdatedDateProperty); }
set { SetValue(UpdatedDateProperty, value); }
}
public string WorkshopId
{
get { return (string)GetValue(WorkshopIdProperty); }
set { SetValue(WorkshopIdProperty, value); }
}
public string TitleFilterString
{
get;
private set;
}
public string WorkshopUrl => $"http://steamcommunity.com/sharedfiles/filedetails/?id={WorkshopId}";
public static WorkshopFileItem GetItem(WorkshopFileDetail item)
{
if (string.IsNullOrWhiteSpace(item.publishedfileid) || string.IsNullOrWhiteSpace(item.title))
return null;
var result = new WorkshopFileItem();
result.AppId = item.creator_appid;
result.CreatedDate = DateTimeUtils.UnixTimeStampToDateTime(item.time_created);
result.FileSize = -1;
result.Subscriptions = item.subscriptions;
result.TimeUpdated = item.time_updated;
result.Title = item.title ?? string.Empty;
result.UpdatedDate = DateTimeUtils.UnixTimeStampToDateTime(item.time_updated);
result.WorkshopId = item.publishedfileid ?? string.Empty;
long fileSize;
if (long.TryParse(item.file_size, out fileSize))
result.FileSize = fileSize;
return result;
}
public override string ToString()
{
return $"{WorkshopId} - {Title}";
}
}
}

View file

@ -0,0 +1,55 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
namespace ServerManagerTool.Common.Model
{
public class WorkshopFileList : ObservableCollection<WorkshopFileItem>
{
public DateTime CachedTime
{
get;
set;
}
public string CachedTimeFormatted
{
get
{
if (CachedTime == DateTime.MinValue)
return "";
return CachedTime.ToString("G");
}
}
public new void Add(WorkshopFileItem item)
{
if (item == null || this.Any(m => m.WorkshopId.Equals(item.WorkshopId)))
return;
base.Add(item);
}
public static WorkshopFileList GetList(WorkshopFileDetailResponse response)
{
var result = new WorkshopFileList();
if (response != null)
{
result.CachedTime = response.cached.ToLocalTime();
if (response.publishedfiledetails != null)
{
foreach (var detail in response.publishedfiledetails)
{
result.Add(WorkshopFileItem.GetItem(detail));
}
}
}
return result;
}
public override string ToString()
{
return $"{nameof(WorkshopFileList)} - {Count}";
}
}
}