Skip to content

Commit 9419ba9

Browse files
committed
make savefile import handle current/old game versions correctly
1 parent ddb0252 commit 9419ba9

11 files changed

Lines changed: 172 additions & 88 deletions

File tree

Languages/English/Keyed/Keyed.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<ModSwitch.Import>Import</ModSwitch.Import>
2525
<ModSwitch.Import.Savegame>Savegame</ModSwitch.Import.Savegame>
2626
<ModSwitch.Import.FromFile>From File</ModSwitch.Import.FromFile>
27+
<ModSwitch.Import.OpenFolder>Open import/export folder</ModSwitch.Import.OpenFolder>
2728

2829
<ModSwitch.ModSet.Mods>{0} items</ModSwitch.ModSet.Mods>
2930

@@ -36,7 +37,8 @@
3637
<ModSwitch.MissingMods.Choice.Ignore>Ignore</ModSwitch.MissingMods.Choice.Ignore>
3738
<ModSwitch.MissingMods.Choice.Ignore.Tip>Ignore the missing mods.</ModSwitch.MissingMods.Choice.Ignore.Tip>
3839
<ModSwitch.MissingMods.Choice.Workshop>Cancel &amp; Open workshop</ModSwitch.MissingMods.Choice.Workshop>
39-
<ModSwitch.MissingMods.Choice.Workshop.Tip>Dont apply the Mod Set. Instead try retrieving applicable mods from the Steam Workshop. Keep in mind those mods might no longer be available.</ModSwitch.MissingMods.Choice.Workshop.Tip>
40+
<ModSwitch.MissingMods.Choice.Workshop_Apply.Tip>Dont apply the Mod Set. Instead try retrieving applicable mods from the Steam Workshop. Keep in mind those mods might no longer be available.</ModSwitch.MissingMods.Choice.Workshop_Apply.Tip>
41+
<ModSwitch.MissingMods.Choice.Workshop_Import.Tip>Dont import the Mod Set. Instead try retrieving applicable mods from the Steam Workshop. Keep in mind those mods might no longer be available.</ModSwitch.MissingMods.Choice.Workshop_Import.Tip>
4042
<ModSwitch.MissingMods.Choice.Remove>Remove from Set</ModSwitch.MissingMods.Choice.Remove>
4143
<ModSwitch.MissingMods.Choice.Remove.Tip>Remove the missing mods from the stored Mod Set.</ModSwitch.MissingMods.Choice.Remove.Tip>
4244

Languages/Japanese/Keyed/Keyed.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
<ModSwitch.MissingMods.Choice.Ignore>無視する</ModSwitch.MissingMods.Choice.Ignore>
3535
<ModSwitch.MissingMods.Choice.Ignore.Tip>不足しているMODを無視します。</ModSwitch.MissingMods.Choice.Ignore.Tip>
3636
<ModSwitch.MissingMods.Choice.Workshop>中止してワークショップを開く</ModSwitch.MissingMods.Choice.Workshop>
37-
<ModSwitch.MissingMods.Choice.Workshop.Tip>このままMODセットを適用しないでください。代わりにSteamワークショップから該当するModを入手してみてください。それらのMODは、削除されていて利用できないかもしれません。</ModSwitch.MissingMods.Choice.Workshop.Tip>
37+
<ModSwitch.MissingMods.Choice.Workshop_Apply.Tip>このままMODセットを適用しないでください。代わりにSteamワークショップから該当するModを入手してみてください。それらのMODは、削除されていて利用できないかもしれません。</ModSwitch.MissingMods.Choice.Workshop_Apply.Tip>
3838
<ModSwitch.MissingMods.Choice.Remove>セットから削除</ModSwitch.MissingMods.Choice.Remove>
3939
<ModSwitch.MissingMods.Choice.Remove.Tip>不足しているMODを保存したMODセットから削除します。</ModSwitch.MissingMods.Choice.Remove.Tip>
4040

