mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-01 17:47:24 +02:00
217 lines
7.6 KiB
C#
217 lines
7.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.Log;
|
|
using Robust.Shared.Prototypes;
|
|
using Robust.Shared.Reflection;
|
|
using Robust.Shared.Utility;
|
|
using Robust.Shared.ViewVariables;
|
|
using static Robust.Shared.ViewVariables.ViewVariablesBlobMembers;
|
|
|
|
namespace Robust.Server.ViewVariables.Traits
|
|
{
|
|
internal sealed class ViewVariablesTraitMembers : ViewVariablesTrait
|
|
{
|
|
private readonly List<MemberInfo> _members = new();
|
|
private readonly ISawmill _logger;
|
|
|
|
public ViewVariablesTraitMembers(IViewVariablesSession session, ISawmill logger) : base(session)
|
|
{
|
|
_logger = logger;
|
|
}
|
|
|
|
public override ViewVariablesBlob? DataRequest(ViewVariablesRequest messageRequestMeta)
|
|
{
|
|
if (messageRequestMeta is ViewVariablesRequestMembers)
|
|
{
|
|
var members = new List<(MemberData mData, MemberInfo mInfo)>();
|
|
var obj = Session.Object;
|
|
var objType = Session.ObjectType;
|
|
|
|
foreach (var property in objType.GetAllProperties())
|
|
{
|
|
if (!ViewVariablesUtility.TryGetViewVariablesAccess(property, out var access))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!property.IsBasePropertyDefinition())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
members.Add((new MemberData
|
|
{
|
|
Editable = access == VVAccess.ReadWrite,
|
|
Name = property.Name,
|
|
Type = property.PropertyType.AssemblyQualifiedName,
|
|
TypePretty = PrettyPrint.PrintUserFacingTypeShort(property.PropertyType, 2),
|
|
Value = property.GetValue(Session.Object),
|
|
PropertyIndex = _members.Count
|
|
}, property));
|
|
_members.Add(property);
|
|
}
|
|
|
|
foreach (var field in objType.GetAllFields())
|
|
{
|
|
if (!ViewVariablesUtility.TryGetViewVariablesAccess(field, out var access))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
members.Add((new MemberData
|
|
{
|
|
Editable = access == VVAccess.ReadWrite,
|
|
Name = field.Name,
|
|
Type = field.FieldType.AssemblyQualifiedName,
|
|
TypePretty = PrettyPrint.PrintUserFacingTypeShort(field.FieldType, 2),
|
|
Value = field.GetValue(obj),
|
|
PropertyIndex = _members.Count
|
|
}, field));
|
|
|
|
_members.Add(field);
|
|
}
|
|
|
|
foreach (var (mData, mInfo) in members)
|
|
{
|
|
mData.Value = MakeValueNetSafe(mData.Value) ?? MakeNullValueNetSafe(mInfo.GetUnderlyingType());
|
|
}
|
|
|
|
var dataList = members
|
|
.OrderBy(p => p.mData.Name)
|
|
.GroupBy(p => p.mInfo.DeclaringType!)
|
|
.OrderByDescending(g => g.Key, TypeHelpers.TypeInheritanceComparer)
|
|
.Select(g =>
|
|
(
|
|
TypeAbbreviation.Abbreviate(g.Key),
|
|
g.Select(d => d.mData).ToList()
|
|
))
|
|
.ToList();
|
|
|
|
return new ViewVariablesBlobMembers
|
|
{
|
|
MemberGroups = dataList
|
|
};
|
|
}
|
|
|
|
if (messageRequestMeta is ViewVariablesRequestAllPrototypes protoReq)
|
|
{
|
|
var list = new List<string>();
|
|
|
|
foreach (var prototype in IoCManager.Resolve<IPrototypeManager>().EnumeratePrototypes(protoReq.Variant))
|
|
{
|
|
list.Add(prototype.ID);
|
|
}
|
|
|
|
return new ViewVariablesBlobAllPrototypes()
|
|
{
|
|
Variant = protoReq.Variant,
|
|
Prototypes = list,
|
|
};
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public override bool TryGetRelativeObject(object property, out object? value)
|
|
{
|
|
if (property is not ViewVariablesMemberSelector selector)
|
|
{
|
|
return base.TryGetRelativeObject(property, out value);
|
|
}
|
|
|
|
if (selector.Index > _members.Count)
|
|
{
|
|
value = default;
|
|
return false;
|
|
}
|
|
|
|
var member = _members[selector.Index];
|
|
switch (member)
|
|
{
|
|
case PropertyInfo propertyInfo:
|
|
try
|
|
{
|
|
value = propertyInfo.GetValue(Session.Object);
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.Error("Exception while getting property {0} on session {1} object {2}: {3}",
|
|
propertyInfo.Name, Session.SessionId, Session.Object, e);
|
|
value = default;
|
|
return false;
|
|
}
|
|
|
|
case FieldInfo field:
|
|
try
|
|
{
|
|
value = field.GetValue(Session.Object);
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.Error("Exception while modifying field {0} on session {1} object {2}: {3}",
|
|
field.Name, Session.SessionId, Session.Object, e);
|
|
value = default;
|
|
return false;
|
|
}
|
|
|
|
default:
|
|
throw new InvalidOperationException();
|
|
}
|
|
}
|
|
|
|
public override bool TryModifyProperty(object[] property, object value)
|
|
{
|
|
if (!(property[0] is ViewVariablesMemberSelector selector))
|
|
{
|
|
return base.TryModifyProperty(property, value);
|
|
}
|
|
|
|
if (selector.Index >= _members.Count)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var member = _members[selector.Index];
|
|
|
|
switch (member)
|
|
{
|
|
case PropertyInfo propertyInfo:
|
|
try
|
|
{
|
|
propertyInfo.GetSetMethod(true)!.Invoke(Session.Object, new[] {value});
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.Error("Exception while modifying property {0} on session {1} object {2}: {3}",
|
|
propertyInfo.Name, Session.SessionId, Session.Object, e);
|
|
return false;
|
|
}
|
|
|
|
case FieldInfo field:
|
|
try
|
|
{
|
|
field.SetValue(Session.Object, value);
|
|
Session.ObjectChangeDelegate?.Invoke(Session.Object);
|
|
|
|
return true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.Error("Exception while modifying field {0} on session {1} object {2}: {3}",
|
|
field.Name, Session.SessionId, Session.Object, e);
|
|
return false;
|
|
}
|
|
|
|
default:
|
|
throw new InvalidOperationException();
|
|
}
|
|
}
|
|
}
|
|
}
|