Fix NetworkManager, add more entity management, default command permission level to "Admin"
This commit is contained in:
71
Torch.Server/ViewModels/Entities/Blocks/BlockViewModel.cs
Normal file
71
Torch.Server/ViewModels/Entities/Blocks/BlockViewModel.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Text;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.Game.Entities.Cube;
|
||||
using Sandbox.ModAPI;
|
||||
using Sandbox.ModAPI.Interfaces;
|
||||
using Torch.Server.ViewModels.Entities;
|
||||
|
||||
namespace Torch.Server.ViewModels.Blocks
|
||||
{
|
||||
public class BlockViewModel : EntityViewModel
|
||||
{
|
||||
public IMyTerminalBlock Block { get; }
|
||||
public MTObservableCollection<PropertyViewModel> Properties { get; } = new MTObservableCollection<PropertyViewModel>();
|
||||
|
||||
public string FullName => $"{Block.CubeGrid.CustomName} - {Block.CustomName}";
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get => Block?.CustomName ?? "null";
|
||||
set
|
||||
{
|
||||
TorchBase.Instance.InvokeBlocking(() => Block.CustomName = value);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Position { get => base.Position; set { } }
|
||||
|
||||
public long BuiltBy
|
||||
{
|
||||
get => ((MySlimBlock)Block.SlimBlock).BuiltBy;
|
||||
set
|
||||
{
|
||||
TorchBase.Instance.InvokeBlocking(() => ((MySlimBlock)Block.SlimBlock).TransferAuthorship(value));
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanStop => false;
|
||||
|
||||
public BlockViewModel(IMyTerminalBlock block, EntityTreeViewModel tree) : base(block, tree)
|
||||
{
|
||||
Block = block;
|
||||
var propList = new List<ITerminalProperty>();
|
||||
block.GetProperties(propList);
|
||||
foreach (var prop in propList)
|
||||
{
|
||||
Type propType = null;
|
||||
foreach (var iface in prop.GetType().GetInterfaces())
|
||||
{
|
||||
if (iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(ITerminalProperty<>))
|
||||
propType = iface.GenericTypeArguments[0];
|
||||
}
|
||||
|
||||
var modelType = typeof(PropertyViewModel<>).MakeGenericType(propType);
|
||||
Properties.Add((PropertyViewModel)Activator.CreateInstance(modelType, prop, this));
|
||||
}
|
||||
}
|
||||
|
||||
public BlockViewModel()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Sandbox.Game.Entities.Cube;
|
||||
using Sandbox.ModAPI;
|
||||
using Sandbox.ModAPI.Interfaces;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using NLog;
|
||||
using Sandbox.ModAPI.Interfaces.Terminal;
|
||||
|
||||
namespace Torch.Server.ViewModels.Blocks
|
||||
{
|
||||
public static class BlockViewModelGenerator
|
||||
{
|
||||
private static Dictionary<Type, Type> _cache = new Dictionary<Type, Type>();
|
||||
private static AssemblyName _asmName;
|
||||
private static ModuleBuilder _mb;
|
||||
private static AssemblyBuilder _ab;
|
||||
private static Logger _log = LogManager.GetLogger("Generator");
|
||||
|
||||
static BlockViewModelGenerator()
|
||||
{
|
||||
_asmName = new AssemblyName("Torch.Server.ViewModels.Generated");
|
||||
_ab = AppDomain.CurrentDomain.DefineDynamicAssembly(_asmName, AssemblyBuilderAccess.RunAndSave);
|
||||
_mb = _ab.DefineDynamicModule(_asmName.Name);
|
||||
}
|
||||
|
||||
public static void GenerateModels()
|
||||
{
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.IsDynamic))
|
||||
{
|
||||
foreach (var type in assembly.ExportedTypes.Where(t => t.IsSubclassOf(typeof(MyTerminalBlock))))
|
||||
{
|
||||
GenerateModel(type);
|
||||
}
|
||||
}
|
||||
_ab.Save("Generated.dll", PortableExecutableKinds.ILOnly, ImageFileMachine.AMD64);
|
||||
}
|
||||
|
||||
public static Type GenerateModel(Type blockType, bool force = false)
|
||||
{
|
||||
if (_cache.ContainsKey(blockType) && !force)
|
||||
return _cache[blockType];
|
||||
|
||||
var propertyList = new List<ITerminalProperty>();
|
||||
MyTerminalControlFactoryHelper.Static.GetProperties(blockType, propertyList);
|
||||
|
||||
var getPropertyMethod = blockType.GetMethod("GetProperty", new[] {typeof(string)});
|
||||
var getValueMethod = typeof(ITerminalProperty<>).GetMethod("GetValue");
|
||||
var setValueMethod = typeof(ITerminalProperty<>).GetMethod("SetValue");
|
||||
var tb = _mb.DefineType($"{_asmName.Name}.{blockType.Name}ViewModel", TypeAttributes.Class | TypeAttributes.Public);
|
||||
var blockField = tb.DefineField("_block", blockType, FieldAttributes.Private);
|
||||
|
||||
var ctor = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] {blockType});
|
||||
var ctorIl = ctor.GetILGenerator();
|
||||
ctorIl.Emit(OpCodes.Ldarg_0);
|
||||
ctorIl.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
|
||||
ctorIl.Emit(OpCodes.Ldarg_0);
|
||||
ctorIl.Emit(OpCodes.Ldarg_1);
|
||||
ctorIl.Emit(OpCodes.Stfld, blockField);
|
||||
ctorIl.Emit(OpCodes.Ret);
|
||||
|
||||
for (var i = 0; i < propertyList.Count; i++)
|
||||
{
|
||||
var prop = propertyList[i];
|
||||
var propType = prop.GetType();
|
||||
|
||||
Type propGenericArg = null;
|
||||
|
||||
foreach (var iface in propType.GetInterfaces())
|
||||
{
|
||||
if (iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(ITerminalProperty<>))
|
||||
propGenericArg = iface.GenericTypeArguments[0];
|
||||
}
|
||||
|
||||
if (propGenericArg == null)
|
||||
{
|
||||
_log.Error($"Property {prop.Id} does not implement {typeof(ITerminalProperty<>).Name}");
|
||||
return null;
|
||||
}
|
||||
|
||||
_log.Info($"GENERIC ARG: {propGenericArg.Name}");
|
||||
|
||||
var pb = tb.DefineProperty($"{prop.Id}", PropertyAttributes.HasDefault, propGenericArg, null);
|
||||
var getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
|
||||
|
||||
var getter = tb.DefineMethod($"get_{prop.Id}", getSetAttr, propGenericArg, Type.EmptyTypes);
|
||||
{
|
||||
var getterIl = getter.GetILGenerator();
|
||||
var propLoc = getterIl.DeclareLocal(propType);
|
||||
getterIl.Emit(OpCodes.Ldarg_0);
|
||||
getterIl.Emit(OpCodes.Ldfld, blockField);
|
||||
getterIl.Emit(OpCodes.Ldstr, prop.Id);
|
||||
getterIl.EmitCall(OpCodes.Callvirt, getPropertyMethod, null);
|
||||
getterIl.Emit(OpCodes.Stloc, propLoc);
|
||||
getterIl.Emit(OpCodes.Ldloc, propLoc);
|
||||
getterIl.Emit(OpCodes.Ldarg_0);
|
||||
getterIl.Emit(OpCodes.Ldfld, blockField);
|
||||
getterIl.EmitCall(OpCodes.Callvirt, getValueMethod, null);
|
||||
getterIl.Emit(OpCodes.Ret);
|
||||
pb.SetGetMethod(getter);
|
||||
}
|
||||
|
||||
var setter = tb.DefineMethod($"set_{prop.Id}", getSetAttr, null, Type.EmptyTypes);
|
||||
{
|
||||
var setterIl = setter.GetILGenerator();
|
||||
var propLoc = setterIl.DeclareLocal(propType);
|
||||
setterIl.Emit(OpCodes.Ldarg_0);
|
||||
setterIl.Emit(OpCodes.Stfld, blockField);
|
||||
setterIl.EmitCall(OpCodes.Callvirt, getPropertyMethod, null);
|
||||
setterIl.Emit(OpCodes.Stloc, propLoc);
|
||||
setterIl.Emit(OpCodes.Ldarg_1);
|
||||
setterIl.Emit(OpCodes.Ldarg_0);
|
||||
setterIl.Emit(OpCodes.Ldfld, blockField);
|
||||
setterIl.EmitCall(OpCodes.Callvirt, setValueMethod, null);
|
||||
setterIl.Emit(OpCodes.Ret);
|
||||
pb.SetSetMethod(setter);
|
||||
}
|
||||
}
|
||||
|
||||
var vmType = tb.CreateType();
|
||||
_cache.Add(blockType, vmType);
|
||||
return vmType;
|
||||
}
|
||||
}
|
||||
}
|
49
Torch.Server/ViewModels/Entities/Blocks/PropertyViewModel.cs
Normal file
49
Torch.Server/ViewModels/Entities/Blocks/PropertyViewModel.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.ModAPI;
|
||||
using Sandbox.ModAPI.Interfaces;
|
||||
|
||||
namespace Torch.Server.ViewModels.Blocks
|
||||
{
|
||||
public class PropertyViewModel<T> : PropertyViewModel
|
||||
{
|
||||
private readonly ITerminalProperty<T> _prop;
|
||||
public string Name { get; }
|
||||
public Type PropertyType => typeof(T);
|
||||
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
var val = default(T);
|
||||
TorchBase.Instance.InvokeBlocking(() => val = _prop.GetValue(Block.Block));
|
||||
return val;
|
||||
}
|
||||
set
|
||||
{
|
||||
TorchBase.Instance.InvokeBlocking(() => _prop.SetValue(Block.Block, value));
|
||||
OnPropertyChanged();
|
||||
Block.RefreshModel();
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyViewModel(ITerminalProperty<T> property, BlockViewModel blockViewModel) : base(blockViewModel)
|
||||
{
|
||||
Name = property.Id;
|
||||
_prop = property;
|
||||
}
|
||||
}
|
||||
|
||||
public class PropertyViewModel : ViewModel
|
||||
{
|
||||
protected readonly BlockViewModel Block;
|
||||
|
||||
public PropertyViewModel(BlockViewModel blockViewModel)
|
||||
{
|
||||
Block = blockViewModel;
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,7 +4,7 @@ namespace Torch.Server.ViewModels.Entities
|
||||
{
|
||||
public class CharacterViewModel : EntityViewModel
|
||||
{
|
||||
public CharacterViewModel(MyCharacter character) : base(character)
|
||||
public CharacterViewModel(MyCharacter character, EntityTreeViewModel tree) : base(character, tree)
|
||||
{
|
||||
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ namespace Torch.Server.ViewModels.Entities
|
||||
{
|
||||
public class EntityViewModel : ViewModel
|
||||
{
|
||||
protected EntityTreeViewModel Tree { get; }
|
||||
public IMyEntity Entity { get; }
|
||||
public long Id => Entity.EntityId;
|
||||
|
||||
@@ -36,7 +37,7 @@ namespace Torch.Server.ViewModels.Entities
|
||||
|
||||
public virtual bool CanDelete => !(Entity is IMyCharacter);
|
||||
|
||||
public EntityViewModel(IMyEntity entity)
|
||||
public EntityViewModel(IMyEntity entity, EntityTreeViewModel tree)
|
||||
{
|
||||
Entity = entity;
|
||||
}
|
||||
|
14
Torch.Server/ViewModels/Entities/FloatingObjectViewModel.cs
Normal file
14
Torch.Server/ViewModels/Entities/FloatingObjectViewModel.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Sandbox.Game.Entities;
|
||||
using Torch.Server.ViewModels.Entities;
|
||||
|
||||
namespace Torch.Server.ViewModels
|
||||
{
|
||||
public class FloatingObjectViewModel : EntityViewModel
|
||||
{
|
||||
private MyFloatingObject Floating => (MyFloatingObject)Entity;
|
||||
|
||||
public override string Name => $"{base.Name} ({Floating.Amount})";
|
||||
|
||||
public FloatingObjectViewModel(MyFloatingObject floating, EntityTreeViewModel tree) : base(floating, tree) { }
|
||||
}
|
||||
}
|
@@ -11,15 +11,17 @@ namespace Torch.Server.ViewModels.Entities
|
||||
public MTObservableCollection<BlockViewModel> Blocks { get; } = new MTObservableCollection<BlockViewModel>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => $"{base.Name} ({Grid.BlocksCount} blocks)";
|
||||
public string DescriptiveName => $"{Name} ({Grid.BlocksCount} blocks)";
|
||||
|
||||
public GridViewModel(MyCubeGrid grid) : base(grid)
|
||||
public GridViewModel() { }
|
||||
|
||||
public GridViewModel(MyCubeGrid grid, EntityTreeViewModel tree) : base(grid, tree)
|
||||
{
|
||||
TorchBase.Instance.InvokeBlocking(() =>
|
||||
{
|
||||
foreach (var block in grid.GetFatBlocks().Where(b => b is IMyTerminalBlock))
|
||||
{
|
||||
Blocks.Add(new BlockViewModel((IMyTerminalBlock)block));
|
||||
Blocks.Add(new BlockViewModel((IMyTerminalBlock)block, tree));
|
||||
}
|
||||
});
|
||||
Blocks.Sort(b => b.Block.GetType().AssemblyQualifiedName);
|
||||
@@ -39,8 +41,9 @@ namespace Torch.Server.ViewModels.Entities
|
||||
|
||||
private void Grid_OnBlockAdded(Sandbox.Game.Entities.Cube.MySlimBlock obj)
|
||||
{
|
||||
if (obj.FatBlock != null)
|
||||
Blocks.Add(new BlockViewModel((IMyTerminalBlock)obj.FatBlock));
|
||||
var block = obj.FatBlock as IMyTerminalBlock;
|
||||
if (block != null)
|
||||
Blocks.Add(new BlockViewModel(block, Tree));
|
||||
|
||||
Blocks.Sort(b => b.Block.GetType().AssemblyQualifiedName);
|
||||
OnPropertyChanged(nameof(Name));
|
||||
|
@@ -1,4 +1,9 @@
|
||||
using Sandbox.Game.Entities;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Sandbox.Game.Entities;
|
||||
using VRage.Game.Entity;
|
||||
using VRage.Game.ModAPI;
|
||||
using VRage.Library.Collections;
|
||||
|
||||
namespace Torch.Server.ViewModels.Entities
|
||||
{
|
||||
@@ -10,6 +15,35 @@ namespace Torch.Server.ViewModels.Entities
|
||||
|
||||
public override bool CanStop => false;
|
||||
|
||||
public VoxelMapViewModel(MyVoxelBase e) : base(e) { }
|
||||
public MTObservableCollection<GridViewModel> AttachedGrids { get; } = new MTObservableCollection<GridViewModel>();
|
||||
|
||||
public void UpdateAttachedGrids()
|
||||
{
|
||||
AttachedGrids.Clear();
|
||||
var box = Entity.WorldAABB;
|
||||
var entities = new List<MyEntity>();
|
||||
MyGamePruningStructure.GetTopMostEntitiesInBox(ref box, entities, MyEntityQueryType.Static);
|
||||
foreach (var entity in entities.Where(e => e is IMyCubeGrid))
|
||||
{
|
||||
var gridModel = Tree.Grids.FirstOrDefault(g => g.Entity.EntityId == entity.EntityId);
|
||||
if (gridModel == null)
|
||||
{
|
||||
gridModel = new GridViewModel((MyCubeGrid)entity, Tree);
|
||||
Tree.Grids.Add(gridModel);
|
||||
}
|
||||
|
||||
AttachedGrids.Add(gridModel);
|
||||
}
|
||||
}
|
||||
|
||||
public VoxelMapViewModel(MyVoxelBase e, EntityTreeViewModel tree) : base(e, tree)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public VoxelMapViewModel()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user