Save Torch config on server start, remove concealment code (moved to plugin)

This commit is contained in:
John Gross
2017-04-18 10:58:23 -07:00
parent 32f5147060
commit 03a22851af
8 changed files with 23 additions and 379 deletions

View File

@@ -52,7 +52,7 @@ namespace Torch.Server
{ {
_log.Info($"Generating default config at {configPath}"); _log.Info($"Generating default config at {configPath}");
options = new TorchConfig(); options = new TorchConfig();
options.SaveTo(configPath); options.Save(configPath);
} }
/* /*

View File

@@ -6,9 +6,9 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml.Serialization; using System.Xml.Serialization;
using NLog; using NLog;
using VRage.Dedicated; using Sandbox.ModAPI.Ingame;
namespace Torch.Server namespace Torch
{ {
public class TorchConfig public class TorchConfig
{ {
@@ -19,13 +19,15 @@ namespace Torch.Server
public int Autosave { get; set; } public int Autosave { get; set; }
public bool AutoRestart { get; set; } public bool AutoRestart { get; set; }
public bool LogChat { get; set; } public bool LogChat { get; set; }
[NonSerialized]
private string _path;
public TorchConfig() : this("Torch") { } public TorchConfig() : this("Torch") { }
public TorchConfig(string instanceName = "Torch", string instancePath = null, int autosaveInterval = 5, bool autoRestart = false) public TorchConfig(string instanceName = "Torch", string instancePath = null, int autosaveInterval = 5, bool autoRestart = false)
{ {
InstanceName = instanceName; InstanceName = instanceName;
InstancePath = instancePath ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SpaceEngineersDedicated", InstanceName); InstancePath = instancePath ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Torch", InstanceName);
Autosave = autosaveInterval; Autosave = autosaveInterval;
AutoRestart = autoRestart; AutoRestart = autoRestart;
} }
@@ -40,6 +42,7 @@ namespace Torch.Server
{ {
config = (TorchConfig)serializer.Deserialize(f); config = (TorchConfig)serializer.Deserialize(f);
} }
config._path = path;
return config; return config;
} }
catch (Exception e) catch (Exception e)
@@ -49,8 +52,13 @@ namespace Torch.Server
} }
} }
public bool SaveTo(string path) public bool Save(string path = null)
{ {
if (path == null)
path = _path;
else
_path = path;
try try
{ {
var serializer = new XmlSerializer(typeof(TorchConfig)); var serializer = new XmlSerializer(typeof(TorchConfig));

View File

@@ -34,24 +34,22 @@ namespace Torch.Server
{ {
public Thread GameThread { get; private set; } public Thread GameThread { get; private set; }
public bool IsRunning { get; private set; } public bool IsRunning { get; private set; }
public string InstancePath { get; private set; } public TorchConfig Config { get; }
public string InstanceName { get; private set; } public string InstanceName => Config?.InstanceName;
public string InstancePath => Config?.InstancePath;
private readonly AutoResetEvent _stopHandle = new AutoResetEvent(false); private readonly AutoResetEvent _stopHandle = new AutoResetEvent(false);
public TorchServer(TorchConfig options = null) public TorchServer(TorchConfig config = null)
{ {
var opt = options ?? new TorchConfig(); Config = config ?? new TorchConfig();
InstanceName = opt.InstanceName;
InstancePath = opt.InstancePath;
} }
public override void Init() public override void Init()
{ {
base.Init(); base.Init();
Log.Info($"Init server instance '{InstanceName}' at path '{InstancePath}'"); Log.Info($"Init server instance '{Config.InstanceName}' at path '{Config.InstancePath}'");
MyFakes.ENABLE_INFINARIO = false; MyFakes.ENABLE_INFINARIO = false;
MyPerGameSettings.SendLogToKeen = false; MyPerGameSettings.SendLogToKeen = false;
@@ -73,14 +71,6 @@ namespace Torch.Server
MySandboxGame.ConfigDedicated = config; MySandboxGame.ConfigDedicated = config;
} }
public void SetInstance(string path = null, string name = null)
{
if (path != null)
InstancePath = path;
if (name != null)
InstanceName = name;
}
public void Start(IMyConfigDedicated config) public void Start(IMyConfigDedicated config)
{ {
SetConfig(config); SetConfig(config);
@@ -95,6 +85,7 @@ namespace Torch.Server
if (IsRunning) if (IsRunning)
throw new InvalidOperationException("Server is already running."); throw new InvalidOperationException("Server is already running.");
Config.Save();
IsRunning = true; IsRunning = true;
Log.Info("Starting server."); Log.Info("Starting server.");
@@ -102,7 +93,7 @@ namespace Torch.Server
Environment.SetEnvironmentVariable("SteamAppId", MyPerServerSettings.AppId.ToString()); Environment.SetEnvironmentVariable("SteamAppId", MyPerServerSettings.AppId.ToString());
Log.Trace("Invoking RunMain"); Log.Trace("Invoking RunMain");
try { Reflection.InvokeStaticMethod(typeof(DedicatedServer), "RunMain", InstanceName, InstancePath, false, true); } try { Reflection.InvokeStaticMethod(typeof(DedicatedServer), "RunMain", Config.InstanceName, Config.InstancePath, false, true); }
catch (Exception e) catch (Exception e)
{ {
Log.Error("Error running server."); Log.Error("Error running server.");

View File

@@ -37,7 +37,7 @@ namespace Torch.Server
if (File.Exists(configName)) if (File.Exists(configName))
options = TorchConfig.LoadFrom(configName); options = TorchConfig.LoadFrom(configName);
else else
options.SaveTo(configName); options.Save(configName);
_server = new TorchServer(options); _server = new TorchServer(options);
_server.Init(); _server.Init();

View File

@@ -38,7 +38,7 @@ namespace Torch.Server
public TorchUI(TorchServer server) public TorchUI(TorchServer server)
{ {
_config = new TorchConfig(); _config = server.Config;
_server = server; _server = server;
InitializeComponent(); InitializeComponent();
_startTime = DateTime.Now; _startTime = DateTime.Now;
@@ -113,7 +113,6 @@ namespace Torch.Server
{ {
var name = (sender as TextBox).Text; var name = (sender as TextBox).Text;
_server.SetInstance(null, name);
_config.InstancePath = name; _config.InstancePath = name;
LoadConfig(_config); LoadConfig(_config);

View File

@@ -38,7 +38,6 @@ namespace Torch.Managers
public EntityManager(ITorchBase torch) public EntityManager(ITorchBase torch)
{ {
_torch = torch; _torch = torch;
_torch.SessionLoaded += () => InitConcealment(60000);
} }
public void ExportGrid(IMyCubeGrid grid, string path) public void ExportGrid(IMyCubeGrid grid, string path)
@@ -58,212 +57,6 @@ namespace Torch.Managers
grid.PositionComp.SetPosition(position); grid.PositionComp.SetPosition(position);
MyEntities.Add(grid); MyEntities.Add(grid);
} }
#region Concealment
private readonly List<ConcealGroup> _concealGroups = new List<ConcealGroup>();
private MyDynamicAABBTreeD _concealedAabbTree;
public void GetConcealedGrids(List<IMyCubeGrid> grids)
{
_concealGroups.SelectMany(x => x.Grids).ForEach(grids.Add);
}
private Timer _concealTimer;
private Timer _revealTimer;
private volatile bool _concealInProgress;
public void InitConcealment(double concealInterval)
{
return;
Log.Info($"Initializing concealment to run every {concealInterval}ms");
_concealedAabbTree = new MyDynamicAABBTreeD(MyConstants.GAME_PRUNING_STRUCTURE_AABB_EXTENSION);
_concealTimer = new Timer(concealInterval);
_concealTimer.Elapsed += ConcealTimerElapsed;
_concealTimer.Start();
_revealTimer = new Timer(1000);
_revealTimer.Elapsed += RevealTimerElapsed;
_revealTimer.Start();
MySession.Static.Players.PlayerRequesting += RevealSpawns;
MyMultiplayer.Static.ClientJoined += RevealCryoPod;
}
private void RevealTimerElapsed(object sender, ElapsedEventArgs e)
{
_torch.Invoke(() => RevealNearbyGrids(MyMultiplayer.Static.ViewDistance));
}
private void RevealCryoPod(ulong steamId)
{
_torch.Invoke(() =>
{
Log.Debug(nameof(RevealCryoPod));
for (var i = _concealGroups.Count - 1; i >= 0; i--)
{
var group = _concealGroups[i];
if (group.IsCryoOccupied(steamId))
{
RevealGroup(group);
return;
}
}
});
}
private void RevealSpawns(PlayerRequestArgs args)
{
_torch.Invoke(() =>
{
Log.Debug(nameof(RevealSpawns));
var identityId = MySession.Static.Players.TryGetIdentityId(args.PlayerId.SteamId);
if (identityId == 0)
return;
for (var i = _concealGroups.Count - 1; i >= 0; i--)
{
var group = _concealGroups[i];
if (group.IsMedicalRoomAvailable(identityId))
RevealGroup(group);
}
});
}
public void RevealAll()
{
for (var i = _concealGroups.Count - 1; i >= 0; i--)
RevealGroup(_concealGroups[i]);
}
private void ConcealTimerElapsed(object sender, ElapsedEventArgs e)
{
if (_concealInProgress)
{
Log.Warn($"Concealment taking longer to complete than the conceal interval of {_concealTimer.Interval}ms");
return;
}
_concealInProgress = true;
Log.Debug("Running concealment");
_torch.Invoke(() =>
{
if (MyAPIGateway.Session == null)
return;
var viewDistance = MyMultiplayer.Static.ViewDistance;
var concealDistance = viewDistance > 50000 ? viewDistance : 50000;
ConcealDistantGrids(concealDistance * 2);
_concealInProgress = false;
});
}
private void ConcealEntity(IMyEntity entity)
{
if (entity != entity.GetTopMostParent())
throw new InvalidOperationException("Can only conceal top-level entities.");
MyGamePruningStructure.Remove((MyEntity)entity);
entity.Physics?.Deactivate();
UnregisterRecursive(entity);
void UnregisterRecursive(IMyEntity e)
{
MyEntities.UnregisterForUpdate((MyEntity)e);
if (e.Hierarchy == null)
return;
foreach (var child in e.Hierarchy.Children)
UnregisterRecursive(child.Entity);
}
}
private void RevealEntity(IMyEntity entity)
{
if (entity != entity.GetTopMostParent())
throw new InvalidOperationException("Can only conceal top-level entities.");
MyGamePruningStructure.Add((MyEntity)entity);
entity.Physics?.Activate();
RegisterRecursive(entity);
void RegisterRecursive(IMyEntity e)
{
MyEntities.RegisterForUpdate((MyEntity)e);
if (e.Hierarchy == null)
return;
foreach (var child in e.Hierarchy.Children)
RegisterRecursive(child.Entity);
}
}
private bool ConcealGroup(ConcealGroup group)
{
if (_concealGroups.Any(g => g.Id == group.Id))
return false;
Log.Info($"Concealing grids: {string.Join(", ", group.Grids.Select(g => g.DisplayName))}");
group.ConcealTime = DateTime.Now;
group.Grids.ForEach(ConcealEntity);
Task.Run(() =>
{
group.UpdatePostConceal();
var aabb = group.WorldAABB;
group.ProxyId = _concealedAabbTree.AddProxy(ref aabb, group, 0);
Log.Debug($"Group {group.Id} cached");
_torch.Invoke(() => _concealGroups.Add(group));
});
return true;
}
private void RevealGroup(ConcealGroup group)
{
Log.Info($"Revealing grids: {string.Join(", ", group.Grids.Select(g => g.DisplayName))}");
group.Grids.ForEach(RevealEntity);
_concealGroups.Remove(group);
_concealedAabbTree.RemoveProxy(group.ProxyId);
}
private readonly List<ConcealGroup> _intersectGroups = new List<ConcealGroup>();
public void RevealGridsInSphere(BoundingSphereD sphere)
{
_concealedAabbTree.OverlapAllBoundingSphere(ref sphere, _intersectGroups);
foreach (var group in _intersectGroups)
{
RevealGroup(group);
}
_intersectGroups.Clear();
}
public void RevealNearbyGrids(double distanceFromPlayers)
{
var playerSpheres = GetPlayerBoundingSpheres(distanceFromPlayers);
foreach (var sphere in playerSpheres)
{
RevealGridsInSphere(sphere);
}
}
public void ConcealDistantGrids(double distanceFromPlayers)
{
var playerSpheres = GetPlayerBoundingSpheres(distanceFromPlayers);
foreach (var group in MyCubeGridGroups.Static.Physical.Groups)
{
var volume = group.GetWorldAABB();
if (playerSpheres.Any(s => s.Contains(volume) != ContainmentType.Disjoint))
continue;
ConcealGroup(new ConcealGroup(group));
}
}
private List<BoundingSphereD> GetPlayerBoundingSpheres(double distance)
{
return ((MyPlayerCollection)MyAPIGateway.Multiplayer.Players).GetOnlinePlayers()
.Where(p => p.Controller?.ControlledEntity != null)
.Select(p => new BoundingSphereD(p.Controller.ControlledEntity.Entity.PositionComp.GetPosition(), distance)).ToList();
}
#endregion Concealment
} }
public static class GroupExtensions public static class GroupExtensions
@@ -281,80 +74,4 @@ namespace Torch.Managers
return box; return box;
} }
} }
internal class ConcealGroup
{
/// <summary>
/// Entity ID of the first grid in the group.
/// </summary>
public long Id { get; }
public DateTime ConcealTime { get; set; }
public BoundingBoxD WorldAABB { get; private set; }
public List<MyCubeGrid> Grids { get; }
public List<MyMedicalRoom> MedicalRooms { get; } = new List<MyMedicalRoom>();
public List<MyCryoChamber> CryoChambers { get; } = new List<MyCryoChamber>();
internal volatile int ProxyId = -1;
public ConcealGroup(MyGroups<MyCubeGrid, MyGridPhysicalGroupData>.Group group)
{
Grids = group.Nodes.Select(n => n.NodeData).ToList();
Id = Grids.First().EntityId;
}
public void UpdatePostConceal()
{
UpdateAABB();
CacheSpawns();
}
private void UpdateAABB()
{
var startPos = Grids.First().PositionComp.GetPosition();
var box = new BoundingBoxD(startPos, startPos);
foreach (var aabb in Grids.Select(g => g.PositionComp.WorldAABB))
box.Include(aabb);
WorldAABB = box;
}
private void CacheSpawns()
{
MedicalRooms.Clear();
CryoChambers.Clear();
foreach (var block in Grids.SelectMany(x => x.GetFatBlocks()))
{
if (block is MyMedicalRoom medical)
MedicalRooms.Add(medical);
else if (block is MyCryoChamber cryo)
CryoChambers.Add(cryo);
}
}
public bool IsMedicalRoomAvailable(long identityId)
{
foreach (var room in MedicalRooms)
{
if (room.HasPlayerAccess(identityId) && room.IsWorking)
return true;
}
return false;
}
public bool IsCryoOccupied(ulong steamId)
{
var currentIdField = typeof(MyCryoChamber).GetField("m_currentPlayerId", BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var chamber in CryoChambers)
{
var value = (MyPlayer.PlayerId?)currentIdField.GetValue(chamber);
if (value?.SteamId == steamId)
return true;
}
return false;
}
}
} }

View File

@@ -137,7 +137,6 @@
<Compile Include="Managers\ScriptingManager.cs" /> <Compile Include="Managers\ScriptingManager.cs" />
<Compile Include="TorchBase.cs" /> <Compile Include="TorchBase.cs" />
<Compile Include="SteamService.cs" /> <Compile Include="SteamService.cs" />
<Compile Include="TorchConfig.cs" />
<Compile Include="TorchPluginBase.cs" /> <Compile Include="TorchPluginBase.cs" />
<Compile Include="Updater\PluginUpdater.cs" /> <Compile Include="Updater\PluginUpdater.cs" />
<Compile Include="ViewModels\ModViewModel.cs" /> <Compile Include="ViewModels\ModViewModel.cs" />

View File

@@ -1,70 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using NLog;
using Sandbox.ModAPI.Ingame;
namespace Torch
{
public class TorchConfig
{
private static Logger _log = LogManager.GetLogger("Config");
public string InstancePath { get; set; }
public string InstanceName { get; set; }
public int Autosave { get; set; }
public bool AutoRestart { get; set; }
public bool LogChat { get; set; }
public TorchConfig() : this("Torch") { }
public TorchConfig(string instanceName = "Torch", string instancePath = null, int autosaveInterval = 5, bool autoRestart = false)
{
InstanceName = instanceName;
InstancePath = instancePath ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Torch", InstanceName);
Autosave = autosaveInterval;
AutoRestart = autoRestart;
}
public static TorchConfig LoadFrom(string path)
{
try
{
var serializer = new XmlSerializer(typeof(TorchConfig));
TorchConfig config;
using (var f = File.OpenRead(path))
{
config = (TorchConfig)serializer.Deserialize(f);
}
return config;
}
catch (Exception e)
{
_log.Error(e);
return null;
}
}
public bool SaveTo(string path)
{
try
{
var serializer = new XmlSerializer(typeof(TorchConfig));
using (var f = File.OpenWrite(path))
{
serializer.Serialize(f, this);
}
return true;
}
catch (Exception e)
{
_log.Error(e);
return false;
}
}
}
}