Skip to content

Commit b3348ec

Browse files
committed
Updated PolyMod to latest version and added working logic. Yet to fix all the bugs
2 parents d50195b + 029c7fa commit b3348ec

24 files changed

+2969
-494
lines changed

FodyWeavers.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
3+
<Costura>
4+
<IncludeAssemblies>
5+
Scriban
6+
</IncludeAssemblies>
7+
</Costura>
8+
</Weavers>

PolyMod.csproj

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<TargetFramework>net6.0</TargetFramework>
44
<ImplicitUsings>enable</ImplicitUsings>
@@ -10,7 +10,7 @@
1010
https://polymod.dev/nuget/v3/index.json;
1111
</RestoreAdditionalProjectSources>
1212
<Configurations>IL2CPP</Configurations>
13-
<Version>1.3.0-pre</Version>
13+
<Version>1.2.6-104</Version>
1414
<PolytopiaVersion>2.9.1.12223</PolytopiaVersion>
1515
<Authors>PolyModdingTeam</Authors>
1616
<Description>The Battle of Polytopia's mod loader.</Description>
@@ -19,7 +19,11 @@
1919
</PropertyGroup>
2020

2121
<ItemGroup>
22-
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.733" />
22+
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.738" />
23+
<PackageReference Include="Costura.Fody" Version="6.0.0">
24+
<PrivateAssets>all</PrivateAssets>
25+
</PackageReference>
26+
<PackageReference Include="Scriban" Version="6.2.1" />
2327
<PackageReference Include="TheBattleOfPolytopia" Version="$(PolytopiaVersion)" />
2428
<EmbeddedResource Include="resources\*.*" />
2529
</ItemGroup>

installer/main.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
"win32": "win",
1616
"darwin": "macos",
1717
}[sys.platform]
18-
BEPINEX = f"733/BepInEx-Unity.IL2CPP-{OS}-x64-6.0.0-be.733%2B995f049"
19-
POLYMOD = "https://github.com/PolyModdingTeam/PolyMod/releases/latest/download/PolyMod.dll"
18+
BEPINEX = "https://polymod.dev/data/bepinex.txt"
19+
POLYMOD = "https://api.github.com/repos/PolyModdingTeam/PolyMod/releases"
2020

2121

2222
def resource_path(path):
@@ -54,6 +54,7 @@ def prepare(target):
5454
return
5555
path_entry.configure(state=customtkinter.DISABLED)
5656
browse_button.configure(state=customtkinter.DISABLED)
57+
prerelease_checkbox.destroy()
5758
install_button.destroy()
5859
uninstall_button.destroy()
5960
progress_bar = customtkinter.CTkProgressBar(app, determinate_speed=50 / 2)
@@ -65,13 +66,17 @@ def prepare(target):
6566
def install(path):
6667
to_zip(
6768
requests.get(
68-
f"https://builds.bepinex.dev/projects/bepinex_be/{BEPINEX}.zip"
69+
requests.get(BEPINEX).text.strip().replace("{os}", OS)
6970
)
7071
).extractall(path)
7172
progress_bar.step()
7273

74+
for release in requests.get(POLYMOD).json():
75+
if release["prerelease"] and not prerelease_checkbox.get(): continue
76+
latest = release
77+
break
7378
open(path + "/BepInEx/plugins/PolyMod.dll", "wb").write(
74-
requests.get(POLYMOD).content
79+
requests.get(latest["assets"][0]["browser_download_url"]).content
7580
)
7681
progress_bar.step()
7782

@@ -133,14 +138,17 @@ def quit():
133138
app, placeholder_text="Game path", width=228)
134139
browse_button = customtkinter.CTkButton(
135140
app, text="Browse", command=browse, width=1)
141+
prerelease_checkbox = customtkinter.CTkCheckBox(
142+
app, text="Prerelease", width=1)
136143
install_button = customtkinter.CTkButton(
137144
app, text="Install", command=lambda: prepare(install))
138145
uninstall_button = customtkinter.CTkButton(
139146
app, text="Uninstall", command=lambda: prepare(uninstall))
140147

141148
path_entry.grid(column=0, row=0, padx=5, pady=5)
142149
browse_button.grid(column=1, row=0, padx=(0, 5), pady=5)
143-
install_button.grid(column=0, row=1, columnspan=2, padx=5, pady=5)
144-
uninstall_button.grid(column=0, row=2, columnspan=2, padx=5, pady=5)
150+
prerelease_checkbox.grid(column=0, row=1, columnspan=2, padx=5, pady=5)
151+
install_button.grid(column=0, row=2, columnspan=2, padx=5, pady=5)
152+
uninstall_button.grid(column=0, row=3, columnspan=2, padx=5, pady=5)
145153