Source/ModSwitch/LanguageKeys.Generated.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ public static class @keyed {
8181
/// </summary>
8282
public const string @ModSwitch_Import_FromFile = "ModSwitch.Import.FromFile";
8383
/// <summary>
84+
/// Gets the translation key for '<em>Open import/export folder</em>'
85+
/// </summary>
86+
public const string @ModSwitch_Import_OpenFolder = "ModSwitch.Import.OpenFolder";
87+
/// <summary>
8488
/// Gets the translation key for '<em>{0} items</em>'
8589
/// </summary>
8690
public const string @ModSwitch_ModSet_Mods = "ModSwitch.ModSet.Mods";
@@ -115,7 +119,11 @@ public static class @keyed {
115119
/// <summary>
116120
/// Gets the translation key for '<em>Dont apply the Mod Set. Instead try retrieving applicable mods from the Steam Workshop. Keep in mind those mods might no longer be available.</em>'
117121
/// </summary>
118-
public const string @ModSwitch_MissingMods_Choice_Workshop_Tip = "ModSwitch.MissingMods.Choice.Workshop.Tip";
122+
public const string @ModSwitch_MissingMods_Choice_Workshop_Apply_Tip = "ModSwitch.MissingMods.Choice.Workshop_Apply.Tip";
123+
/// <summary>
124+
/// Gets the translation key for '<em>Dont import the Mod Set. Instead try retrieving applicable mods from the Steam Workshop. Keep in mind those mods might no longer be available.</em>'
125+
/// </summary>
126+
public const string @ModSwitch_MissingMods_Choice_Workshop_Import_Tip = "ModSwitch.MissingMods.Choice.Workshop_Import.Tip";
119127
/// <summary>
120128
/// Gets the translation key for '<em>Remove from Set</em>'
121129
/// </summary>

Source/ModSwitch/Model/ModSet.cs

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -67,31 +67,32 @@ public void Apply() {
6767
(m, idx) => new {
6868
id = m,
6969
Index = idx
70-
})
71-
.FullOuterJoin(
72-
ModLister.AllInstalledMods,
73-
t => t.id,
74-
mmd => mmd.FolderName,
75-
(t, mmd, s) => new {
76-
Key = s,
77-
SetIndex = t?.Index,
78-
Metadata = mmd
79-
})
80-
.ToArray();
70+
});
8171

8272
// partition by install status
83-
var notInstalled = tmp.Where(t => t.Metadata?.FolderName == null)
84-
.ToArray();
85-
var installedMods = tmp.Where(t => t.SetIndex != null && t.Metadata?.FolderName != null)
86-
.OrderBy(t => t.SetIndex)
87-
.Select(t => t.Metadata);
73+
var resolution = ModConfigUtil.TryResolveModsList(tmp,
74+
mmd => mmd.FolderName,
75+
t => t.id,
76+
(mmd, t) => new { Mod = mmd, Index = t.Index},
77+
(_, t) => t.id);
78+
79+
foreach (var x in resolution.Resolved) {
80+
Log.Message($"{x.Mod.Name} - {x.Index}");
81+
}
82+
83+
84+
string[] notInstalled =resolution.Unresolved;
85+
ModMetaData[] installedMods = resolution.Resolved
86+
.OrderBy(t => t.Index)
87+
.Select(t => t.Mod)
88+
.ToArray();
8889

