3 using Microsoft.Xna.Framework;
5 using System.Collections.Generic;
6 using System.Collections.Immutable;
7 using System.ComponentModel;
8 using System.Globalization;
10 using System.Reflection;
11 using System.Xml.Linq;
21 [AttributeUsage(AttributeTargets.Property)]
43 public Serialize(
object defaultValue,
IsPropertySaveable isSaveable,
string description =
"",
string translationTextTag =
"",
bool alwaysUseInstanceValues =
false)
53 [AttributeUsage(AttributeTargets.Property)]
54 public sealed
class Header : Attribute
58 public Header(
string text =
"",
string localizedTextTag =
null)
60 Text = localizedTextTag !=
null ? TextManager.Get(localizedTextTag) : text;
66 private static readonly ImmutableDictionary<Type, string> supportedTypes =
new Dictionary<Type, string>
68 { typeof(
bool),
"bool" },
69 { typeof(
int),
"int" },
70 { typeof(
float),
"float" },
71 { typeof(
string),
"string" },
72 { typeof(Identifier),
"identifier" },
75 { typeof(Point),
"point" },
76 { typeof(Vector2),
"vector2" },
77 { typeof(Vector3),
"vector3" },
78 { typeof(Vector4),
"vector4" },
80 { typeof(Color),
"color" },
81 { typeof(
string[]),
"stringarray" },
82 { typeof(Identifier[]),
"identifierarray" }
83 }.ToImmutableDictionary();
85 private static readonly Dictionary<Type, Dictionary<Identifier, SerializableProperty>> cachedProperties =
86 new Dictionary<Type, Dictionary<Identifier, SerializableProperty>>();
87 public readonly
string Name;
98 PropertyInfo =
property.ComponentType.GetProperty(property.Name);
108 if (a is T)
return (T)a;
114 public void SetValue(
object parentObject,
object val)
121 if (value ==
null) {
return false; }
123 if (!supportedTypes.TryGetValue(
PropertyType, out
string typeName))
130 enumVal = Enum.Parse(
PropertyInfo.PropertyType, value,
true);
134 DebugConsole.ThrowError($
"Failed to set the value of the property \"{Name}\" of \"{parentObject}\" to {value} (not a valid {PropertyInfo.PropertyType})", e);
143 DebugConsole.ThrowError($
"Failed to set the value of the property \"{Name}\" of \"{parentObject}\" to {value}", e);
149 DebugConsole.ThrowError($
"Failed to set the value of the property \"{Name}\" of \"{parentObject}\" to {value} (Type \"{PropertyType.Name}\" not supported)");
160 bool boolValue = value.ToIdentifier() ==
"true";
161 if (TrySetBoolValueWithoutReflection(parentObject, boolValue)) {
return true; }
165 if (
int.TryParse(value, out
int intVal))
167 if (TrySetFloatValueWithoutReflection(parentObject, intVal)) {
return true; }
176 if (
float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out
float floatVal))
178 if (TrySetFloatValueWithoutReflection(parentObject, floatVal)) {
return true; }
190 PropertyInfo.SetValue(parentObject, XMLExtensions.ParsePoint(value));
193 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseVector2(value));
196 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseVector3(value));
199 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseVector4(value));
202 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseColor(value));
205 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseRect(value,
true));
208 PropertyInfo.SetValue(parentObject, value.ToIdentifier());
210 case "languageidentifier":
211 PropertyInfo.SetValue(parentObject, value.ToLanguageIdentifier());
213 case "localizedstring":
217 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseStringArray(value));
219 case "identifierarray":
220 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseIdentifierArray(value));
226 DebugConsole.ThrowError($
"Failed to set the value of the property \"{Name}\" of \"{parentObject}\" to {value}", e);
234 if (value ==
null || parentObject ==
null ||
PropertyInfo ==
null)
return false;
238 if (!supportedTypes.TryGetValue(
PropertyType, out
string typeName))
245 enumVal = Enum.Parse(
PropertyInfo.PropertyType, value.ToString(),
true);
249 DebugConsole.ThrowError(
250 $
"Failed to set the value of the property \"{Name}\" of \"{parentObject}\" to {value} (not a valid {PropertyInfo.PropertyType})", e);
258 DebugConsole.ThrowError($
"Failed to set the value of the property \"{Name}\" of \"{parentObject}\" to {value} (Type \"{PropertyType.Name}\" not supported)");
266 if (value.GetType() == typeof(
string))
274 PropertyInfo.SetValue(parentObject, XMLExtensions.ParsePoint((
string)value));
277 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseVector2((
string)value));
280 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseVector3((
string)value));
283 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseVector4((
string)value));
286 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseColor((
string)value));
289 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseRect((
string)value,
false));
292 PropertyInfo.SetValue(parentObject,
new Identifier((
string)value));
294 case "languageidentifier":
295 PropertyInfo.SetValue(parentObject, ((
string)value).ToLanguageIdentifier());
297 case "localizedstring":
301 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseStringArray((
string)value));
303 case "identifierarray":
304 PropertyInfo.SetValue(parentObject, XMLExtensions.ParseIdentifierArray((
string)value));
307 DebugConsole.ThrowError($
"Failed to set the value of the property \"{Name}\" of \"{parentObject}\" to {value}");
308 DebugConsole.ThrowError($
"(Cannot convert a string to a {PropertyType})");
314 DebugConsole.ThrowError($
"Failed to set the value of the property \"{Name}\" of \"{parentObject}\" to {value}");
315 DebugConsole.ThrowError(
"(Non-matching type, should be " +
PropertyType +
" instead of " + value.GetType() +
")");
324 DebugConsole.ThrowError($
"Failed to set the value of the property \"{Name}\" of \"{parentObject}\" to {value}", e);
332 DebugConsole.ThrowError($
"Error in SerializableProperty.TrySetValue (Property: {PropertyInfo.Name})", e);
341 if (TrySetFloatValueWithoutReflection(parentObject, value)) {
return true; }
344 catch (TargetInvocationException e)
346 DebugConsole.ThrowError(
"Exception thrown by the target of SerializableProperty.TrySetValue", e.InnerException);
351 DebugConsole.ThrowError($
"Error in SerializableProperty.TrySetValue (Property: {PropertyInfo.Name})", e);
362 if (TrySetBoolValueWithoutReflection(parentObject, value)) {
return true; }
365 catch (TargetInvocationException e)
367 DebugConsole.ThrowError(
"Exception thrown by the target of SerializableProperty.TrySetValue", e.InnerException);
372 DebugConsole.ThrowError($
"Error in SerializableProperty.TrySetValue (Property: {PropertyInfo.Name})", e);
382 if (TrySetFloatValueWithoutReflection(parentObject, value)) {
return true; }
385 catch (TargetInvocationException e)
387 DebugConsole.ThrowError(
"Exception thrown by the target of SerializableProperty.TrySetValue", e.InnerException);
392 DebugConsole.ThrowError($
"Error in SerializableProperty.TrySetValue (Property: {PropertyInfo.Name})", e);
400 if (parentObject ==
null ||
PropertyInfo ==
null) {
return false; }
402 var value = TryGetValueWithoutReflection(parentObject);
403 if (value !=
null) {
return value; }
409 catch (TargetInvocationException e)
411 DebugConsole.ThrowError(
"Exception thrown by the target of SerializableProperty.GetValue", e.InnerException);
416 DebugConsole.ThrowError(
"Error in SerializableProperty.GetValue", e);
423 if (parentObject ==
null ||
PropertyInfo ==
null) {
return 0.0f; }
425 if (TryGetFloatValueWithoutReflection(parentObject, out
float value))
438 return (
float)
PropertyInfo.GetValue(parentObject,
null);
441 catch (TargetInvocationException e)
443 DebugConsole.ThrowError(
"Exception thrown by the target of SerializableProperty.GetValue", e.InnerException);
448 DebugConsole.ThrowError(
"Error in SerializableProperty.GetValue", e);
455 if (parentObject ==
null ||
PropertyInfo ==
null) {
return false; }
457 if (TryGetBoolValueWithoutReflection(parentObject, out
bool value))
466 catch (TargetInvocationException e)
468 DebugConsole.ThrowError(
"Exception thrown by the target of SerializableProperty.GetValue", e.InnerException);
473 DebugConsole.ThrowError(
"Error in SerializableProperty.GetValue", e);
480 if (type.IsEnum) {
return "Enum"; }
481 if (!supportedTypes.TryGetValue(type, out
string typeName))
488 private readonly ImmutableDictionary<Identifier, Func<object, object>> valueGetters =
489 new Dictionary<Identifier, Func<object, object>>()
491 {
"Voltage".ToIdentifier(), (obj) => obj is
Powered p ? p.
Voltage : (
object)
null},
495 {
"FissionRate".ToIdentifier(), (obj) => obj is
Reactor r ? r.
FissionRate : (
object)
null},
496 {
"OxygenFlow".ToIdentifier(), (obj) => obj is
Vent v ? v.
OxygenFlow : (
object)
null},
498 "CurrFlow".ToIdentifier(),
503 {
"CurrentVolume".ToIdentifier(), (obj) => obj is
Engine e ? e.
CurrentVolume : (
object)
null},
505 {
"Oxygen".ToIdentifier(), (obj) => obj is Character c ? c.Oxygen : (
object)
null},
506 {
"Health".ToIdentifier(), (obj) => obj is Character c ? c.Health : (
object)
null},
507 {
"OxygenAvailable".ToIdentifier(), (obj) => obj is Character c ? c.OxygenAvailable : (
object)
null},
508 {
"PressureProtection".ToIdentifier(), (obj) => obj is Character c ? c.PressureProtection : (
object)
null},
509 {
"IsDead".ToIdentifier(), (obj) => obj is Character c ? c.IsDead : (
object)
null},
510 {
"IsHuman".ToIdentifier(), (obj) => obj is Character c ? c.IsHuman : (
object)
null},
512 {
"Condition".ToIdentifier(), (obj) => obj is Item i ? i.Condition : (
object)
null},
513 {
"ContainerIdentifier".ToIdentifier(), (obj) => obj is Item i ? i.ContainerIdentifier : (
object)
null},
514 {
"PhysicsBodyActive".ToIdentifier(), (obj) => obj is Item i ? i.PhysicsBodyActive : (
object)
null},
515 }.ToImmutableDictionary();
520 private object TryGetValueWithoutReflection(
object parentObject)
524 if (TryGetFloatValueWithoutReflection(parentObject, out
float value)) {
return value; }
528 if (TryGetBoolValueWithoutReflection(parentObject, out
bool value)) {
return value; }
532 if (TryGetStringValueWithoutReflection(parentObject, out
string value)) {
return value; }
540 private bool TryGetFloatValueWithoutReflection(
object parentObject, out
float value)
547 if (parentObject is
Powered powered) { value = powered.Voltage;
return true; }
552 if (parentObject is
Powered powered) { value = powered.RelativeVoltage;
return true; }
557 if (parentObject is
Powered powered) { value = powered.CurrPowerConsumption;
return true; }
562 if (parentObject is
PowerContainer powerContainer) { value = powerContainer.Charge;
return true; }
567 if (parentObject is
PowerContainer powerContainer) { value = powerContainer.ChargePercentage;
return true; }
572 if (parentObject is
PowerContainer powerContainer) { value = powerContainer.RechargeRatio;
return true; }
576 {
if (parentObject is
Reactor reactor) { value = reactor.AvailableFuel;
return true; } }
579 {
if (parentObject is
Reactor reactor) { value = reactor.FissionRate;
return true; } }
582 {
if (parentObject is
Reactor reactor) { value = reactor.Temperature;
return true; } }
585 if (parentObject is
Vent vent) { value = vent.OxygenFlow;
return true; }
588 {
if (parentObject is
Pump pump) { value = pump.CurrFlow;
return true; } }
589 if (parentObject is
OxygenGenerator oxygenGenerator) { value = oxygenGenerator.CurrFlow;
return true; }
592 {
if (parentObject is
Engine engine) { value = engine.CurrentBrokenVolume;
return true; } }
593 {
if (parentObject is
Pump pump) { value = pump.CurrentBrokenVolume;
return true; } }
596 {
if (parentObject is
Engine engine) { value = engine.CurrentVolume;
return true; } }
599 {
if (parentObject is Character character) { value = character.Oxygen;
return true; } }
600 {
if (parentObject is Hull hull) { value = hull.Oxygen;
return true; } }
603 {
if (parentObject is Character character) { value = character.Health;
return true; } }
606 {
if (parentObject is Character character) { value = character.OxygenAvailable;
return true; } }
608 case nameof(
Character.PressureProtection):
609 {
if (parentObject is Character character) { value = character.PressureProtection;
return true; } }
611 case nameof(
Item.Condition):
612 {
if (parentObject is Item item) { value = item.Condition;
return true; } }
615 {
if (parentObject is Character character) { value = character.SpeedMultiplier;
return true; } }
617 case nameof(
Character.PropulsionSpeedMultiplier):
618 {
if (parentObject is Character character) { value = character.PropulsionSpeedMultiplier;
return true; } }
620 case nameof(
Character.LowPassMultiplier):
621 {
if (parentObject is Character character) { value = character.LowPassMultiplier;
return true; } }
623 case nameof(
Character.HullOxygenPercentage):
625 if (parentObject is Character character)
627 value = character.HullOxygenPercentage;
630 else if (parentObject is Item item)
632 value = item.HullOxygenPercentage;
638 {
if (parentObject is
Door door) { value = door.Stuck;
return true; } }
647 private bool TryGetBoolValueWithoutReflection(
object parentObject, out
bool value)
653 if (parentObject is
ItemComponent ic) { value = ic.IsActive;
return true; }
656 if (parentObject is
PowerTransfer powerTransfer) { value = powerTransfer.Overload;
return true; }
659 if (parentObject is
MotionSensor motionSensor) { value = motionSensor.MotionDetected;
return true; }
662 {
if (parentObject is Character character) { value = character.IsDead;
return true; } }
665 {
if (parentObject is Character character) { value = character.IsHuman;
return true; } }
668 {
if (parentObject is
LightComponent lightComponent) { value = lightComponent.IsOn;
return true; } }
670 case nameof(
Item.PhysicsBodyActive):
672 if (parentObject is Item item) { value = item.PhysicsBodyActive;
return true; }
676 if (parentObject is
DockingPort dockingPort) { value = dockingPort.Docked;
return true; }
679 if (parentObject is
Reactor reactor) { value = reactor.TemperatureCritical;
return true; }
682 if (parentObject is
TriggerComponent trigger) { value = trigger.TriggerActive;
return true; }
685 if (parentObject is
Controller controller) { value = controller.State;
return true; }
689 if (parentObject is Character character)
691 value = character.InWater;
694 else if (parentObject is Item item)
696 value = item.InWater;
702 if (parentObject is
Rope rope) { value = rope.Snapped;
return true; }
711 private bool TryGetStringValueWithoutReflection(
object parentObject, out
string value)
716 case nameof(
Item.ContainerIdentifier):
718 if (parentObject is Item item) { value = item.ContainerIdentifier.Value;
return true; }
728 private bool TrySetFloatValueWithoutReflection(
object parentObject,
float value)
732 case nameof(
Item.Condition):
733 {
if (parentObject is Item item) { item.Condition = value;
return true; } }
736 if (parentObject is
Powered powered) { powered.Voltage = value;
return true; }
739 if (parentObject is
PowerContainer powerContainer) { powerContainer.Charge = value;
return true; }
742 if (parentObject is
Reactor reactor) { reactor.AvailableFuel = value;
return true; }
745 {
if (parentObject is Character character) { character.Oxygen = value;
return true; } }
748 {
if (parentObject is Character character) { character.OxygenAvailable = value;
return true; } }
750 case nameof(
Character.PressureProtection):
751 {
if (parentObject is Character character) { character.PressureProtection = value;
return true; } }
753 case nameof(
Character.LowPassMultiplier):
754 {
if (parentObject is Character character) { character.LowPassMultiplier = value;
return true; } }
757 {
if (parentObject is Character character) { character.StackSpeedMultiplier(value);
return true; } }
760 {
if (parentObject is Character character) { character.StackHealthMultiplier(value);
return true; } }
762 case nameof(
Character.PropulsionSpeedMultiplier):
763 {
if (parentObject is Character character) { character.PropulsionSpeedMultiplier = value;
return true; } }
765 case nameof(
Character.ObstructVisionAmount):
766 {
if (parentObject is Character character) { character.ObstructVisionAmount = value;
return true; } }
768 case nameof(
Item.Scale):
769 {
if (parentObject is Item item) { item.Scale = value;
return true; } }
777 private bool TrySetBoolValueWithoutReflection(
object parentObject,
bool value)
782 {
if (parentObject is Character character) { character.ObstructVision = value;
return true; } }
785 {
if (parentObject is Character character) { character.HideFace = value;
return true; } }
788 {
if (parentObject is Character character) { character.UseHullOxygen = value;
return true; } }
791 {
if (parentObject is
LightComponent lightComponent) { lightComponent.IsOn = value;
return true; } }
794 {
if (parentObject is
ItemComponent ic) { ic.IsActive = value;
return true; } }
802 List<SerializableProperty> editableProperties =
new List<SerializableProperty>();
803 foreach (var property
in obj.SerializableProperties.Values)
805 if (property.Attributes.OfType<T>().Any()) editableProperties.Add(property);
808 return editableProperties;
811 public static Dictionary<Identifier, SerializableProperty>
GetProperties(
object obj)
813 Type objType = obj.GetType();
814 if (cachedProperties.ContainsKey(objType))
816 return cachedProperties[objType];
819 var properties = TypeDescriptor.GetProperties(obj.GetType()).Cast<PropertyDescriptor>();
820 Dictionary<Identifier, SerializableProperty> dictionary =
new Dictionary<Identifier, SerializableProperty>();
821 foreach (var property
in properties)
824 dictionary.Add(serializableProperty.Name.ToIdentifier(), serializableProperty);
827 cachedProperties[objType] = dictionary;
832 public static Dictionary<Identifier, SerializableProperty>
DeserializeProperties(
object obj, XElement element =
null)
834 Dictionary<Identifier, SerializableProperty> dictionary =
GetProperties(obj);
836 foreach (var property
in dictionary.Values)
839 foreach (var ini
in property.Attributes.OfType<
Serialize>())
841 property.TrySetValue(obj, ini.DefaultValue);
850 foreach (XAttribute attribute
in element.Attributes())
852 if (!dictionary.TryGetValue(attribute.NameAsIdentifier(), out
SerializableProperty property)) {
continue; }
853 if (!property.Attributes.OfType<
Serialize>().Any()) {
continue; }
854 property.TrySetValue(obj, attribute.Value);
863 var saveProperties = GetProperties<Serialize>(obj);
864 foreach (var property
in saveProperties)
866 object value =
property.GetValue(obj);
867 if (value ==
null)
continue;
875 foreach (var attribute
in property.Attributes.OfType<
Serialize>())
877 if ((attribute.IsSaveable ==
IsPropertySaveable.Yes && !attribute.DefaultValue.Equals(value)) ||
878 (!ignoreEditable && property.Attributes.OfType<
Editable>().Any()))
889 if (!supportedTypes.TryGetValue(value.GetType(), out
string typeName))
891 if (property.PropertyType.IsEnum)
893 stringValue = value.ToString();
897 DebugConsole.ThrowError(
"Failed to serialize the property \"" + property.Name +
"\" of \"" + obj +
"\" (type " + property.PropertyType +
" not supported)");
907 stringValue = ((float)value).ToString(
"G", CultureInfo.InvariantCulture);
910 stringValue = XMLExtensions.PointToString((Point)value);
913 stringValue = XMLExtensions.Vector2ToString((Vector2)value);
916 stringValue = XMLExtensions.Vector3ToString((Vector3)value);
919 stringValue = XMLExtensions.Vector4ToString((Vector4)value);
922 stringValue = XMLExtensions.ColorToString((Color)value);
925 stringValue = XMLExtensions.RectToString((
Rectangle)value);
928 string[] stringArray = (
string[])value;
929 stringValue = stringArray !=
null ?
string.Join(
';', stringArray) :
"";
931 case "identifierarray":
932 Identifier[] identifierArray = (Identifier[])value;
933 stringValue = identifierArray !=
null ?
string.Join(
';', identifierArray) :
"";
936 stringValue = value.ToString();
940 element.GetAttribute(property.Name)?.Remove();
941 element.SetAttributeValue(property.Name, stringValue);
954 foreach (var subElement
in configElement.Elements())
956 if (!subElement.Name.ToString().Equals(
"upgrade", StringComparison.OrdinalIgnoreCase)) {
continue; }
957 var upgradeVersion =
new Version(subElement.GetAttributeString(
"gameversion",
"0.0.0.0"));
958 if (subElement.GetAttributeBool(
"campaignsaveonly",
false))
964 if (savedVersion >= upgradeVersion) {
continue; }
966 foreach (XAttribute attribute
in subElement.Attributes())
968 var attributeName = attribute.NameAsIdentifier();
969 if (attributeName ==
"gameversion" || attributeName ==
"campaignsaveonly") {
continue; }
971 if (attributeName ==
"refreshrect")
975 if (!structure.ResizeHorizontal)
977 structure.Rect = structure.DefaultRect =
new Rectangle(structure.Rect.X, structure.Rect.Y,
978 (
int)structure.Prefab.ScaledSize.X,
979 structure.Rect.Height);
981 if (!structure.ResizeVertical)
983 structure.Rect = structure.DefaultRect =
new Rectangle(structure.Rect.X, structure.Rect.Y,
984 structure.Rect.Width,
985 (
int)structure.Prefab.ScaledSize.Y);
988 else if (entity is
Item item)
990 if (!item.ResizeHorizontal)
992 item.Rect = item.DefaultRect =
new Rectangle(item.Rect.X, item.Rect.Y,
993 (
int)(item.Prefab.Size.X * item.Prefab.Scale),
996 if (!item.ResizeVertical)
998 item.Rect = item.DefaultRect =
new Rectangle(item.Rect.X, item.Rect.Y,
1000 (
int)(item.Prefab.Size.Y * item.Prefab.Scale));
1005 if (entity.SerializableProperties.TryGetValue(attributeName, out
SerializableProperty property))
1007 FixValue(property, entity, attribute);
1010 component.ParseMsg();
1013 else if (entity is
Item item1)
1019 FixValue(componentProperty, component, attribute);
1031 if (attribute.Value.Length > 0 && attribute.Value[0] ==
'*')
1033 float.TryParse(attribute.Value.Substring(1), NumberStyles.Float, CultureInfo.InvariantCulture, out
float multiplier);
1037 property.TrySetValue(parentObject, (
int)(((
int)property.
GetValue(parentObject)) * multiplier));
1041 property.TrySetValue(parentObject, (
float)property.
GetValue(parentObject) * multiplier);
1045 property.TrySetValue(parentObject, (Vector2)property.
GetValue(parentObject) * multiplier);
1049 property.TrySetValue(parentObject, ((Point)property.
GetValue(parentObject)).Multiply(multiplier));
1052 else if (attribute.Value.Length > 0 && attribute.Value[0] ==
'+')
1056 float.TryParse(attribute.Value.Substring(1), NumberStyles.Float, CultureInfo.InvariantCulture, out
float addition);
1057 property.TrySetValue(parentObject, (
int)(((
int)property.
GetValue(parentObject)) + addition));
1061 float.TryParse(attribute.Value.Substring(1), NumberStyles.Float, CultureInfo.InvariantCulture, out
float addition);
1062 property.TrySetValue(parentObject, (
float)property.
GetValue(parentObject) + addition);
1066 var addition = XMLExtensions.ParseVector2(attribute.Value.Substring(1));
1067 property.TrySetValue(parentObject, (Vector2)property.
GetValue(parentObject) + addition);
1071 var addition = XMLExtensions.ParsePoint(attribute.Value.Substring(1));
1072 property.TrySetValue(parentObject, ((Point)property.
GetValue(parentObject)) + addition);
1077 property.TrySetValue(parentObject, attribute.Value);
1081 if (entity is
Item item2)
1083 var componentElement = subElement.FirstElement();
1084 if (componentElement ==
null) {
continue; }
1085 ItemComponent itemComponent = item2.Components.First(c => c.Name == componentElement.Name.ToString());
1086 if (itemComponent ==
null) {
continue; }
1087 foreach (XAttribute attribute
in componentElement.Attributes())
1089 var attributeName = attribute.NameAsIdentifier();
1090 if (itemComponent.SerializableProperties.TryGetValue(attributeName, out
SerializableProperty property))
1092 FixValue(property, itemComponent, attribute);
1095 foreach (var element
in componentElement.Elements())
1097 switch (element.Name.ToString().ToLowerInvariant())
1099 case "requireditem":
1100 case "requireditems":
1101 itemComponent.RequiredItems.Clear();
1102 itemComponent.DisabledRequiredItems.Clear();
1104 itemComponent.SetRequiredItems(element, allowEmpty:
true);
1109 (componentElement.GetChildElement(
"containable") !=
null || componentElement.GetChildElement(
"subcontainer") !=
null))
1111 itemContainer.ReloadContainableRestrictions(componentElement);
static GameSession?? GameSession
static readonly Version Version
float CurrentBrokenVolume
The base class for components holding the different functionalities of the item
float RelativeVoltage
Essentially Voltage / MinVoltage (= how much of the minimum required voltage has been satisfied),...
float CurrPowerConsumption
static Dictionary< Identifier, SerializableProperty > DeserializeProperties(object obj, XElement element=null)
bool TrySetValue(object parentObject, string value)
readonly AttributeCollection Attributes
void SetValue(object parentObject, object val)
SerializableProperty(PropertyDescriptor property)
readonly PropertyInfo PropertyInfo
static string GetSupportedTypeName(Type type)
readonly Type PropertyType
float GetFloatValue(object parentObject)
object GetValue(object parentObject)
bool TrySetValue(object parentObject, object value)
static void UpgradeGameVersion(ISerializableEntity entity, ContentXElement configElement, Version savedVersion)
Upgrade the properties of an entity saved with an older version of the game. Properties that should b...
static List< SerializableProperty > GetProperties< T >(ISerializableEntity obj)
bool TrySetValue(object parentObject, float value)
bool TrySetValue(object parentObject, int value)
bool GetBoolValue(object parentObject)
bool TrySetValue(object parentObject, bool value)
static Dictionary< Identifier, SerializableProperty > GetProperties(object obj)
static void SerializeProperties(ISerializableEntity obj, XElement element, bool saveIfDefault=false, bool ignoreEditable=false)
readonly bool OverridePrefabValues
bool AlwaysUseInstanceValues
If set to true, the instance values saved in a submarine file will always override the prefab values,...
readonly IsPropertySaveable IsSaveable
readonly Identifier TranslationTextTag
Serialize(object defaultValue, IsPropertySaveable isSaveable, string description="", string translationTextTag="", bool alwaysUseInstanceValues=false)
Makes the property serializable to/from XML
readonly object DefaultValue
Dictionary< Identifier, SerializableProperty > SerializableProperties