diff --git a/PolyMod.csproj b/PolyMod.csproj
index fc5d85d..99a2248 100644
--- a/PolyMod.csproj
+++ b/PolyMod.csproj
@@ -11,7 +11,7 @@
IL2CPP
PolyMod
- 1.2.10-pre
+ 1.2.10-pre.1
2.16.3.15581
PolyModdingTeam
The Battle of Polytopia's mod loader.
diff --git a/src/Loader.cs b/src/Loader.cs
index 838e491..32bbc96 100644
--- a/src/Loader.cs
+++ b/src/Loader.cs
@@ -54,85 +54,89 @@ internal record TypeMapping(Type type, bool shouldCreateCache = true);
///
/// Handlers for processing specific data types during mod loading.
///
- internal static readonly Dictionary> typeHandlers = new()
+ internal static readonly Dictionary>> typeHandlers = new()
{
- [typeof(TribeType)] = new((token, duringEnumCacheCreation) =>
- {
- if (duringEnumCacheCreation)
- {
- Registry.customTribes.Add((TribeType)Registry.autoidx);
- token["style"] = Registry.climateAutoidx;
- token["climate"] = Registry.climateAutoidx;
- Registry.climateAutoidx++;
- }
- else
+ [typeof(TribeType)] = new List>() {
+ new((token, duringEnumCacheCreation) =>
{
- if (token["skins"] != null)
+ if (duringEnumCacheCreation)
+ {
+ Registry.customTribes.Add((TribeType)Registry.autoidx);
+ token["style"] = Registry.climateAutoidx;
+ token["climate"] = Registry.climateAutoidx;
+ Registry.climateAutoidx++;
+ }
+ else
{
- JArray skins = token["skins"].Cast();
- List skinValues = skins._values.ToArray().ToList();
- foreach (var skin in skinValues)
+ if (token["skins"] != null)
{
- string skinValue = skin.ToString();
- if (!Enum.TryParse(skinValue, ignoreCase: true, out _))
+ JArray skins = token["skins"].Cast();
+ List skinValues = skins._values.ToArray().ToList();
+ foreach (var skin in skinValues)
{
- EnumCache.AddMapping(skinValue.ToLowerInvariant(), (SkinType)Registry.autoidx);
- EnumCache.AddMapping(skinValue.ToLowerInvariant(), (SkinType)Registry.autoidx);
- Registry.skinInfo.Add(new Visual.SkinInfo(Registry.autoidx, skinValue, null));
- Plugin.logger.LogInfo("Created mapping for skinType with id " + skinValue + " and index " + Registry.autoidx);
- Registry.autoidx++;
+ string skinValue = skin.ToString();
+ if (!Enum.TryParse(skinValue, ignoreCase: true, out _))
+ {
+ EnumCache.AddMapping(skinValue.ToLowerInvariant(), (SkinType)Registry.autoidx);
+ EnumCache.AddMapping(skinValue.ToLowerInvariant(), (SkinType)Registry.autoidx);
+ Registry.skinInfo.Add(new Visual.SkinInfo(Registry.autoidx, skinValue, null));
+ Plugin.logger.LogInfo("Created mapping for skinType with id " + skinValue + " and index " + Registry.autoidx);
+ Registry.autoidx++;
+ }
}
- }
- Il2CppSystem.Collections.Generic.List modifiedSkins = skins._values;
- foreach (var skin in Registry.skinInfo)
- {
- if (modifiedSkins.Contains(skin.id))
+ Il2CppSystem.Collections.Generic.List modifiedSkins = skins._values;
+ foreach (var skin in Registry.skinInfo)
+ {
+ if (modifiedSkins.Contains(skin.id))
+ {
+ modifiedSkins.Remove(skin.id);
+ modifiedSkins.Add(skin.idx.ToString());
+ }
+ }
+ JArray newSkins = new JArray();
+ foreach (var item in modifiedSkins)
{
- modifiedSkins.Remove(skin.id);
- modifiedSkins.Add(skin.idx.ToString());
+ newSkins.Add(item);
}
+ token["skins"] = newSkins;
}
- JArray newSkins = new JArray();
- foreach (var item in modifiedSkins)
+ if (token["preview"] != null)
{
- newSkins.Add(item);
+ Visual.PreviewTile[] preview = JsonSerializer.Deserialize(token["preview"].ToString())!;
+ Registry.tribePreviews[Util.GetJTokenName(token)] = preview;
}
- token["skins"] = newSkins;
- }
- if (token["preview"] != null)
- {
- Visual.PreviewTile[] preview = JsonSerializer.Deserialize(token["preview"].ToString())!;
- Registry.tribePreviews[Util.GetJTokenName(token)] = preview;
}
- }
- }),
-
- [typeof(UnitData.Type)] = new((token, duringEnumCacheCreation) =>
- {
- if (!duringEnumCacheCreation)
+ })
+ },
+ [typeof(UnitData.Type)] = new List>() {
+ new((token, duringEnumCacheCreation) =>
{
- if (token["prefab"] != null)
+ if (!duringEnumCacheCreation)
{
- Registry.prefabNames.Add((int)(UnitData.Type)(int)token["idx"], CultureInfo.CurrentCulture.TextInfo.ToTitleCase(token["prefab"]!.ToString()));
- }
- if (token["embarksTo"] != null)
- {
- string unitId = Util.GetJTokenName(token);
- string embarkUnitId = token["embarksTo"].ToString();
- Main.embarkNames[unitId] = embarkUnitId;
- }
- if (token["weapon"] != null)
- {
- string weaponString = token["weapon"].ToString();
- if (EnumCache.TryGetType(weaponString, out UnitData.WeaponEnum type))
+ if (token["prefab"] != null)
+ {
+ Registry.prefabNames.Add((int)(UnitData.Type)(int)token["idx"], token["prefab"]!.ToString());
+ }
+ if (token["embarksTo"] != null)
+ {
+ string unitId = Util.GetJTokenName(token);
+ string embarkUnitId = token["embarksTo"].ToString();
+ Main.embarkNames[unitId] = embarkUnitId;
+ }
+ if (token["weapon"] != null)
{
- token["weapon"] = (int)type;
+ string weaponString = token["weapon"].ToString();
+ if (EnumCache.TryGetType(weaponString, out UnitData.WeaponEnum type))
+ {
+ token["weapon"] = (int)type;
+ }
}
}
- }
- }),
+ })
+ },
- [typeof(ImprovementData.Type)] = new((token, duringEnumCacheCreation) =>
+ [typeof(ImprovementData.Type)] = new List>() {
+ new((token, duringEnumCacheCreation) =>
{
if (duringEnumCacheCreation)
{
@@ -161,29 +165,34 @@ internal record TypeMapping(Type type, bool shouldCreateCache = true);
Main.attractsTerrainNames[improvementId] = attractsId;
}
}
- }),
+ })
+ },
- [typeof(ResourceData.Type)] = new((token, duringEnumCacheCreation) =>
- {
- if (duringEnumCacheCreation)
+ [typeof(ResourceData.Type)] = new List>() {
+ new((token, duringEnumCacheCreation) =>
{
- ResourceData.Type resourcePrefabType = ResourceData.Type.Game;
- if (token["prefab"] != null)
+ if (duringEnumCacheCreation)
{
- string prefabId = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(token["prefab"]!.ToString());
- if (Enum.TryParse(prefabId, out ResourceData.Type parsedType))
- resourcePrefabType = parsedType;
+ ResourceData.Type resourcePrefabType = ResourceData.Type.Game;
+ if (token["prefab"] != null)
+ {
+ string prefabId = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(token["prefab"]!.ToString());
+ if (Enum.TryParse(prefabId, out ResourceData.Type parsedType))
+ resourcePrefabType = parsedType;
+ }
+ if(token["idx"] != null)
+ PrefabManager.resources.TryAdd((ResourceData.Type)(int)token["idx"], PrefabManager.resources[resourcePrefabType]);
}
- if(token["idx"] != null)
- PrefabManager.resources.TryAdd((ResourceData.Type)(int)token["idx"], PrefabManager.resources[resourcePrefabType]);
- }
- }),
+ })
+ },
- [typeof(SkinData)] = new((token, duringEnumCacheCreation) =>
- {
- var prop = token.Parent.Cast();
- prop.Replace(new JProperty(prop.Name.ToLower(), prop.Value));
- }),
+ [typeof(SkinData)] = new List>() {
+ new((token, duringEnumCacheCreation) =>
+ {
+ var prop = token.Parent.Cast();
+ prop.Replace(new JProperty(prop.Name.ToLower(), prop.Value));
+ })
+ },
};
///
@@ -217,7 +226,7 @@ public static void AddGameMode(string id, UIButtonBase.ButtonAction action, bool
/// Adds a new data type for patching.
///
/// The identifier for the data type in JSON.
- /// The C# type corresponding to the identifier.
+ /// "The C# type corresponding to the identifier.
public static void AddPatchDataType(string typeId, Type type)
{
if (!typeMappings.ContainsKey(typeId))
@@ -230,6 +239,21 @@ public static void AddPatchDataType(string typeId, Type type, bool shouldCreateC
typeMappings.Add(typeId, new TypeMapping(type, shouldCreateCache));
}
+ public static void AddTypeHandler(Type type, Action handler)
+ {
+ if(!typeMappings.ContainsValue(new TypeMapping(type, true)) && !typeMappings.ContainsValue(new TypeMapping(type, false)))
+ {
+ Plugin.logger.LogWarning($"Tried adding TypeHandler for type: {type.ToString()} with missing TypeMapping. Please, add TypeMapping first.");
+ return;
+ }
+ if(!typeHandlers.ContainsKey(type))
+ typeHandlers[type] = new();
+
+ typeHandlers[type].Add(handler);
+
+ Plugin.logger.LogWarning($"Added TypeHandler for type: {type.ToString()}.");
+ }
+
///
/// Loads all mods from the mods directory.
///
@@ -889,9 +913,12 @@ internal static void CreateMappings(JObject rootObject)
methodInfo.Invoke(null, new object[] { id, (int)token["idx"] });
methodInfo.Invoke(null, new object[] { id, (int)token["idx"] });
- if (typeHandlers.TryGetValue(targetType, out var handler))
+ if (typeHandlers.TryGetValue(targetType, out var handlers))
{
- handler(token, true);
+ foreach(var handler in handlers)
+ {
+ handler(token, true);
+ }
}
Plugin.logger.LogInfo("Created mapping for " + targetType.ToString() + " with id " + id + " and index " + (int)token["idx"]);
}
@@ -903,9 +930,12 @@ internal static void CreateMappings(JObject rootObject)
string dataType = Util.GetJTokenName(token, 2);
if (typeMappings.TryGetValue(dataType, out TypeMapping? typeMapping))
{
- if (typeHandlers.TryGetValue(typeMapping.type, out var handler))
+ if (typeHandlers.TryGetValue(typeMapping.type, out var handlers))
{
- handler(token, false);
+ foreach(var handler in handlers)
+ {
+ handler(token, false);
+ }
}
}
}
@@ -921,25 +951,27 @@ internal static void ProcessPrefabs()
{
UnitData.Type unitPrefabType = UnitData.Type.Scout;
string prefabId = item.Value;
- if (Enum.TryParse(prefabId, out UnitData.Type parsedType))
+ int hashKey = PrefabManager.GetSkinnedHashKey((UnitData.Type)item.Key, TribeType.None, SkinType.Default);
+ if (!Enum.TryParse(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(prefabId), out unitPrefabType)) // Existing unit prefabs
{
- unitPrefabType = parsedType;
- PrefabManager.units.TryAdd(item.Key, PrefabManager.units[(int)unitPrefabType]);
- }
- else
- {
- KeyValuePair prefabInfo = Registry.unitPrefabs.FirstOrDefault(kv => kv.Key.name == prefabId);
- int hashKey = PrefabManager.GetSkinnedHashKey((UnitData.Type)item.Key, TribeType.None, SkinType.Default);
+ KeyValuePair prefabInfo = Registry.unitPrefabs.FirstOrDefault(
+ kv => kv.Key.name == prefabId
+ );
if (!EqualityComparer.Default.Equals(prefabInfo.Key, default))
{
+ Visual.UnitPrefabInfo unitPrefabInfo = new(
+ EnumCache.GetName((UnitData.Type)item.Key),
+ EnumCache.GetName(TribeType.None),
+ EnumCache.GetName(SkinType.Default)
+ );
PrefabManager.units.TryAdd(hashKey, prefabInfo.Value);
- }
- else
- {
- int existingPrefabKey = PrefabManager.GetSkinnedHashKey(unitPrefabType, TribeType.None, SkinType.Default);
- PrefabManager.units.TryAdd(hashKey, PrefabManager.units[existingPrefabKey]);
+ return;
}
}
+ PrefabManager.units.TryAdd(
+ hashKey,
+ PrefabManager.units[PrefabManager.GetSkinnedHashKey(unitPrefabType, TribeType.None, SkinType.Default)]
+ );
}
}
diff --git a/src/Managers/Visual.cs b/src/Managers/Visual.cs
index bade10b..e3e7c71 100644
--- a/src/Managers/Visual.cs
+++ b/src/Managers/Visual.cs
@@ -54,8 +54,19 @@ public record SkinInfo(int idx, string id, SkinData? skinData);
/// A dictionary of custom widths for basic popups.
public static Dictionary basicPopupWidths = new();
/// Represents information about a unit prefab.
- public record UnitPrefabInfo(string type, string tribe, string skin);
- public static Dictionary skinnedHashKeys = new();
+ public struct UnitPrefabInfo
+ {
+ public UnitPrefabInfo(string type, string tribe, string skin)
+ {
+ this.type = type;
+ this.tribe = tribe;
+ this.skin = skin;
+ }
+ public string type;
+ public string tribe;
+ public string skin;
+ }
+ public static Dictionary customPrefabs = new();
private static bool firstTimeOpeningPreview = true;
private static UnitData.Type currentUnitTypeUI = UnitData.Type.None;
private static TribeType attackerTribe = TribeType.None;
@@ -234,118 +245,22 @@ private static void SkinVisualsRenderer_SkinWorldObject(
}
[HarmonyPostfix]
- [HarmonyPatch(typeof(PrefabManager), nameof(PrefabManager.SetupData))]
- private static void PrefabManager_SetupData(PrefabManager __instance)
- {
- PrefabManager.units.Clear();
- PrefabManager.unitUIOverrides.Clear();
-
- foreach (PrefabManager.UnitPrefabData unitPrefabData in __instance.unitPrefabs)
- {
- PrefabManager.units.Add(
- PrefabManager.GetSkinnedHashKey(unitPrefabData.type, unitPrefabData.tribe, unitPrefabData.skin),
- unitPrefabData.prefab
- );
- }
-
- foreach (PrefabManager.UnitPrefabData unitUIPrefabData in __instance.unitUIOverridePrefabs)
- {
- PrefabManager.unitUIOverrides.Add(
- PrefabManager.GetSkinnedHashKey(unitUIPrefabData.type, unitUIPrefabData.tribe, unitUIPrefabData.skin),
- unitUIPrefabData.prefab
- );
- }
- }
-
- [HarmonyPrefix]
- [HarmonyPatch(typeof(PrefabManager), nameof(PrefabManager.GetSkinnedHashKey))]
- private static bool PrefabManager_GetSkinnedHashKey(ref int __result, UnitData.Type type, TribeType tribe, SkinType skin)
+ [HarmonyPatch(typeof(PrefabManager), nameof(PrefabManager.GetPrefab),
+ typeof(UnitData.Type), typeof(TribeType), typeof(SkinType)
+ )]
+ private static void PrefabManager_GetPrefab(ref Unit __result, UnitData.Type type, TribeType tribe, SkinType skin)
{
UnitPrefabInfo unitPrefabInfo = new(
EnumCache.GetName(type),
EnumCache.GetName(tribe),
EnumCache.GetName(skin)
);
- if(!skinnedHashKeys.ContainsKey(unitPrefabInfo))
- {
- int key = skinnedHashKeys.Keys.Count;
- skinnedHashKeys.Add(unitPrefabInfo, key);
- }
- __result = skinnedHashKeys[unitPrefabInfo];
- return false;
- }
-
- [HarmonyPrefix]
- [HarmonyPatch(typeof(PrefabManager), nameof(PrefabManager.HasUIUnitOverride))]
- public static bool PrefabManager_HasUIUnitOverride(ref bool __result, UnitData.Type unitType, TribeType tribe, SkinType skin)
- {
- int skinnedHashKey = PrefabManager.GetSkinnedHashKey(unitType, tribe, skin);
- __result = PrefabManager.unitUIOverrides.ContainsKey(skinnedHashKey);
- return false;
- }
-
- [HarmonyPrefix]
- [HarmonyPatch(typeof(PrefabManager), nameof(PrefabManager.GetUnitOrUiOverride))]
- public static bool PrefabManager_GetUnitOrUiOverride(ref Unit __result, UnitData.Type unitType, TribeType tribe, SkinType skin)
- {
- int skinnedHashKey = PrefabManager.GetSkinnedHashKey(unitType, tribe, skin);
- if (PrefabManager.unitUIOverrides.TryGetValue(skinnedHashKey, out var prefab))
- {
- __result = prefab;
- return false;
- }
- __result = PrefabManager.GetPrefab(unitType, tribe, skin);
- return false;
- }
-
- [HarmonyPrefix]
- [HarmonyPatch(typeof(PrefabManager), nameof(PrefabManager.GetPrefab), typeof(UnitData.Type), typeof(TribeType), typeof(SkinType))]
- public static bool GetPrefab(ref Unit __result, UnitData.Type type, TribeType tribe, SkinType skin)
- {
- if (SeasonManager.IsChristmas())
- {
- Unit prefab = PrefabManager.GetPrefab(type, OverrideCondition.Christmas);
- if (prefab != null)
- {
- __result = prefab;
- return false;
- }
- }
- int skinnedHashKey = PrefabManager.GetSkinnedHashKey(type, tribe, skin);
- if (PrefabManager.units.TryGetValue(skinnedHashKey, out var value))
- {
- __result = value;
- return false;
- }
- if (skin != SkinType.Default || tribe != TribeType.None)
+ if(customPrefabs.ContainsKey(
+ unitPrefabInfo
+ ))
{
- int skinnedHashKey2 = PrefabManager.GetSkinnedHashKey(type, TribeType.None, skin);
- int skinnedHashKey3 = PrefabManager.GetSkinnedHashKey(type, tribe, SkinType.Default);
- int skinnedHashKey4 = PrefabManager.GetSkinnedHashKey(type, TribeType.None, SkinType.Default);
- int num = 0;
- if (PrefabManager.units.ContainsKey(skinnedHashKey2))
- {
- num = skinnedHashKey2;
- }
- else if (PrefabManager.units.ContainsKey(skinnedHashKey3))
- {
- num = skinnedHashKey3;
- }
- else if (PrefabManager.units.ContainsKey(skinnedHashKey4))
- {
- num = skinnedHashKey4;
- }
- if (num != 0)
- {
- Unit unit = PrefabManager.units[num];
- PrefabManager.units.Add(skinnedHashKey, unit);
- __result = unit;
- return false;
- }
+ __result = customPrefabs[unitPrefabInfo];
}
- Plugin.logger.LogInfo($"Couldn't find prefab for type: {type}");
- __result = PrefabManager.units[0];
- return false;
}
#endregion