Skip to content

Commit 769f809

Browse files
committed
Merge branch 'main' into fallbackfonts
2 parents cf0a209 + 82ea1ff commit 769f809

7 files changed

Lines changed: 121 additions & 45 deletions

File tree

PolyMod.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
</RestoreAdditionalProjectSources>
1212
<Configurations>IL2CPP</Configurations>
1313
<RootNamespace>PolyMod</RootNamespace>
14-
<Version>1.2.11-pre</Version>
14+
<Version>1.2.11</Version>
1515
<PolytopiaVersion>2.16.4.15698</PolytopiaVersion>
1616
<Authors>PolyModdingTeam</Authors>
1717
<Description>The Battle of Polytopia's mod loader.</Description>

src/Loader.cs

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -307,38 +307,26 @@ internal static void RegisterMods(Dictionary<string, Mod> mods)
307307
// Load mod from directory or zip archive
308308
if (Directory.Exists(modContainer))
309309
{
310-
foreach (var file in Directory.GetFiles(modContainer))
310+
foreach (var file in Directory.GetFiles(modContainer, "*", SearchOption.AllDirectories))
311311
{
312-
if (Path.GetFileName(file) == "manifest.json")
313-
{
314-
manifest = JsonSerializer.Deserialize<Mod.Manifest>(
315-
File.ReadAllBytes(file),
316-
new JsonSerializerOptions()
317-
{
318-
Converters = { new VersionJson() },
319-
}
320-
);
321-
continue;
322-
}
323-
files.Add(new(Path.GetFileName(file), File.ReadAllBytes(file)));
312+
ProcessModFile(
313+
Path.GetRelativePath(modContainer, file),
314+
File.ReadAllBytes(file),
315+
files,
316+
ref manifest
317+
);
324318
}
325319
}
326320
else
327321
{
328322
foreach (var entry in new ZipArchive(File.OpenRead(modContainer)).Entries)
329323
{
330-
if (entry.FullName == "manifest.json")
331-
{
332-
manifest = JsonSerializer.Deserialize<Mod.Manifest>(
333-
entry.ReadBytes(),
334-
new JsonSerializerOptions()
335-
{
336-
Converters = { new VersionJson() },
337-
}
338-
);
339-
continue;
340-
}
341-
files.Add(new(entry.FullName, entry.ReadBytes()));
324+
ProcessModFile(
325+
entry.FullName,
326+
entry.ReadBytes(),
327+
files,
328+
ref manifest
329+
);
342330
}
343331
}
344332
#region ValidateManifest()
@@ -384,6 +372,22 @@ internal static void RegisterMods(Dictionary<string, Mod> mods)
384372
CheckDependencies(mods);
385373
}
386374

375+
private static void ProcessModFile(string fullName, byte[] bytes, List<Mod.File> files, ref Mod.Manifest? manifest)
376+
{
377+
if (fullName == "manifest.json")
378+
{
379+
manifest = JsonSerializer.Deserialize<Mod.Manifest>(
380+
bytes,
381+
new JsonSerializerOptions()
382+
{
383+
Converters = { new VersionJson() },
384+
}
385+
);
386+
return;
387+
}
388+
files.Add(new(fullName, bytes));
389+
}
390+
387391
internal static void LoadMods(Dictionary<string, Mod> mods, out bool dependencyCycle)
388392
{
389393
dependencyCycle = !SortMods(Registry.mods);
@@ -400,7 +404,8 @@ internal static void LoadMods(Dictionary<string, Mod> mods, out bool dependencyC
400404
{
401405
LoadAssemblyFile(mod, file);
402406
}
403-
if (Path.GetFileName(file.name) == "sprites.json")
407+
Match spritesMatch = Regex.Match(Path.GetFileName(file.name), @"^sprites(?:_(.*))?\.json$");
408+
if (spritesMatch.Success)
404409
{
405410
LoadSpriteInfoFile(mod, file);
406411
}
@@ -417,7 +422,6 @@ internal static void LoadMods(Dictionary<string, Mod> mods, out bool dependencyC
417422
file,
418423
languageName
419424
);
420-
continue;
421425
}
422426
}
423427
if (!mod.client && id != "polytopia")

src/Managers/Hub.cs

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
using UnityEngine.UI;
1010
using static PopupBase;
1111
using PolytopiaBackendBase.Common;
12+
using System.Text.Encodings.Web;
13+
using Il2CppSystem.Linq;
14+
using System.Text.RegularExpressions;
15+
1216

