Skip to content

Commit 7bf5e7e

Browse files
committed
Restore pull request #899
1 parent c6d35da commit 7bf5e7e

4 files changed

Lines changed: 92 additions & 6 deletions

File tree

Celeste.Mod.mm/Content/Dialog/English.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@
187187
LEVELSET_CELESTE= Celeste
188188
LEVELSET_= Uncategorized
189189

190+
MISSING_VANILLA_DATA= Missing Vanilla data :(
191+
190192
# Updater
191193
UPDATER_TITLE= UPDATER
192194
UPDATER_LEGACYREF_TITLE= LEGACYREF SETUP

Celeste.Mod.mm/Patches/OuiFileSelect.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,31 @@
88
using Mono.Cecil;
99
using Mono.Cecil.Cil;
1010
using MonoMod.Cil;
11+
using Celeste.Mod;
1112

1213
namespace Celeste {
1314
class patch_OuiFileSelect : OuiFileSelect {
1415

1516
internal bool startingNewFile;
1617

18+
public extern void orig_LoadThread();
19+
public new void LoadThread() {
20+
orig_LoadThread();
21+
22+
string saveFilePath = patch_UserIO.GetSaveFilePath();
23+
if (!Directory.Exists(saveFilePath))
24+
return;
25+
26+
for (int i = 0; i < Slots.Count() - 1; i++) { // - 1, last slot is always empty
27+
if (!Slots[i].Exists && Directory.GetFiles(saveFilePath, $"{i}-mod*.celeste").Length > 0) {
28+
Logger.Warn("OuiFileSelect", $"Save slot {i} has modded data but no vanilla save data, flagging as corrupted");
29+
((patch_OuiFileSelectSlot) Slots[i]).MissingVanillaData = true;
30+
Slots[i].Corrupted = true;
31+
Slots[i].Exists = true; // both `Corrupted` and `Exists` flags must be set
32+
}
33+
}
34+
}
35+
1736
[PatchOuiFileSelectSubmenuChecks] // we want to manipulate the orig method with MonoModRules
1837
public extern IEnumerator orig_Enter(Oui from);
1938
public new IEnumerator Enter(Oui from) {
@@ -28,12 +47,16 @@ class patch_OuiFileSelect : OuiFileSelect {
2847
maxSaveFile = 1; // we're adding 2 later, so there will be at least 3 slots.
2948
string saveFilePath = patch_UserIO.GetSaveFilePath();
3049
if (Directory.Exists(saveFilePath)) {
31-
foreach (string filePath in Directory.GetFiles(saveFilePath)) {
50+
foreach (string filePath in Directory.GetFiles(saveFilePath, "*.celeste")) {
3251
string fileName = Path.GetFileName(filePath);
3352
// is the file named [number].celeste?
34-
if (fileName.EndsWith(".celeste") && int.TryParse(fileName.Substring(0, fileName.Length - 8), out int fileIndex)) {
53+
if (int.TryParse(fileName.Substring(0, fileName.Length - 8), out int fileIndex)) {
3554
maxSaveFile = Math.Max(maxSaveFile, fileIndex);
3655
}
56+
// or is the file mod data named [number]-mod[save|session]-[modname].celeste?
57+
if (fileName.Contains("-mod") && int.TryParse(fileName.Substring(0, fileName.IndexOf('-')), out int modFileIndex)) {
58+
maxSaveFile = Math.Max(maxSaveFile, modFileIndex);
59+
}
3760
}
3861
}
3962

Celeste.Mod.mm/Patches/OuiFileSelectSlot.cs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ public interface ISubmenu { }
4444

4545
private OuiFileSelectSlotLevelSetPicker newGameLevelSetPicker;
4646

47+
public bool MissingVanillaData;
48+
4749
// computed maximums for stamp rendering
4850
private int maxStrawberryCount;
4951
private int maxGoldenStrawberryCount;
@@ -204,8 +206,6 @@ private void OnExistingFileRenameSelected() {
204206

205207
public extern void orig_OnNewGameSelected();
206208
public void OnNewGameSelected() {
207-
patch_SaveData.TryDeleteModSaveData(FileSlot);
208-
209209
orig_OnNewGameSelected();
210210

211211
string newGameLevelSet = newGameLevelSetPicker?.NewGameLevelSet;
@@ -291,6 +291,7 @@ public class Button {
291291
public float Scale = 1f;
292292
}
293293

294+
[PatchFileSelectSlotRenderMissingVanillaDataDialog]
294295
[PatchFileSelectSlotRender] // manually manipulate the method via MonoModRules
295296
public extern void orig_Render();
296297
public override void Render() {
@@ -354,6 +355,12 @@ class PatchFileSelectSlotRenderAttribute : Attribute { }
354355
[MonoModCustomMethodAttribute(nameof(MonoModRules.PatchOuiFileSelectSlotOnContinueSelected))]
355356
class PatchOuiFileSelectSlotOnContinueSelectedAttribute : Attribute { }
356357

358+
/// <summary>
359+
/// Patches the method to differentiate between Corrupted and MissingVanillaData.
360+
/// </summary>
361+
[MonoModCustomMethodAttribute(nameof(MonoModRules.PatchFileSelectSlotRenderMissingVanillaDataDialog))]
362+
class PatchFileSelectSlotRenderMissingVanillaDataDialog : Attribute { }
363+
357364
static partial class MonoModRules {
358365

359366
public static void PatchOuiFileSelectSlotUpdate(ILContext context, CustomAttribute attrib) {
@@ -370,6 +377,48 @@ public static void PatchOuiFileSelectSlotUpdate(ILContext context, CustomAttribu
370377
cursor.Next.OpCode = OpCodes.Brfalse;
371378
}
372379

380+
public static void PatchFileSelectSlotRenderMissingVanillaDataDialog(ILContext context, CustomAttribute attrib) {
381+
TypeDefinition declaringType = context.Method.DeclaringType;
382+
FieldDefinition f_MissingVanillaData = declaringType.FindField("MissingVanillaData");
383+
384+
ILCursor cursor = new ILCursor(context);
385+
386+
// C# change:
387+
// [...]
388+
// else if (Corrupted)
389+
// {
390+
// - ActiveFont.Draw(Dialog.Clean("file_corrupted"), slide2, new Vector2(0.5f, 0.5f), Vector2.One, Color.Black * 0.8f);
391+
// + ActiveFont.Draw(Dialog.Clean((!MissingVanillaData) ? "file_corrupted" : "MISSING_VANILLA_DATA"), vector3, new Vector2(0.5f, 0.5f), Vector2.One, Color.Black * 0.8f);
392+
// }
393+
// [...]
394+
395+
// IL change:
396+
// [...]
397+
// ldfld System.Boolean Celeste.OuiFileSelectSlot::Corrupted
398+
// brfalse.s (...)
399+
// + ldarg.0
400+
// + ldfld bool Celeste.OuiFileSelectSlot::MissingVanillaData
401+
// + brfalse.s ldstr
402+
// + ldstr "MISSING_VANILLA_DATA"
403+
// + br.s ldnull
404+
// ldstr : ldstr "file_corrupted"
405+
// ldnull : ldnull
406+
// call string Celeste.Dialog::Clean(string, class Celeste.Language)
407+
// [...]
408+
409+
cursor.GotoNext(MoveType.Before, instr => instr.MatchLdstr("file_corrupted"));
410+
ILLabel ldstr = cursor.MarkLabel();
411+
cursor.GotoNext();
412+
ILLabel ldnull = cursor.MarkLabel();
413+
414+
cursor.GotoLabel(ldstr, MoveType.Before);
415+
cursor.EmitLdarg0();
416+
cursor.EmitLdfld(f_MissingVanillaData);
417+
cursor.EmitBrfalse(ldstr);
418+
cursor.EmitLdstr("MISSING_VANILLA_DATA");
419+
cursor.EmitBr(ldnull);
420+
}
421+
373422
public static void PatchFileSelectSlotRender(ILContext context, CustomAttribute attrib) {
374423
TypeDefinition declaringType = context.Method.DeclaringType;
375424
FieldDefinition f_maxStrawberryCount = declaringType.FindField("maxStrawberryCount");

Celeste.Mod.mm/Patches/SaveData.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using MonoMod;
77
using System;
88
using System.Collections.Generic;
9+
using System.IO;
910
using System.Linq;
1011
using System.Runtime.CompilerServices;
1112
using System.Xml;
@@ -297,8 +298,19 @@ public static void LoadModSaveData(int slot) {
297298

298299
public static extern bool orig_TryDelete(int slot);
299300
public static new bool TryDelete(int slot) {
300-
if (!orig_TryDelete(slot))
301-
return false;
301+
bool vanillaExists = false;
302+
string saveFilePath = patch_UserIO.GetSaveFilePath();
303+
if (Directory.Exists(saveFilePath))
304+
vanillaExists = File.Exists(Path.Combine(saveFilePath, $"{slot}.celeste"));
305+
306+
if (vanillaExists) {
307+
if (!orig_TryDelete(slot)) {
308+
return false;
309+
}
310+
}
311+
else
312+
Logger.Warn("SaveData", $"Deleting save data for slot {slot} which has no vanilla data");
313+
302314
return TryDeleteModSaveData(slot);
303315
}
304316

0 commit comments

Comments
 (0)