146154
app.mainloop()

resources/localization.json

Lines changed: 95 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@
2222
"German (Germany)": "UNSER DISCORD"
2323
},
2424
"polymod_hub_footer": {
25-
"English": "Join our discord! Feel free to discuss mods, create them and ask for help!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
26-
"Russian": "Присоединяйтесь к нашему дискорду! Не стесняйтесь обсуждать моды, создавать их и просить о помощи!\n\n{0}Особая благодарность{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
27-
"Turkish": "Discord sunucumuza katıl! Orada modlar oluşturabilir, tartışabilir ve yardım isteyebilirsin!\n\n{0}Hepinize çok teşekkür ederim:{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
28-
"Spanish (Mexico)": "Unete a nuestro discord! Aqui se puede discutir sobre la modificacion del juego, guias para crear su propio, preguntar a los creadores, y mas!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
29-
"French (France)": "Rejoignez notre discord! N'hésitez pas à discuter des mods, à en créer et à demander de l'aide!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
30-
"Polish": "Dołącz do naszego discorda! Zachęcamy do omawiania modów, tworzenia ich lub proszenia o pomoc!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
31-
"Portuguese (Brazil)": "Entre no nosso Discord! Sinta-se à vontade para discutir sobre os mods, criar novos mods e pedir ajuda!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
32-
"Elyrion": "§ii∫ Δi^#ȱrΔ! Δi^#₺^^ mȱΔ#, ȱrrȱ ỹ a^š ỹȱπ!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
33-
"German (Germany)": "Tritt unserem Discord bei, um Hilfe zu bekommen, Mods zu diskutieren oder sogar selbst zu erstellen!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon"
25+
"English": "Join our discord! Feel free to discuss mods, create them and ask for help!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nincomplete_tree\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
26+
"Russian": "Присоединяйтесь к нашему дискорду! Не стесняйтесь обсуждать моды, создавать их и просить о помощи!\n\n{0}Особая благодарность{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nincomplete_tree\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
27+
"Turkish": "Discord sunucumuza katıl! Orada modlar oluşturabilir, tartışabilir ve yardım isteyebilirsin!\n\n{0}Hepinize çok teşekkür ederim:{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nincomplete_tree\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
28+
"Spanish (Mexico)": "Unete a nuestro discord! Aqui se puede discutir sobre la modificacion del juego, guias para crear su propio, preguntar a los creadores, y mas!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nincomplete_tree\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
29+
"French (France)": "Rejoignez notre discord! N'hésitez pas à discuter des mods, à en créer et à demander de l'aide!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nincomplete_tree\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
30+
"Polish": "Dołącz do naszego discorda! Zachęcamy do omawiania modów, tworzenia ich lub proszenia o pomoc!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nincomplete_tree\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
31+
"Portuguese (Brazil)": "Entre no nosso Discord! Sinta-se à vontade para discutir sobre os mods, criar novos mods e pedir ajuda!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nincomplete_tree\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
32+
"Elyrion": "§ii∫ Δi^#ȱrΔ! Δi^#₺^^ mȱΔ#, ȱrrȱ ỹ a^š ỹȱπ!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nincomplete_tree\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon",
33+
"German (Germany)": "Tritt unserem Discord bei, um Hilfe zu bekommen, Mods zu diskutieren oder sogar selbst zu erstellen!\n\n{0}Special thanks{1}\n___exploit___\njohnklipi\nhighflyer\nMRB\nincomplete_tree\nArtemis\nParanoia\nNyrrv\nCitillan\nLukasAyas\nVaM\nWhail\nBrober\nMaradon"
3434
},
3535
"polymod_hub_header": {
3636
"English": "{0}Welcome!{1}\nHere you can see the list of all currently loaded mods:",
@@ -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}",
@@ -107,8 +107,8 @@
107107
"German (Germany)": "Benötigte Dependenzen nicht aufgefunden"
108108
},
109109
"polymod_signature_incompatible": {
110-
"English": "Current mods are not compatible with original mods!",
111-
"Russian": "Текущие моды несовместимы с оригинальными модами!",
110+
"English": "Current mods are not compatible with mods of this game!",
111+
"Russian": "Текущие моды несовместимы с модами этого матча!",
112112
"Turkish": "Mevcut modlar orijinal modlarla uyumsuz!",
113113
"Spanish (Mexico)": "Falta de compatibilidad entre los mods concurrientes!",
114114
"French (France)": "Les mods actuels ne sont pas compatibles avec les mods originaux!",
@@ -160,5 +160,87 @@
160160
"Portuguese (Brazil)": "Essa versão do PolyMod não foi desenvolvida para a versão atual do aplicativo e pode não funcionar corretamente!",
161161
"Elyrion": "πȱ∫ỹmȱδ ƒƒƒƒƒƒƒ ŋȱŧ ȱrrȱ #₺rr∑ŋŧ ƒƒƒƒƒƒƒ ỹ maỹ ŋȱŧ ~ȱr§ #ȱrr∑#ŧ∫ỹ!",
162162
"German (Germany)": "Diese Version von PolyMod ist nicht für die aktuelle Version der Anwendung ausgelegt und könnte nicht funktionieren!"
163+
},
164+
"polymod_debug": {
165+
"English": "Debug",
166+
"Russian": "Дебаг",
167+
"Turkish": "Hata ayıklama",
168+
"Spanish (Mexico)": "Depurar",
169+
"French (France)": "Débogage",
170+
"Polish": "Debugowanie",
171+
"Portuguese (Brazil)": "Depurar",
172+
"Elyrion": "Δ∑o₺þ",
173+
"German (Germany)": "Debuggen"
174+
},
175+
"polymod_autoupdate": {
176+
"English": "Auto-update",
177+
"Russian": "Автообновление",
178+
"Turkish": "Otomatik güncelleme",
179+
"Spanish (Mexico)": "Actualización automática",
180+
"French (France)": "MAJ auto",
181+
"Polish": "Auto aktualizacja",
182+
"Portuguese (Brazil)": "Atualização automática",
183+
"Elyrion": "a₺Ŧȱ₺πΔaŦ∑",
184+
"German (Germany)": "Auto Aktualisierung"
185+
},
186+
"polymod_autoupdate_alpha": {
187+
"English": "Include alphas",
188+
"Russian": "Включить альфы",
189+
"Elyrion": "iŋ#∫₺Δ∑ a∫πţaȓ"
190+
},
191+
"polymod_autoupdate_description": {
192+
"English": "New update available!",
193+
"Russian": "Доступно новое обновление!",
194+
"Elyrion": "ŋ∑~ ₺πΔaŦ∑ a‡ai∫ao∫∑"
195+
},
196+
"polymod_autoupdate_update": {
197+
"English": "Update",
198+
"Russian": "Обновить",
199+
"Elyrion": "₺πΔaŦ∑"
200+
},
201+
"polymod_hub_config": {
202+
"English": "CONFIG",
203+
"Russian": "КОНФИГ",
204+
"Elyrion": "#ȱŋ₼iþ"
205+
},
206+
"polymod_hub_config_enable": {
207+
"English": "ENABLE {0}",
208+
"Russian": "ВКЛЮЧИТЬ {0}",
209+
"Elyrion": "∑ŋao∫∑ {0}"
210+
},
211+
"polymod_hub_config_disable": {
212+
"English": "DISABLE {0}",
213+
"Russian": "ВЫКЛЮЧИТЬ {0}",
214+
"Elyrion": "Δiȓao∫∑ {0}"
215+
},
216+
"polymod_config_setto": {
217+
"English": "{0} is set to {1}!",
218+
"Russian": "{0} задан на {1}!",
219+
"Elyrion": "{0} iȓ ȓ∑Ŧ Ŧȱ {1}!"
220+
},
221+
"polymod_hub_spriteinfo_update": {
222+
"English": "UPDATE SPRITES",
223+
"Russian": "ОБНОВИТЬ СПРАЙТЫ",
224+
"Elyrion": "₺πΔaŦ∑ ȓπriŦ∑ȓ"
225+
},
226+
"polymod_spriteinfo_updated": {
227+
"English": "Sprite info for mod {0} updated!",
228+
"Russian": "Данные спрайтов обновлены для мода {0}!",
229+
"Elyrion": "ȓπriŦ∑ iŋ₼ȱ ₼ȱr mȱΔ {0} ₺πΔaŦ∑Δ!"
230+
},
231+
"polymod_spriteinfo_notupdated": {
232+
"English": "No sprite infos were found!",
233+
"Russian": "Данные спрайтов не найдены!",
234+
"Elyrion": "ŋȱ ȓπriŦ∑ iŋ₼ȱȓ ~∑r∑ ₼ȱ₺ŋΔ!"
235+
},
236+
"polymod_wc_warning": {
237+
"English": "{0} may not work correctly due to PolyMod. Do you wish to proceed?",
238+
"Russian": "{0} может работать некорректно из-за PolyMod'а. Вы уверены что хотите продолжить?",
239+
"Elyrion": "{0} maỹ ŋȱŦ ~ȱr§ #ȱrr∑#Ŧ∫ỹ Δ₺∑ Ŧȱ πȱ∫ỹmȱΔ. Δȱ ỹȱ₺ ~iȓţ Ŧȱ πrȱ#∑∑Δ?"
240+
},
241+
"polymod_wc_proceed": {
242+
"English": "PROCEED",
243+
"Russian": "ПРОДОЛЖИТЬ",
244+
"Elyrion": "πrȱ#∑∑Δ"
163245
}
164246
}

