Save Torch config on server start, remove concealment code (moved to plugin)
This commit is contained in:
@@ -52,7 +52,7 @@ namespace Torch.Server
|
||||
{
|
||||
_log.Info($"Generating default config at {configPath}");
|
||||
options = new TorchConfig();
|
||||
options.SaveTo(configPath);
|
||||
options.Save(configPath);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -6,9 +6,9 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using NLog;
|
||||
using VRage.Dedicated;
|
||||
using Sandbox.ModAPI.Ingame;
|
||||
|
||||
namespace Torch.Server
|
||||
namespace Torch
|
||||
{
|
||||
public class TorchConfig
|
||||
{
|
||||
@@ -19,13 +19,15 @@ namespace Torch.Server
|
||||
public int Autosave { get; set; }
|
||||
public bool AutoRestart { get; set; }
|
||||
public bool LogChat { get; set; }
|
||||
[NonSerialized]
|
||||
private string _path;
|
||||
|
||||
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.ApplicationData), "SpaceEngineersDedicated", InstanceName);
|
||||
InstancePath = instancePath ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Torch", InstanceName);
|
||||
Autosave = autosaveInterval;
|
||||
AutoRestart = autoRestart;
|
||||
}
|
||||
@@ -40,6 +42,7 @@ namespace Torch.Server
|
||||
{
|
||||
config = (TorchConfig)serializer.Deserialize(f);
|
||||
}
|
||||
config._path = path;
|
||||
return config;
|
||||
}
|
||||
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
|
||||
{
|
||||
var serializer = new XmlSerializer(typeof(TorchConfig));
|
||||
|
@@ -34,24 +34,22 @@ namespace Torch.Server
|
||||
{
|
||||
public Thread GameThread { get; private set; }
|
||||
public bool IsRunning { get; private set; }
|
||||
public string InstancePath { get; private set; }
|
||||
public string InstanceName { get; private set; }
|
||||
public TorchConfig Config { get; }
|
||||
public string InstanceName => Config?.InstanceName;
|
||||
public string InstancePath => Config?.InstancePath;
|
||||
|
||||
private readonly AutoResetEvent _stopHandle = new AutoResetEvent(false);
|
||||
|
||||
public TorchServer(TorchConfig options = null)
|
||||
public TorchServer(TorchConfig config = null)
|
||||
{
|
||||
var opt = options ?? new TorchConfig();
|
||||
|
||||
InstanceName = opt.InstanceName;
|
||||
InstancePath = opt.InstancePath;
|
||||
Config = config ?? new TorchConfig();
|
||||
}
|
||||
|
||||
public override void 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;
|
||||
MyPerGameSettings.SendLogToKeen = false;
|
||||
@@ -73,14 +71,6 @@ namespace Torch.Server
|
||||
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)
|
||||
{
|
||||
SetConfig(config);
|
||||
@@ -95,6 +85,7 @@ namespace Torch.Server
|
||||
if (IsRunning)
|
||||
throw new InvalidOperationException("Server is already running.");
|
||||
|
||||
Config.Save();
|
||||
IsRunning = true;
|
||||
Log.Info("Starting server.");
|
||||
|
||||
@@ -102,7 +93,7 @@ namespace Torch.Server
|
||||
Environment.SetEnvironmentVariable("SteamAppId", MyPerServerSettings.AppId.ToString());
|
||||
|
||||
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)
|
||||
{
|
||||
Log.Error("Error running server.");
|
||||
|
@@ -37,7 +37,7 @@ namespace Torch.Server
|
||||
if (File.Exists(configName))
|
||||
options = TorchConfig.LoadFrom(configName);
|
||||
else
|
||||
options.SaveTo(configName);
|
||||
options.Save(configName);
|
||||
|
||||
_server = new TorchServer(options);
|
||||
_server.Init();
|
||||
|
@@ -38,7 +38,7 @@ namespace Torch.Server
|
||||
|
||||
public TorchUI(TorchServer server)
|
||||
{
|
||||
_config = new TorchConfig();
|
||||
_config = server.Config;
|
||||
_server = server;
|
||||
InitializeComponent();
|
||||
_startTime = DateTime.Now;
|
||||
@@ -113,7 +113,6 @@ namespace Torch.Server
|
||||
{
|
||||
var name = (sender as TextBox).Text;
|
||||
|
||||
_server.SetInstance(null, name);
|
||||
_config.InstancePath = name;
|
||||
|
||||
LoadConfig(_config);
|
||||
|
@@ -38,7 +38,6 @@ namespace Torch.Managers
|
||||
public EntityManager(ITorchBase torch)
|
||||
{
|
||||
_torch = torch;
|
||||
_torch.SessionLoaded += () => InitConcealment(60000);
|
||||
}
|
||||
|
||||
public void ExportGrid(IMyCubeGrid grid, string path)
|
||||
@@ -58,212 +57,6 @@ namespace Torch.Managers
|
||||
grid.PositionComp.SetPosition(position);
|
||||
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
|
||||
@@ -281,80 +74,4 @@ namespace Torch.Managers
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -137,7 +137,6 @@
|
||||
<Compile Include="Managers\ScriptingManager.cs" />
|
||||
<Compile Include="TorchBase.cs" />
|
||||
<Compile Include="SteamService.cs" />
|
||||
<Compile Include="TorchConfig.cs" />
|
||||
<Compile Include="TorchPluginBase.cs" />
|
||||
<Compile Include="Updater\PluginUpdater.cs" />
|
||||
<Compile Include="ViewModels\ModViewModel.cs" />
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user