Skip to content

Commit cb6e747

Browse files
Merge branch 'dev1.2' into autoupdate
2 parents 5bd58c5 + b9675a3 commit cb6e747

File tree

9 files changed

+155
-43
lines changed

9 files changed

+155
-43
lines changed

PolyMod.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
https://polymod.dev/nuget/v3/index.json;
1111
</RestoreAdditionalProjectSources>
1212
<Configurations>IL2CPP</Configurations>
13-
<Version>1.1.7</Version>
13+
<Version>1.2.0-pre</Version>
1414
<PolytopiaVersion>2.12.3.14031</PolytopiaVersion>
1515
<Authors>PolyModdingTeam</Authors>
1616
<Description>The Battle of Polytopia's mod loader.</Description>

resources/localization.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
"German (Germany)": "{0} Willkommen! {1}\nDiese Mods sind gerade eben geladen:"
4545
},
4646
"polymod_hub_mod": {
47-
"English": "Name: {0}\nStatus: {1}\nAuthors: {2}\nVersion: {3}",
48-
"Russian": "Имя: {0}\nСтатус: {1}\nАвторы: {2}\nВерсия: {3}",
47+
"English": "Name: {0}\nStatus: {1}\nAuthors: {2}\nVersion: {3}\nDescription: {4}",
48+
"Russian": "Имя: {0}\nСтатус: {1}\nАвторы: {2}\nВерсия: {3}\nОписание: {4}",
4949
"Turkish": "İsim: {0}\nDurum: {1}\nYaratıcılar: {2}\nSürüm: {3}",
5050
"Spanish (Mexico)": "Titulo: {0}\nEstado: {1}\nPublicador: {2}\nVersion: {3}",
5151
"French (France)": "Titre: {0}\nEtat: {1}\nAuteurs: {2}\nVersion: {3}",

src/Loader.cs

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using PolyMod.Json;
77
using PolyMod.Managers;
88
using Polytopia.Data;
9+
using PolytopiaBackendBase.Game;
910
using System.Data;
1011
using System.Diagnostics;
1112
using System.Globalization;
@@ -32,6 +33,16 @@ public static class Loader
3233
{ "improvementAbility", typeof(ImprovementAbility.Type) },
3334
{ "playerAbility", typeof(PlayerAbility.Type) }
3435
};
36+
internal static List<GameModeButtonsInformation> gamemodes = new();
37+
public record GameModeButtonsInformation(int gameModeIndex, UIButtonBase.ButtonAction action, int? buttonIndex, Sprite? sprite);
38+
39+
public static void AddGameModeButton(string id, UIButtonBase.ButtonAction action, Sprite? sprite)
40+
{
41+
EnumCache<GameMode>.AddMapping(id, (GameMode)Registry.gameModesAutoidx);
42+
EnumCache<GameMode>.AddMapping(id, (GameMode)Registry.gameModesAutoidx);
43+
gamemodes.Add(new GameModeButtonsInformation(Registry.gameModesAutoidx, action, null, sprite));
44+
Registry.gameModesAutoidx++;
45+
}
3546

3647
public static void AddPatchDataType(string typeId, Type type)
3748
{
@@ -88,30 +99,42 @@ internal static void LoadMods(Dictionary<string, Mod> mods)
8899
}
89100
}
90101

