Non-indexed remove causes a full reset (@Xero's issue)

Removed ignore last session option.  Implicitly true now.
Asteroid generation options (fixes #151)
This commit is contained in:
Westin Miller
2017-10-29 09:53:20 -07:00
parent 7a63527d8f
commit b7fa57c9b7
11 changed files with 120 additions and 91 deletions

View File

@@ -5,7 +5,9 @@ using System.Text;
using System.Threading.Tasks;
using Sandbox.Engine.Multiplayer;
using Sandbox.Game.Multiplayer;
using VRage.Game;
using VRage.Network;
using VRage.Replication;
namespace Torch.API.Managers
{
@@ -19,13 +21,30 @@ namespace Torch.API.Managers
/// </summary>
/// <param name="author">Author's name</param>
/// <param name="message">Message</param>
public TorchChatMessage(string author, string message)
/// <param name="font">Font</param>
public TorchChatMessage(string author, string message, string font = MyFontEnum.Blue)
{
Timestamp = DateTime.Now;
AuthorSteamId = null;
Author = author;
Message = message;
Font = "Blue";
Font = font;
}
/// <summary>
/// Creates a new torch chat message with the given author and message.
/// </summary>
/// <param name="author">Author's name</param>
/// <param name="authorSteamId">Author's steam ID</param>
/// <param name="message">Message</param>
/// <param name="font">Font</param>
public TorchChatMessage(string author, ulong authorSteamId, string message, string font = MyFontEnum.Blue)
{
Timestamp = DateTime.Now;
AuthorSteamId = authorSteamId;
Author = author;
Message = message;
Font = font;
}
/// <summary>
@@ -33,35 +52,36 @@ namespace Torch.API.Managers
/// </summary>
/// <param name="authorSteamId">Author's steam ID</param>
/// <param name="message">Message</param>
public TorchChatMessage(ulong authorSteamId, string message)
/// <param name="font">Font</param>
public TorchChatMessage(ulong authorSteamId, string message, string font = MyFontEnum.Blue)
{
Timestamp = DateTime.Now;
AuthorSteamId = authorSteamId;
Author = MyMultiplayer.Static?.GetMemberName(authorSteamId) ?? "Player";
Message = message;
Font = "Blue";
Font = font;
}
/// <summary>
/// This message's timestamp.
/// </summary>
public DateTime Timestamp;
public readonly DateTime Timestamp;
/// <summary>
/// The author's steam ID, if available. Else, null.
/// </summary>
public ulong? AuthorSteamId;
public readonly ulong? AuthorSteamId;
/// <summary>
/// The author's name, if available. Else, null.
/// </summary>
public string Author;
public readonly string Author;
/// <summary>
/// The message contents.
/// </summary>
public string Message;
public readonly string Message;
/// <summary>
/// The font, or null if default.
/// </summary>
public string Font;
public readonly string Font;
}
/// <summary>

View File

@@ -26,6 +26,7 @@ namespace Torch.Server.ViewModels
public ConfigDedicatedViewModel(MyConfigDedicated<MyObjectBuilder_SessionSettings> configDedicated)
{
_config = configDedicated;
_config.IgnoreLastSession = true;
SessionSettings = new SessionSettingsViewModel(_config.SessionSettings);
Administrators = string.Join(Environment.NewLine, _config.Administrators);
Banned = string.Join(Environment.NewLine, _config.Banned);
@@ -53,6 +54,8 @@ namespace Torch.Server.ViewModels
Log.Warn($"'{mod}' is not a valid mod ID.");
}
// Never ever
_config.IgnoreLastSession = true;
_config.Save(path);
}
@@ -79,12 +82,6 @@ namespace Torch.Server.ViewModels
set { _config.GroupID = value; OnPropertyChanged(); }
}
public bool IgnoreLastSession
{
get { return _config.IgnoreLastSession; }
set { _config.IgnoreLastSession = value; OnPropertyChanged(); }
}
public string IP
{
get { return _config.IP; }

View File

@@ -23,7 +23,7 @@ namespace Torch.Server.ViewModels
/// </summary>
public SessionSettingsViewModel() : this(new MyObjectBuilder_SessionSettings())
{
}
/// <summary>
@@ -363,6 +363,19 @@ namespace Torch.Server.ViewModels
get => _settings.WorldSizeKm; set { _settings.WorldSizeKm = value; OnPropertyChanged(); }
}
/// <inheritdoc cref="MyObjectBuilder_SessionSettings.ProceduralDensity"/>
public float ProceduralDensity
{
get => _settings.ProceduralDensity; set { _settings.ProceduralDensity = value; OnPropertyChanged(); }
}
/// <inheritdoc cref="MyObjectBuilder_SessionSettings.ProceduralSeed"/>
public int ProceduralSeed
{
get => _settings.ProceduralSeed;
set { _settings.ProceduralSeed = value; OnPropertyChanged(); }
}
/// <summary />
public static implicit operator MyObjectBuilder_SessionSettings(SessionSettingsViewModel viewModel)
{

View File

@@ -136,12 +136,12 @@ namespace Torch.Server
var commands = _server.CurrentSession?.Managers.GetManager<Torch.Commands.CommandManager>();
if (commands != null && commands.IsCommand(text))
{
InsertMessage(new TorchChatMessage("Server", text) { Font = MyFontEnum.DarkBlue });
InsertMessage(new TorchChatMessage("Server", text, MyFontEnum.DarkBlue));
_server.Invoke(() =>
{
string response = commands.HandleCommandFromServer(text);
if (!string.IsNullOrWhiteSpace(response))
InsertMessage(new TorchChatMessage("Server", response) { Font = MyFontEnum.Blue });
InsertMessage(new TorchChatMessage("Server", response, MyFontEnum.Blue));
});
}
else

View File

@@ -45,7 +45,6 @@
<Label Content=":" Width="12" />
<TextBox Text="{Binding Port}" Width="48" Height="20" />
</StackPanel>
<CheckBox IsChecked="{Binding IgnoreLastSession}" Content="Ignore Last Session" Margin="3" />
<CheckBox IsChecked="{Binding PauseGameWhenEmpty}" Content="Pause When Empty" Margin="3" />
</StackPanel>
<StackPanel Margin="3">
@@ -174,6 +173,14 @@
DockPanel.Dock="Left" />
<Label Content="Environment Hostility" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding ProceduralDensity}" Margin="3" Width="70" />
<Label Content="Procedural Density" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding ProceduralSeed}" Margin="3" Width="70" />
<Label Content="Procedural Seed" />
</StackPanel>
</StackPanel>
</Expander>
<Expander Header="Players">