src/Api/Config.cs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Nodes;
3+
4+
namespace PolyMod.Api;
5+
6+
/// <summary>
7+
/// Allows mods to save config.
8+
/// </summary>
9+
public class Config<T> where T : class
10+
{
11+
private T? currentConfig;
12+
private readonly string modName;
13+
private readonly ConfigTypes configType;
14+
private static readonly string ExposedConfigPath = Path.Combine(Plugin.BASE_PATH, "mods.json");
15+
private readonly string perModConfigPath;
16+
private T? defaultConfig;
17+
public Config(string modName, ConfigTypes configType)
18+
{
19+
this.modName = modName;
20+
this.configType = configType;
21+
perModConfigPath = Path.Combine(Plugin.MODS_PATH, $"{modName}.json");
22+
Load();
23+
}
24+
25+
internal void Load() // can be called internally if config changes; gui config not implemented yet
26+
{
27+
switch (configType)
28+
{
29+
case ConfigTypes.PerMod:
30+
{
31+
if (!File.Exists(perModConfigPath))
32+
{
33+
return;
34+
}
35+
var jsonText = File.ReadAllText(perModConfigPath);
36+
currentConfig = JsonSerializer.Deserialize<T>(jsonText);
37+
break;
38+
}
39+
case ConfigTypes.Exposed:
40+
{
41+
if (!File.Exists(ExposedConfigPath))
42+
{
43+
return;
44+
}
45+
var jsonText = File.ReadAllText(ExposedConfigPath);
46+
currentConfig = JsonNode.Parse(jsonText)![modName]?.Deserialize<T>();
47+
break;
48+
}
49+
default:
50+
throw new ArgumentOutOfRangeException();
51+
}
52+
}
53+
/// <summary>
54+
/// Sets the default if the config does not exist yet. Always call this before reading from the config.
55+
/// </summary>
56+
public void SetDefaultConfig(T defaultValue)
57+
{
58+
defaultConfig = defaultValue;
59+
if (currentConfig is not null) return;
60+
Write(defaultConfig);
61+
SaveChanges();
62+
}
63+
64+
/// <summary>
65+
/// Writes the **entire** config. Usage not recommended, use Edit() instead
66+
/// </summary>
67+
public void Write(T config)
68+
{
69+
currentConfig = config;
70+
}
71+
/// <summary>
72+
/// Gets the config. Should only be called after setting a default.
73+
/// </summary>
74+
public T Get()
75+
{
76+
return currentConfig ?? throw new InvalidOperationException("Must set default before reading config.");
77+
}
78+
/// <summary>
79+
/// Edits the config. Should only be called after setting a default.
80+
/// </summary>
81+
/// <remarks>Call SaveChanges after editing</remarks>
82+
public void Edit(Action<T> editor)
83+
{
84+
editor(currentConfig ?? throw new InvalidOperationException("Must set default before reading config."));
85+
}
86+
/// <summary>
87+
/// Gets part of the config. Should only be called after setting a default
88+
/// </summary>
89+
public TResult Get<TResult>(Func<T, TResult> getter)
90+
{
91+
return getter(currentConfig ?? throw new InvalidOperationException("Must set default before reading config."));
92+
}
93+
/// <summary>
94+
/// Writes the config to disk
95+
/// </summary>
96+
public void SaveChanges()
97+
{
98+
switch (configType)
99+
{
100+
case ConfigTypes.PerMod:
101+
var perModJson = JsonSerializer.Serialize(currentConfig, new JsonSerializerOptions { WriteIndented = true });
102+
File.WriteAllText(perModConfigPath, perModJson);
103+
break;
104+
case ConfigTypes.Exposed:
105+
var modsConfigText = File.ReadAllText(ExposedConfigPath);
106+
var modsConfigJson = JsonNode.Parse(modsConfigText)!.AsObject();
107+
modsConfigJson[modName] = JsonSerializer.SerializeToNode(currentConfig!);
108+
File.WriteAllText(ExposedConfigPath, modsConfigJson.ToJsonString(new JsonSerializerOptions { WriteIndented = true }));
109+
break;
110+
default:
111+
throw new ArgumentOutOfRangeException();
112+
}
113+
}
114+
115+
public enum ConfigTypes
116+
{
117+
PerMod,
118+
Exposed
119+
}
120+
}

0 commit comments

Comments
 (0)