91-
if (manifest != null
92-
&& manifest.id != null
93-
&& Regex.IsMatch(manifest.id, @"^(?!polytopia$)[a-z_]+$")
94-
&& manifest.version != null
95-
&& manifest.authors != null
96-
&& manifest.authors.Length != 0
97-
)
102+
if (manifest == null)
98103
{
99-
if (mods.ContainsKey(manifest.id))
100-
{
101-
Plugin.logger.LogError($"Mod {manifest.id} already exists");
102-
continue;
103-
}
104-
mods.Add(manifest.id, new(
105-
manifest,
106-
Mod.Status.Success,
107-
files
108-
));
109-
Plugin.logger.LogInfo($"Registered mod {manifest.id}");
104+
Plugin.logger.LogError($"Mod manifest not found in {modContainer}");
105+
continue;
110106
}
111-
else
107+
if (manifest.id == null)
108+
{
109+
Plugin.logger.LogError($"Mod id not found in {modContainer}");
110+
continue;
111+
}
112+
if (!Regex.IsMatch(manifest.id, @"^(?!polytopia$)[a-z_]+$"))
112113
{
113-
Plugin.logger.LogError("An invalid mod manifest was found or not found at all");
114+
Plugin.logger.LogError($"Mod id {manifest.id} is invalid in {modContainer}");
115+
continue;
114116
}
117+
if (manifest.version == null)
118+
{
119+
Plugin.logger.LogError($"Mod version not found in {modContainer}");
120+
continue;
121+
}
122+
if (manifest.authors == null || manifest.authors.Length == 0)
123+
{
124+
Plugin.logger.LogError($"Mod authors not found in {modContainer}");
125+
continue;
126+
}
127+
if (mods.ContainsKey(manifest.id))
128+
{
129+
Plugin.logger.LogError($"Mod {manifest.id} already exists");
130+
continue;
131+
}
132+
mods.Add(manifest.id, new(
133+
manifest,
134+
Mod.Status.Success,
135+
files
136+
));
137+
Plugin.logger.LogInfo($"Registered mod {manifest.id}");
115138
}
116139

117140
foreach (var (id, mod) in mods)
@@ -408,6 +431,14 @@ public static void LoadGameLogicDataPatch(Mod mod, JObject gld, JObject patch)
408431
}
409432
}
410433