View File

@@ -12,6 +12,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using NLog;
using Torch;
using Sandbox;
using Sandbox.Engine.Multiplayer;
@@ -34,6 +35,8 @@ namespace Torch.Server
/// </summary>
public partial class PlayerListControl : UserControl
{
private static readonly Logger _log = LogManager.GetCurrentClassLogger();
private ITorchServer _server;
public PlayerListControl()
@@ -65,13 +68,27 @@ namespace Torch.Server
private void KickButton_Click(object sender, RoutedEventArgs e)
{
var player = (KeyValuePair<ulong, PlayerViewModel>)PlayerList.SelectedItem;
_server.CurrentSession?.Managers.GetManager<IMultiplayerManagerServer>()?.KickPlayer(player.Key);
try
{
_server.CurrentSession.Managers.GetManager<IMultiplayerManagerServer>().KickPlayer(player.Key);
}
catch (Exception ex)
{
_log.Warn(ex);
}
}
private void BanButton_Click(object sender, RoutedEventArgs e)
{
var player = (KeyValuePair<ulong, PlayerViewModel>)PlayerList.SelectedItem;
_server.CurrentSession?.Managers.GetManager<IMultiplayerManagerServer>()?.BanPlayer(player.Key);
try
{
_server.CurrentSession.Managers.GetManager<IMultiplayerManagerServer>().BanPlayer(player.Key);
}
catch (Exception ex)
{
_log.Warn(ex);
}
}
}
}

View File

