Skip to content

Commit

Permalink
Implement GetPropertyCollectionField()
Browse files Browse the repository at this point in the history
  • Loading branch information
Crypto137 committed Feb 3, 2024
1 parent 3089af2 commit 02892b6
Showing 1 changed file with 41 additions and 10 deletions.
51 changes: 41 additions & 10 deletions src/MHServerEmu/Games/GameData/Calligraphy/CalligraphySerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ private static bool DeserializeFieldGroup(Prototype prototype, Blueprint bluepri
return true;
}

#region Properties

/// <summary>
/// Deserializes a property mixin field group of a Calligraphy prototype.
/// </summary>
Expand All @@ -200,16 +202,7 @@ private static bool DeserializePropertyMixin(Prototype prototype, Blueprint blue
// The only PropertyList field (the one from ModPrototype) is currently being sent here and considered just a regular property collection
var collectionFieldInfo = classType.GetProperty("Properties");
if (collectionFieldInfo != null)
{
collection = (PrototypePropertyCollection)collectionFieldInfo.GetValue(prototype);

// Initialize a new collection in this field if there isn't one already
if (collection == null)
{
collection = new();
collectionFieldInfo.SetValue(prototype, collection);
}
}
collection = GetPropertyCollectionField(prototype, collectionFieldInfo);
}

// This handles both cases (initialization and filling property collections)
Expand Down Expand Up @@ -248,6 +241,44 @@ private static bool DeserializeFieldGroupIntoProperty(PrototypePropertyCollectio
return true;
}

/// <summary>
/// Returns the <see cref="PrototypePropertyCollection"/> belonging to the provided <see cref="Prototype"/> if it has one.
/// Returns <see langword="null"/> if the prototype has no <see cref="PrototypePropertyCollection"/> fields.
/// </summary>
public static PrototypePropertyCollection GetPropertyCollectionField(Prototype prototype)
{
// NOTE: This method is public because it is also used by PowerPrototype during post-processing.
// Maybe we should move this to PrototypeClassManager where it makes more sense to be.

// In all of our data there is never more than one PrototypePropertyCollection field,
// and it's always called Properties, so we will make use of that to avoid iterating through
// all fields.
var fieldInfo = prototype.GetType().GetProperty("Properties", typeof(PrototypePropertyCollection));
if (fieldInfo != null) return GetPropertyCollectionField(prototype, fieldInfo);
return null;
}

/// <summary>
/// Returns the <see cref="PrototypePropertyCollection"/> belonging to the provided <see cref="Prototype"/>.
/// </summary>
private static PrototypePropertyCollection GetPropertyCollectionField(Prototype prototype, System.Reflection.PropertyInfo fieldInfo)
{
var collection = (PrototypePropertyCollection)fieldInfo.GetValue(prototype);

// Initialize a new collection in this field if there isn't one already or it doesn't belong to it
if (collection == null || prototype.IsDynamicFieldOwnedBy(collection) == false)
{
// Copy parent collection if there is one, otherwise start with a blank one
collection = collection == null ? new() : collection.ShallowCopy();
fieldInfo.SetValue(prototype, collection);
prototype.SetDynamicFieldOwner(collection);
}

return collection;
}

#endregion

#region Field Copying

/// <summary>
Expand Down

0 comments on commit 02892b6

Please sign in to comment.