434+
public static void LoadAssetBundle(Mod mod, Mod.File file)
435+
{
436+
Registry.assetBundles.Add(
437+
Path.GetFileNameWithoutExtension(file.name),
438+
AssetBundle.LoadFromMemory(file.bytes)
439+
);
440+
}
441+
411442
public static void HandleSkins(JObject gld, JObject patch)
412443
{
413444
foreach (JToken jtoken in patch.SelectTokens("$.tribeData.*").ToArray())

src/Managers/Hub.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Cpp2IL.Core.Extensions;
22
using HarmonyLib;
3+
using I2.Loc;
34
using Il2CppInterop.Runtime;
45
using TMPro;
56
using UnityEngine;
@@ -121,7 +122,8 @@ static void PolyModHubButtonClicked(int buttonId, BaseEventData eventData)
121122
Localization.Get("polymod.hub.mod.status."
122123
+ Enum.GetName(typeof(Mod.Status), mod.status)!.ToLower()),
123124
string.Join(", ", mod.authors),
124-
mod.version.ToString()
125+
mod.version.ToString(),
126+
mod.description ?? ""
125127
});
126128
popup.Description += "\n\n";
127129
}
@@ -134,24 +136,29 @@ static void PolyModHubButtonClicked(int buttonId, BaseEventData eventData)
134136
new("buttons.back"),
135137
new(
136138
"polymod.hub.discord",
137-
callback: (UIButtonBase.ButtonAction)((int _, BaseEventData _) =>
139+
callback: (UIButtonBase.ButtonAction)((_, _) =>
138140
NativeHelpers.OpenURL(Plugin.DISCORD_LINK, false))
139141
)
140142
};
141143
if (Plugin.config.debug)
142144
popupButtons.Add(new(
143145
"polymod.hub.dump",
144-
callback: (UIButtonBase.ButtonAction)((int _, BaseEventData _) =>
146+
callback: (UIButtonBase.ButtonAction)((_, _) =>
145147
{
146148
Directory.CreateDirectory(Plugin.DUMPED_DATA_PATH);
147149
File.WriteAllTextAsync(
148-
Path.Combine(Plugin.DUMPED_DATA_PATH, $"gameLogicData.json"),
150+
Path.Combine(Plugin.DUMPED_DATA_PATH, "gameLogicData.json"),
149151
PolytopiaDataManager.provider.LoadGameLogicData(VersionManager.GameLogicDataVersion)
150152
);
151153
File.WriteAllTextAsync(
152-
Path.Combine(Plugin.DUMPED_DATA_PATH, $"avatarData.json"),
154+
Path.Combine(Plugin.DUMPED_DATA_PATH, "avatarData.json"),
153155
PolytopiaDataManager.provider.LoadAvatarData(1337)
154156
);
157+
foreach (var category in LocalizationManager.Sources[0].GetCategories())
158+
File.WriteAllTextAsync(
159+
Path.Combine(Plugin.DUMPED_DATA_PATH, $"localization_{category}.csv"),
160+
LocalizationManager.Sources[0].Export_CSV(category)
161+
);
155162
NotificationManager.Notify(Localization.Get("polymod.hub.dumped"));
156163
}),
157164
closesPopup: false

src/Managers/Loc.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ private static bool Localization_Get(ref string key, Il2CppReferenceArray<Il2Cpp
3333
{
3434
if (int.TryParse(item, out int parsedIdx))
3535
{
36-
if(parsedIdx >= Plugin.AUTOIDX_STARTS_FROM)
36+
if (parsedIdx >= Plugin.AUTOIDX_STARTS_FROM)
3737
{
3838
idx = parsedIdx;
3939
}

src/Managers/Main.cs

Lines changed: 81 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using HarmonyLib;
33
using Newtonsoft.Json.Linq;
44
using Polytopia.Data;
5+
using PolytopiaBackendBase.Game;
56
using System.Diagnostics;
67
using System.Text;
78
using System.Text.Json;
@@ -70,13 +71,71 @@ private static bool IL2CPPUnityLogSource_UnityLogCallback(string logLine, string
7071
return true;
7172
}
7273

74+
[HarmonyPrefix]
75+
[HarmonyPatch(typeof(GameModeScreen), nameof(GameModeScreen.Init))]
76+
private static void GameModeScreen_Init(GameModeScreen __instance)
77+
{
78+
List<GamemodeButton> list = __instance.buttons.ToList();
79+
for (int i = 0; i < Loader.gamemodes.Count; i++)
80+
{
81+
var item = Loader.gamemodes[i];
82+
var button = GameObject.Instantiate(__instance.buttons[2]);
83+
list.Add(button);
84+
Loader.gamemodes[i] = new Loader.GameModeButtonsInformation(item.gameModeIndex, item.action, __instance.buttons.Length, item.sprite);
85+
}
86+
87+
var newArray = list.ToArray();
88+
for (int i = 0; i < __instance.buttons.Length; i++)
89+
{
90+
if (newArray[i] != null) newArray[i].OnClicked = __instance.buttons[i].OnClicked;
91+
}
92+
93+
for (int i = 0; i < Loader.gamemodes.Count; i++)
94+
{
95+
if (Loader.gamemodes[i].buttonIndex != null)
96+
newArray[Loader.gamemodes[i].buttonIndex!.Value].OnClicked = Loader.gamemodes[i].action;
97+
}
98+
99+
__instance.buttons = newArray;
100+
101+
for (int i = 0; i < __instance.buttons.Length; i++)
102+
{
103+
GamemodeButton button = __instance.buttons[i];
104+
var newData = button.gamemodeData.ToList();
105+
foreach (var info in Loader.gamemodes)
106+
{
107+
string id = EnumCache<GameMode>.GetName((GameMode)info.gameModeIndex).ToLower();
108+
newData.Add(new GamemodeButton.GamemodeButtonData()
109+
{
110+
gameMode = (GameMode)info.gameModeIndex,
111+
id = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(id),
112+
descriptionKey = "gamemode." + id + ".description.button",
113+
headerKey = "gamemode." + id + ".caps",
114+
icon = info.sprite
115+
});
116+
}
117+
button.gamemodeData = newData.ToArray();
118+
119+
for (int j = 0; j < Loader.gamemodes.Count; j++)
120+
{
121+
Loader.GameModeButtonsInformation info = Loader.gamemodes[j];
122+
123+
if(info.buttonIndex == i)
124+
{
125+
button.SetGamemode(info.buttonIndex.Value);
126+
}
127+
}
128+
}
129+
}
130+
73131
internal static void Init()
74132
{
75133
stopwatch.Start();
76134
Harmony.CreateAndPatchAll(typeof(Main));
77135
Mod.Manifest polytopia = new(
78136
"polytopia",
79137
"The Battle of Polytopia",
138+
null,
80139
new(Application.version.ToString()),
81140
new string[] { "Midjiwan AB" },
82141
Array.Empty<Mod.Dependency>()
@@ -131,21 +190,31 @@ internal static void Load(JObject gameLogicdata)
131190
if (mod.status != Mod.Status.Success) continue;
132191
foreach (var file in mod.files)
133192
{
134-
if (Path.GetFileName(file.name) == "patch.json")
135-
{
136-
Loader.LoadGameLogicDataPatch(mod, gameLogicdata, JObject.Parse(new StreamReader(new MemoryStream(file.bytes)).ReadToEnd()));
137-
}
138-
if (Path.GetFileName(file.name) == "localization.json")
193+
switch (Path.GetFileName(file.name))
139194
{
140-
Loader.LoadLocalizationFile(mod, file);
195+
case "patch.json":
196+
Loader.LoadGameLogicDataPatch(
197+
mod,
198+
gameLogicdata,
199+
JObject.Parse(new StreamReader(new MemoryStream(file.bytes)).ReadToEnd())
200+
);
201+
break;
202+
case "localization.json":
203+
Loader.LoadLocalizationFile(mod, file);
204+
break;
141205
}
142-
if (Path.GetExtension(file.name) == ".png")
143-
{
144-
Loader.LoadSpriteFile(mod, file);
145-
}
146-
if (Path.GetExtension(file.name) == ".wav")
206+
207+
switch (Path.GetExtension(file.name))
147208
{
148-
Loader.LoadAudioFile(mod, file);
209+
case ".png":
210+
Loader.LoadSpriteFile(mod, file);
211+
break;
212+
case ".wav":
213+
Loader.LoadAudioFile(mod, file);
214+
break;
215+
case ".bundle":
216+
Loader.LoadAssetBundle(mod, file);
217+
break;
149218
}
150219
}
151220
}

src/Managers/Visual.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ void GetAtlas(SpriteAtlas spriteAtlas)
6565
if (spriteAtlas != null)
6666
{
6767
Sprite foundSprite = __instance.GetSpriteFromAtlas(spriteAtlas, sprite);
68-
if(foundSprite != null)
68+
if (foundSprite != null)
6969
{
7070
completion?.Invoke(atlas, sprite, __instance.GetSpriteFromAtlas(spriteAtlas, sprite));
7171
found = true;

src/Mod.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ namespace PolyMod;
22
public class Mod
33
{
44
public record Dependency(string id, Version min, Version max, bool required = true);
5-
public record Manifest(string id, string? name, Version version, string[] authors, Dependency[]? dependencies, bool client = false);
5+
public record Manifest(string id, string? name, string? description, Version version, string[] authors, Dependency[]? dependencies, bool client = false);
66
public record File(string name, byte[] bytes);
77
public enum Status
88
{
@@ -13,6 +13,7 @@ public enum Status
1313

1414
public string id;
1515
public string? name;
16+
public string? description;
1617
public Version version;
1718
public string[] authors;
1819
public Dependency[]? dependencies;
@@ -24,6 +25,7 @@ public Mod(Manifest manifest, Status status, List<File> files)
2425
{
2526
id = manifest.id;
2627
name = manifest.name ?? manifest.id;
28+
description = manifest.description;
2729
version = manifest.version;
2830
authors = manifest.authors;
2931
dependencies = manifest.dependencies;

src/Registry.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using LibCpp2IL;
22
using PolyMod.Managers;
33
using Polytopia.Data;
4+
using PolytopiaBackendBase.Game;
45
using UnityEngine;
56

67
namespace PolyMod;
@@ -12,9 +13,11 @@ public static class Registry
1213
internal static Dictionary<string, Mod> mods = new();
1314
public static Dictionary<string, Visual.PreviewTile[]> tribePreviews = new();
1415
public static Dictionary<string, Visual.SpriteInfo> spriteInfos = new();
16+
public static Dictionary<string, AssetBundle> assetBundles = new();
1517
public static List<TribeData.Type> customTribes = new();
1618
public static List<Visual.SkinInfo> skinInfo = new();
1719
public static int climateAutoidx = (int)Enum.GetValues(typeof(TribeData.Type)).Cast<TribeData.Type>().Last();
20+
public static int gameModesAutoidx = Enum.GetValues(typeof(GameMode)).Length;
1821

1922
public static Sprite? GetSprite(string name, string style = "", int level = 0)
2023
{

0 commit comments

Comments
 (0)