Skip to content

Commit

Permalink
237 library designs scrambled (#257)
Browse files Browse the repository at this point in the history
* Delete an unused Galaxy.Load method overload

* Made coupling between MountedComponentTemplate and Design looser, so as to avoid corrupting designs when switching mods
  • Loading branch information
ekolis committed Dec 30, 2022
1 parent dc2d54e commit 79a4255
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 22 deletions.
58 changes: 37 additions & 21 deletions FrEee/Game/Objects/Space/Galaxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
using FrEee.Modding;
using FrEee.Utility;
using FrEee.Utility.Extensions;
using Microsoft.Scripting.Utils;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -523,26 +525,6 @@ public static void Initialize(GameSetup gsu, PRNG dice, Status status = null, do
Galaxy.SaveAll(status, desiredProgress);
}

/// <summary>
/// Loads a savegame from a stream.
/// </summary>
/// <param name="stream"></param>
public static void Load(Stream stream)
{
Galaxy.Current = Serializer.Deserialize<Galaxy>(stream);
if (Current.ModPath == null)
Mod.Load(null); // skipped in deserialization because it is null but the mod needs to be loaded!
//Current.SpaceObjectIDCheck("after loading from disk/memory");

if (Empire.Current != null)
{
// initialize IronPython galaxy on load
Current.StringValue = Current.SaveToString(false);
var formula = new ComputedFormula<int>("Galaxy.Current.TurnNumber", null, true);
var turn = formula.Value;
}
}

/// <summary>
/// Loads a savegame from the Savegame folder.
/// Note that if it was renamed, it might have different game name, turn number, player number, etc. than the filename indicates.
Expand All @@ -561,6 +543,7 @@ public static void Load(string filename)
}
fs.Close();
fs.Dispose();
Current.PopulatePropertyValues();
}

/// <summary>
Expand Down Expand Up @@ -607,7 +590,40 @@ public static void LoadFromString(string serializedData)
// load library of designs, strategies, etc.
Library.Load();
}
}

Current.PopulatePropertyValues();
}

/// <summary>
/// Populates property values specified by <see cref="PopulateAttribute{T}"/>.
/// </summary>
private void PopulatePropertyValues()
{
// TODO: cache list of properties to populate when deserializing?
// enumerate all referrables
foreach (var referrable in Referrables)
{
// find referrable's properties
var props = referrable.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var prop in props)
{
// search property's attributes for PopulateAttribute<T>
foreach (var att in prop.GetCustomAttributes())
{
if (att.GetType().IsGenericType && att.GetType().GetGenericTypeDefinition() == typeof(PopulateAttribute<>))
{
// found PopulateAttribute<T>
// create populator
var populatorType = att.GetType().GetGenericArguments()[0];
var populator = (IPopulator)populatorType.Instantiate();

// get value from populator and save it into the referrable's property
prop.SetValue(referrable, populator.Populate(referrable));
}
}
}
}
}

/// <summary>
/// Only public for unit tests. You should probably call ProcessTurn instead.
Expand Down
6 changes: 5 additions & 1 deletion FrEee/Game/Objects/Technology/MountedComponentTemplate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ public IEnumerable<IAbilityObject> Children
/// <summary>
/// The design which contains this mounted component template.
/// </summary>
[DoNotSerialize]
[Populate<MountedComponentTemplateContainerPopulator>]
public IDesign Container { get; set; }

public ResourceQuantity Cost
Expand Down Expand Up @@ -387,7 +389,9 @@ public void ReplaceClientIDs(IDictionary<long, long> idmap, ISet<IPromotable> do
if (!done.Contains(this))
{
done.Add(this);
Container.ReplaceClientIDs(idmap, done);
// we don't need to do this because the container is only loosely coupled to the MCT
// and it will be sanitized for itself anyway
//Container.ReplaceClientIDs(idmap, done);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FrEee.Game.Interfaces;
using FrEee.Game.Objects.Space;
using FrEee.Utility;

namespace FrEee.Game.Objects.Technology
{
/// <summary>
/// Populates the <see cref="MountedComponentTemplate.Container"/> property.
/// </summary>
public class MountedComponentTemplateContainerPopulator
: IPopulator
{
public object? Populate(object? context)
{
if (context is MountedComponentTemplate mct)
{
return Galaxy.Current.Referrables.OfType<IDesign>().SingleOrDefault(q => q.Components.Contains(mct));
}
else
{
return null;
}
}
}
}
20 changes: 20 additions & 0 deletions FrEee/Utility/IPopulator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace FrEee.Utility
{
public interface IPopulator
{
/// <summary>
/// Performs potentially expensive lookup logic to retrieve that data which needs to be populated
/// into the cache.
/// </summary>
/// <param name="context"></param>
/// <returns>The data retrieved, or null if it was not found.</returns>
public object? Populate(object? context);
}
}
14 changes: 14 additions & 0 deletions FrEee/Utility/PopulateAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FrEee.Utility
{
public class PopulateAttribute<T>
: Attribute
where T : IPopulator
{
}
}

0 comments on commit 79a4255

Please sign in to comment.