@@ -40,7 +40,7 @@ namespace Torch.Collections
/// </summary>
/// <param name="old">Collection to clear and reuse, or null if none</param>
/// <returns>The snapshot</returns>
protected abstract TC Snapshot(TC old);
protected abstract List<TV> Snapshot(List<TV> old);
/// <summary>
/// Marks all snapshots taken of this collection as dirty.
@@ -104,7 +104,7 @@ namespace Torch.Collections
OnPropertyChanged(nameof(Count));
OnCollectionChanged(oldIndex.HasValue
? new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, oldIndex.Value)
: new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
: new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
return true;
}
}
@@ -204,7 +204,6 @@ namespace Torch.Collections
for (int i = invokeList.Length - 1; i >= 0; i--)
{
var wrapper = (DispatcherDelegate)invokeList[i].Target;
Debug.Assert(wrapper._dispatcher == CurrentDispatcher, "Adding and removing should be done from the same dispatcher");
if (wrapper._delegate.Equals(evt))
{
_event -= wrapper.Invoke;
@@ -215,7 +214,7 @@ namespace Torch.Collections
private struct DispatcherDelegate
{
internal readonly Dispatcher _dispatcher;
private readonly Dispatcher _dispatcher;
internal readonly TEvtHandle _delegate;
internal DispatcherDelegate(TEvtHandle del)
@@ -244,7 +243,7 @@ namespace Torch.Collections
private sealed class ThreadView
{
private readonly MtObservableCollection<TC, TV> _owner;
private readonly WeakReference<TC> _snapshot;
private readonly WeakReference<List<TV>> _snapshot;
/// <summary>
/// The <see cref="MtObservableCollection{TC,TV}._version"/> of the <see cref="_snapshot"/>
/// </summary>
@@ -257,17 +256,17 @@ namespace Torch.Collections
internal ThreadView(MtObservableCollection<TC, TV> owner)
{
_owner = owner;
_snapshot = new WeakReference<TC>(null);
_snapshot = new WeakReference<List<TV>>(null);
_snapshotVersion = 0;
_snapshotRefCount = 0;
}
private TC GetSnapshot()
private List<TV> GetSnapshot()
{
// reading the version number + snapshots
using (_owner.Lock.ReadUsing())
{
if (!_snapshot.TryGetTarget(out TC currentSnapshot) || _snapshotVersion != _owner._version)
if (!_snapshot.TryGetTarget(out List<TV> currentSnapshot) || _snapshotVersion != _owner._version)
{
// Update the snapshot, using the old one if it isn't referenced.
currentSnapshot = _owner.Snapshot(_snapshotRefCount == 0 ? currentSnapshot : null);

View File

@@ -2,9 +2,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Torch.Utils;
namespace Torch.Collections
@@ -21,17 +18,16 @@ namespace Torch.Collections
/// </summary>
public MtObservableDictionary() : base(new Dictionary<TK, TV>())
{
Keys = new ProxyCollection<TK>(this, Backing.Keys, (x) => x.Key);
Values = new ProxyCollection<TV>(this, Backing.Values, (x) => x.Value);
ObservableKeys = new ProxyCollection<TK>(this, Backing.Keys, (x) => x.Key);
ObservableValues = new ProxyCollection<TV>(this, Backing.Values, (x) => x.Value);
}
protected override IDictionary<TK, TV> Snapshot(IDictionary<TK, TV> old)
protected override List<KeyValuePair<TK, TV>> Snapshot(List<KeyValuePair<TK, TV>> old)
{
if (old == null)
return new Dictionary<TK, TV>(Backing);
return new List<KeyValuePair<TK, TV>>(Backing);
old.Clear();
foreach (KeyValuePair<TK, TV> k in Backing)
old.Add(k);
old.AddRange(Backing);
return old;
}
@@ -83,10 +79,17 @@ namespace Torch.Collections
}
/// <inheritdoc/>
public ICollection<TK> Keys { get; }
public ICollection<TK> Keys => ObservableKeys;
/// <inheritdoc/>
public ICollection<TV> Values { get; }
public ICollection<TV> Values => ObservableValues;
// TODO when we rewrite this to use a sorted dictionary.
/// <inheritdoc cref="Keys"/>
private ProxyCollection<TK> ObservableKeys { get; }
/// <inheritdoc cref="Keys"/>
private ProxyCollection<TV> ObservableValues { get; }
internal void RaiseFullReset()
{
@@ -94,7 +97,11 @@ namespace Torch.Collections
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
private class ProxyCollection<TP> : ICollection<TP>
/// <summary>
/// Proxy collection capable of raising notifications when the parent collection changes.
/// </summary>
/// <typeparam name="TP">Entry type</typeparam>
public class ProxyCollection<TP> : ICollection<TP>
{
private readonly MtObservableDictionary<TK, TV> _owner;
private readonly ICollection<TP> _backing;
@@ -116,17 +123,13 @@ namespace Torch.Collections
/// <inheritdoc/>
public void Add(TP item)
{
using (_owner.Lock.WriteUsing())
{
_backing.Add(item);
_owner.RaiseFullReset();
}
throw new NotSupportedException();
}
/// <inheritdoc/>
public void Clear()
{
_owner.Clear();
throw new NotSupportedException();
}
/// <inheritdoc/>
@@ -146,13 +149,7 @@ namespace Torch.Collections
/// <inheritdoc/>
public bool Remove(TP item)
{
using (_owner.Lock.WriteUsing())
{
if (!_backing.Remove(item))
return false;
_owner.RaiseFullReset();
return true;
}
throw new NotSupportedException();
}
/// <inheritdoc/>
@@ -165,6 +162,7 @@ namespace Torch.Collections
}
}
/// <inheritdoc/>
public bool IsReadOnly => _backing.IsReadOnly;
}
}

View File

@@ -29,7 +29,7 @@ namespace Torch.Collections
{
}
protected override IList<T> Snapshot(IList<T> old)
protected override List<T> Snapshot(List<T> old)
{
if (old == null)
{
@@ -37,11 +37,7 @@ namespace Torch.Collections
return list;
}
old.Clear();
if (old is List<T> tmp)
tmp.AddRange(Backing);
else
foreach (T k in Backing)
old.Add(k);
old.AddRange(Backing);
return old;
}
@@ -55,7 +51,7 @@ namespace Torch.Collections
/// <inheritdoc/>
public void Insert(int index, T item)
{
using(Lock.WriteUsing())
using (Lock.WriteUsing())
{
Backing.Insert(index, item);
MarkSnapshotsDirty();
@@ -82,12 +78,13 @@ namespace Torch.Collections
{
get
{
using(Lock.ReadUsing())
using (Lock.ReadUsing())
return Backing[index];
}
set
{
using(Lock.ReadUsing()) {
using (Lock.ReadUsing())
{
T old = Backing[index];
Backing[index] = value;
MarkSnapshotsDirty();
@@ -109,7 +106,8 @@ namespace Torch.Collections
/// </summary>
public void Sort<TKey>(Func<T, TKey> selector, IComparer<TKey> comparer = null)
{
using (Lock.ReadUsing()) {
using (Lock.ReadUsing())
{
comparer = comparer ?? Comparer<TKey>.Default;
if (Backing is List<T> lst)
lst.Sort(new TransformComparer<T, TKey>(selector, comparer));

View File

@@ -113,12 +113,7 @@ namespace Torch.Managers.ChatManager
{
if (!sendToOthers)
return;
var torchMsg = new TorchChatMessage()
{
AuthorSteamId = Sync.MyId,
Author = MySession.Static.LocalHumanPlayer?.DisplayName ?? "Player",
Message = messageText
};
var torchMsg = new TorchChatMessage(MySession.Static.LocalHumanPlayer?.DisplayName ?? "Player", Sync.MyId, messageText);
var consumed = false;
MessageRecieved?.Invoke(torchMsg, ref consumed);
if (!consumed)
@@ -138,14 +133,8 @@ namespace Torch.Managers.ChatManager
private void Multiplayer_ChatMessageReceived(ulong steamUserId, string message)
{
var torchMsg = new TorchChatMessage()
{
AuthorSteamId = steamUserId,
Author = Torch.CurrentSession.Managers.GetManager<IMultiplayerManagerBase>()
?.GetSteamUsername(steamUserId),
Font = (steamUserId == MyGameService.UserId) ? "DarkBlue" : "Blue",
Message = message
};
var torchMsg = new TorchChatMessage(steamUserId, message,
(steamUserId == MyGameService.UserId) ? MyFontEnum.DarkBlue : MyFontEnum.Blue);
var consumed = false;
MessageRecieved?.Invoke(torchMsg, ref consumed);
if (!consumed && HasHud)
@@ -154,13 +143,7 @@ namespace Torch.Managers.ChatManager
private void Multiplayer_ScriptedChatMessageReceived(string message, string author, string font)
{
var torchMsg = new TorchChatMessage()
{
AuthorSteamId = null,
Author = author,
Font = font,
Message = message
};
var torchMsg = new TorchChatMessage(author, message, font);
var consumed = false;
MessageRecieved?.Invoke(torchMsg, ref consumed);
if (!consumed && HasHud)

View File

@@ -147,12 +147,9 @@ namespace Torch.Managers.ChatManager
internal void RaiseMessageRecieved(ChatMsg message, ref bool consumed)
{
var torchMsg = new TorchChatMessage()
{
AuthorSteamId = message.Author,
Author = MyMultiplayer.Static?.GetMemberName(message.Author) ?? $"user_{message.Author}",
Message = message.Text
};
var torchMsg =
new TorchChatMessage(MyMultiplayer.Static?.GetMemberName(message.Author) ?? $"user_{message.Author}",
message.Author, message.Text);
MessageProcessing?.Invoke(torchMsg, ref consumed);
}