8990
if (notInstalled.Length != 0) {
9091
var missing = notInstalled
9192
.Select(
92-
t => new {
93-
t.Key,
94-
IsSteam = rgxSteamModId.IsMatch(t.Key)
93+
s => new {
94+
Key = s,
95+
IsSteam = rgxSteamModId.IsMatch(s)
9596
})
9697
.OrderBy(t => t.Key)
9798
.ToArray();
@@ -108,11 +109,14 @@ public void Apply() {
108109
() => ApplyMods(installedMods),
109110
() => {
110111
// dont know how to open multiple tabs in steam overlay right now - just pop urls to browser ;)
111-
foreach (var mod in missing.Where(t => t.IsSteam))
112-
Process.Start($"http://steamcommunity.com/sharedfiles/filedetails/?id={mod.Key}");
112+
foreach (var mod in missing) {
113+
string url = Util.BuildWorkshopUrl(mod.Key, mod.Key);
114+
Process.Start(url);
115+
}
116+
113117
},
114118
() => {
115-
Mods.RemoveAll(s => notInstalled.Any(ni => ni.Key == s));
119+
Mods.RemoveAll(s => notInstalled.Any(ni => ni == s));
116120
_owner.Mod.WriteSettings();
117121
ApplyMods(installedMods);
118122
}

Source/ModSwitch/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
[assembly: System.Reflection.AssemblyCopyright("Copyright © DoctorVanGogh 2017")]
1313
[assembly: System.Runtime.InteropServices.ComVisible(false)]
1414
[assembly: System.Runtime.InteropServices.Guid("ab2e8e89-3d1d-4e36-a0ae-489b6ebc84a6")]
15-
[assembly: System.Reflection.AssemblyVersion("2.0.0.258")]
15+
[assembly: System.Reflection.AssemblyVersion("2.0.0.273")]
1616

1717

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.0.0.258
1+
2.0.0.273

Source/ModSwitch/Settings.cs

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Reflection;
66
using System.IO;
77
using System.Linq;
8+
using System.Text;
89
using System.Xml;
910
using RimWorld;
1011
using UnityEngine;
@@ -121,6 +122,14 @@ public void DoWindowContents(Rect rect) {
121122
Find.WindowStack.Add(
122123
new FloatMenu(
123124
new List<FloatMenuOption> {
125+
new FloatMenuOption(
126+
LanguageKeys.keyed.ModSwitch_Import_OpenFolder.Translate(),
127+
() => {
128+
MS_GenFilePaths.EnsureExportFolderExists();
129+
130+
Process.Start(MS_GenFilePaths.ModSwitchFolderPath);
131+
}
132+
),
124133
new FloatMenuOption(
125134
LanguageKeys.keyed.ModSwitch_Import_FromFile.Translate(),
126135
() => {
@@ -163,15 +172,9 @@ public void DoWindowContents(Rect rect) {
163172
absorbInputAroundWindow = true,
164173
closeOnClickedOutside = true,
165174
doCloseX = true
166-
}))
175+
})),
167176
}));
168177

169-
if (list.ButtonTextLabeled("Import/Export location", "Open folder")) {
170-
MS_GenFilePaths.EnsureExportFolderExists();
171-
172-
Process.Start(MS_GenFilePaths.ModSwitchFolderPath);
173-
}
174-
175178
#if DEBUG
176179
if (list.ButtonTextLabeled("Debug", "ListExisting")) {
177180
foreach (var modSet in Sets) {
@@ -219,28 +222,76 @@ public override void ExposeData() {
219222
}
220223

221224
private void ImportFromSave(FileInfo fi) {
222-
Scribe.loader.InitLoadingMetaHeaderOnly(fi.FullName);
223-
try {
224-
ScribeMetaHeaderUtility.LoadGameDataHeader(ScribeMetaHeaderUtility.ScribeHeaderMode.Map, false);
225-
Scribe.loader.FinalizeLoading();
226225

227-
int suffix = 0;
228-
string name = fi.Name;
229-
while (Sets.Any(ms => ms.Name == name))
230-
name = $"{fi.Name}_{++suffix}";
226+
void AddModSet(string name, IEnumerable<ModMetaData> mods) {
231227
Sets.Add(
232-
new ModSet(this) {
228+
new ModSet(this) {
233229
Name = name,
234230
BuildNumber = new Version(VersionControl.VersionStringWithoutRev(ScribeMetaHeaderUtility.loadedGameVersion)).Build,
235-
Mods = new List<string>(ScribeMetaHeaderUtility.loadedModIdsList)
231+
Mods = new List<string>(mods.Select(mmd => mmd.FolderName))
236232
});
237233
Mod.WriteSettings();
234+
}
235+
236+
237+
Scribe.loader.InitLoadingMetaHeaderOnly(fi.FullName);
238+
try {
239+
ScribeMetaHeaderUtility.LoadGameDataHeader(ScribeMetaHeaderUtility.ScribeHeaderMode.Map, false);
240+
Scribe.loader.FinalizeLoading();
241+
242+
int suffix = 0;
243+
string setname = fi.Name;
244+
while (Sets.Any(ms => ms.Name == setname))
245+
setname = $"{fi.Name}_{++suffix}";
246+
247+
var modsFromSave = ScribeMetaHeaderUtility.loadedModIdsList
248+
.Zip(ScribeMetaHeaderUtility.loadedModNamesList, (id, name) => new {Id = id, Name = name})
249+
.Select((t, idx) => new { Id = t.Id, Name = t.Name, Index = idx});
250+
251+
252+
Log.Message($"Loaded version: '{ScribeMetaHeaderUtility.loadedGameVersion}'");
253+
254+
var idAccessor = Util.GetVersionSpecificIdMapping(VersionControl.VersionFromString(VersionControl.VersionStringWithoutRev(ScribeMetaHeaderUtility.loadedGameVersion)));
255+
256+
var (resolved, unresolved) = ModConfigUtil.TryResolveModsList(
257+
modsFromSave,
258+
idAccessor,
259+
t => t.Id,
260+
(mmd, t) => new {Mod = mmd, Index = t.Index },
261+
(_, t) => new {Name = t.Name, Id = t.Id});
262+
263+
var loadableMods = resolved.OrderBy(t => t.Index).Select(t => t.Mod);
264+
265+
StringBuilder sb = new StringBuilder(LanguageKeys.keyed.ModSwitch_MissingMods.Translate(Path.GetFileNameWithoutExtension(fi.Name)));
266+
sb.AppendLine();
267+
sb.AppendLine();
268+
foreach (var item in unresolved)
269+
sb.AppendLine($" - {item.Name} ({item.Id})");
270+
271+
if (unresolved.Any()) {
272+
Find.WindowStack.Add(
273+
new Dialog_MissingMods(
274+
sb.ToString(),
275+
() => AddModSet(setname, loadableMods),
276+
() => {
277+
// dont know how to open multiple tabs in steam overlay right now - just pop urls to browser ;)
278+
foreach (var mod in unresolved) {
279+
string url = Util.BuildWorkshopUrl(mod.Name, mod.Id);
280+
Process.Start(url);
281+
}
282+
},
283+
null
284+
));
285+
}
286+
287+
AddModSet(setname, loadableMods);
238288
} catch (Exception ex) {
239289
Log.Warning(string.Concat("Exception loading ", fi.FullName, ": ", ex));
240290
Scribe.ForceStop();
241291

242292
}
243293
}
294+
244295

245296
private void ImportFromExport(FileInfo fi){
246297
if (File.Exists(fi.FullName)) {

Source/ModSwitch/[UI]/Dialog_MissingMods.cs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
using Verse;
44

55
namespace DoctorVanGogh.ModSwitch {
6+
public enum ModSetAction {
7+
Apply = 0,
8+
Import
9+
}
10+
611
public class Dialog_MissingMods : Window {
712
private const float TitleHeight = 42f;
813
private const float ButtonHeight = 35f;
@@ -19,6 +24,8 @@ public class Dialog_MissingMods : Window {
1924

2025
public string text;
2126

27+
public ModSetAction Trigger { get; set; } = ModSetAction.Apply;
28+
2229
public Dialog_MissingMods(string text, Action ignore, Action workshop, Action remove) {
2330
this.text = text;
2431
defaultAction = ignore;
@@ -77,15 +84,18 @@ public override void DoWindowContents(Rect inRect) {
7784
2,
7885
LanguageKeys.keyed.ModSwitch_MissingMods_Choice_Workshop.Translate(),
7986
_workshop,
80-
LanguageKeys.keyed.ModSwitch_MissingMods_Choice_Workshop_Tip.Translate(),
87+
Trigger == ModSetAction.Apply
88+
? LanguageKeys.keyed.ModSwitch_MissingMods_Choice_Workshop_Apply_Tip.Translate()
89+
: LanguageKeys.keyed.ModSwitch_MissingMods_Choice_Workshop_Import_Tip.Translate(),
8190
false);
82-
AddButton(
83-
inRect,
84-
3,
85-
LanguageKeys.keyed.ModSwitch_MissingMods_Choice_Remove.Translate(),
86-
_remove,
87-
LanguageKeys.keyed.ModSwitch_MissingMods_Choice_Remove_Tip.Translate(),
88-
true);
91+
if (_remove != null)
92+
AddButton(
93+
inRect,
94+
3,
95+
LanguageKeys.keyed.ModSwitch_MissingMods_Choice_Remove.Translate(),
96+
_remove,
97+
LanguageKeys.keyed.ModSwitch_MissingMods_Choice_Remove_Tip.Translate(),
98+
true);
8999
}
90100
}
91101
}

0 commit comments

Comments
 (0)