1317
namespace PolyMod.Managers;
1418

@@ -180,27 +184,60 @@ static void PolyModHubButtonClicked(int buttonId, BaseEventData eventData)
180184
callback: (UIButtonBase.ButtonAction)((_, _) =>
181185
{
182186
Directory.CreateDirectory(Plugin.DUMPED_DATA_PATH);
187+
Directory.CreateDirectory(Plugin.LOGIC_DUMP_PATH);
188+
Directory.CreateDirectory(Plugin.LOCALIZATION_DUMP_PATH);
183189
File.WriteAllTextAsync(
184-
Path.Combine(Plugin.DUMPED_DATA_PATH, "gameLogicData.json"),
190+
Path.Combine(Plugin.LOGIC_DUMP_PATH, "gameLogicData.json"),
185191
PolytopiaDataManager.provider.LoadGameLogicData(VersionManager.GameLogicDataVersion)
186192
);
187193
File.WriteAllTextAsync(
188-
Path.Combine(Plugin.DUMPED_DATA_PATH, "avatarData.json"),
194+
Path.Combine(Plugin.LOGIC_DUMP_PATH, "avatarData.json"),
189195
PolytopiaDataManager.provider.LoadAvatarData(1337)
190196
);
191-
foreach (var category in LocalizationManager.Sources[0].GetCategories())
197+
var source = LocalizationManager.Sources[0];
198+
foreach (var language in source.GetLanguages())
199+
{
200+
int languageIndex = source.GetLanguageIndex(language);
201+
var dict = new Dictionary<string, string>();
202+
203+
foreach (var term in source.mTerms)
204+
{
205+
var translation = term.GetTranslation(languageIndex);
206+
207+
if (!string.IsNullOrEmpty(translation))
208+
dict[term.Term] = translation;
209+
}
210+
var options = new JsonSerializerOptions
211+
{
212+
WriteIndented = true,
213+
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
214+
};
215+
216+
string json = JsonSerializer.Serialize(dict, options);
217+
218+
File.WriteAllText(
219+
Path.Combine(Plugin.LOCALIZATION_DUMP_PATH, $"language_{source.mLanguages[languageIndex].Code}.json"),
220+
json
221+
);
222+
}
223+
foreach (var category in source.GetCategories())
192224
File.WriteAllTextAsync(
193-
Path.Combine(Plugin.DUMPED_DATA_PATH, $"localization_{category}.csv"),
194-
LocalizationManager.Sources[0].Export_CSV(category)
225+
Path.Combine(Plugin.LOCALIZATION_DUMP_PATH, $"localization_{category}.csv"),
226+
source.Export_CSV(category)
195227
);
196228
foreach (KeyValuePair<string, Mod> entry in Registry.mods)
197229
{
198230
foreach (Mod.File file in entry.Value.files)
199231
{
200-
if (Path.GetFileName(file.name) == "sprites.json")
201-
{
202-
File.WriteAllBytes(Path.Combine(Plugin.DUMPED_DATA_PATH, $"sprites_{entry.Key}.json"), file.bytes);
203-
}
232+
Match spritesMatch = Regex.Match(Path.GetFileName(file.name), @"^sprites(?:_(.*))?\.json$");
233+
if (spritesMatch.Success)
234+
File.WriteAllBytes(
235+
Path.Combine(
236+
Plugin.DUMPED_DATA_PATH,
237+
$"{Path.GetFileNameWithoutExtension(file.name)}_{entry.Key}.json"
238+
),
239+
file.bytes
240+
);
204241
}
205242
}
206243
foreach (TribeType type in Enum.GetValues(typeof(TribeType)))

src/Managers/Loc.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,21 @@ public static bool Localization_Init()
100100
if (LocalizationManager.Sources.Count == 0)
101101
LocalizationManager.UpdateSources();
102102

103-
foreach(var name in languagesToAdd.Keys)
103+
LanguageSourceData source = LocalizationManager.Sources[0];
104+
105+
// Elyrion has no language code. I am almost completely sure it is a bug, by looking at the code.
106+
LanguageData elyrionLanguage = source.GetLanguageData("Elyrion");
107+
elyrionLanguage.Code = Localization.LANG_CODE_ELYRION;
108+
109+
foreach(var languageCode in languagesToAdd.Keys)
104110
{
105-
Dictionary<string, string> terms = languagesToAdd[name];
111+
Dictionary<string, string> terms = languagesToAdd[languageCode];
106112

107-
LanguageSourceData source = LocalizationManager.Sources[0];
108-
int languageIndex = source.GetLanguageIndex(name);
113+
int languageIndex = source.GetLanguageIndexFromCode(languageCode);
109114
string languageName = terms["language"];
110115
if (languageIndex == -1)
111116
{
112-
source.AddLanguage(languageName, name);
117+
source.AddLanguage(languageName, languageCode);
113118
languageIndex = source.GetLanguageIndex(languageName);
114119
}
115120

@@ -127,7 +132,7 @@ public static bool Localization_Init()
127132

128133
LocalizationManager.UpdateSources();
129134

130-
Plugin.logger.LogInfo($"{name} language added and loaded!");
135+
Plugin.logger.LogInfo($"{languageCode} language terms added.");
131136
}
132137
return true;
133138
}

src/Managers/Main.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,8 @@ internal static void Load(GameLogicData gameLogicData, JObject json)
389389
foreach (var file in mod.files)
390390
{
391391
if (mod.status != Mod.Status.Success) break;
392-
if (Path.GetFileName(file.name) == "localization.json")
392+
Match localizationMatch = Regex.Match(Path.GetFileName(file.name), @"^localization(_.*)?\.json$");
393+
if (localizationMatch.Success)
393394
{
394395
Loader.LoadLocalizationFile(mod, file);
395396
continue;

src/Managers/Visual.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,10 @@ private static void TerrainRenderer_UpdateGraphics(TerrainRenderer __instance, T
312312
SkinType skinType = tile.data.Skin;
313313

314314
string flood = "";
315-
if (tile.data.effects.Contains(TileData.EffectType.Flooded) || (tribe == TribeType.Aquarion && tile.data.terrain == Polytopia.Data.TerrainData.Type.Mountain))
315+
if (
316+
tile.data.effects.Contains(TileData.EffectType.Flooded) ||
317+
(tribe == TribeType.Aquarion && tile.data.terrain == Polytopia.Data.TerrainData.Type.Mountain)
318+
) // TODO: Check all tribes with flooded abil instead of Aquarion only.
316319
{
317320
foreach (var effect in tile.data.effects)
318321
{
@@ -366,6 +369,22 @@ private static void TileData_Flood(TileData __instance, PlayerState playerState)
366369
}
367370
}
368371

372+
/// <summary>Removes custom flood effect loc from tile tip header.</summary>
373+
[HarmonyPostfix]
374+
[HarmonyPatch(typeof(TileTipGenerator), nameof(TileTipGenerator.GetTileTipHeader))]
375+
public static void GetTileTipHeader(ref string __result, TileData tileData, SkinType skin,
376+
PlayerState playerState, GameState gameState, GameLogicData gameLogicData)
377+
{
378+
foreach(var effect in tileData.effects)
379+
{
380+
if(customFloodingSkins.ContainsKey(effect))
381+
{
382+
string localizedEffect = Localization.GetSkinned(skin, playerState.tribe, $"tile.effect.{effect.GetName()}");
383+
__result = __result.Replace($", {localizedEffect}", string.Empty);
384+
}
385+
}
386+
}
387+
369388
/// <summary>Forces an update of the mesh for a PolytopiaSpriteRenderer with a custom sprite.</summary>
370389
[HarmonyPostfix]
371390
[HarmonyPatch(typeof(PolytopiaSpriteRenderer), nameof(PolytopiaSpriteRenderer.ForceUpdateMesh))]

src/Plugin.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ internal const string INCOMPATIBILITY_WARNING_LAST_VERSION_KEY
5353
/// </summary>
5454
public static readonly string DUMPED_DATA_PATH = Path.Combine(BASE_PATH, "DumpedData");
5555

56+
/// <summary>
57+
/// The path to the directory where localization is dumped.
58+
/// </summary>
59+
public static readonly string LOGIC_DUMP_PATH = Path.Combine(DUMPED_DATA_PATH, "Logic");
60+
61+
/// <summary>
62+
/// The path to the directory where gameLogicData and avatarData are dumped.
63+
/// </summary>
64+
public static readonly string LOCALIZATION_DUMP_PATH = Path.Combine(DUMPED_DATA_PATH, "Localization");
65+
5666
/// <summary>
5767
/// The path to the PolyMod configuration file.
5868
/// </summary>

0 commit comments

Comments
 (0)