Skip to content

Commit 8ea215b

Browse files
committed
Added warnings when a patch overrides another patch.
1 parent 06a2af5 commit 8ea215b

File tree

3 files changed

+89
-28
lines changed

3 files changed

+89
-28
lines changed

src/FileLoading.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,16 @@ static void LoadPatch(string filepath)
127127

128128
try
129129
{
130-
Mod.LogInfo($"Loading '{patchName}'");
130+
Mod.LogInfo($"Loading patch '{patchName}'");
131131

132132
using (FileStream file = File.OpenRead(filepath))
133133
{
134-
TerrainRegistry.ApplyPatchFile(file);
134+
TerrainRegistry.ApplyPatchFile(patchName, file);
135135
}
136136
}
137137
catch (Exception ex)
138138
{
139-
Mod.LogError($"Problem loading '{patchName}': {ex}");
139+
Mod.LogError($"Problem loading patch '{patchName}': {ex}");
140140
}
141141
}
142142
}

src/Patches.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ private static bool SetResult(Int3 batchId, ref string result, bool runOriginal)
6565
Mod.Settings.IncludePatches &&
6666
TerrainRegistry.patchedBatches.ContainsKey(batchId))
6767
{
68-
result = TerrainRegistry.patchedBatches[batchId];
68+
result = TerrainRegistry.patchedBatches[batchId].fileName;
6969
return false;
7070
}
7171
else

src/Terrain.cs

+85-24
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
2+
using System.Collections;
23
using System.Collections.Generic;
34
using System.IO;
5+
using System.Linq;
46

57
namespace TerrainPatcher
68
{
@@ -21,16 +23,20 @@ public static void PatchTerrain(
2123
try
2224
{
2325
Mod.LogInfo($"Applying patch '{patchName}'");
24-
ApplyPatchFile(patchFile, forceOriginal);
26+
ApplyPatchFile(patchName, patchFile, forceOriginal);
2527
}
2628
catch (Exception ex)
2729
{
28-
Mod.LogError($"Problem applying '{patchName}': {ex}");
30+
Mod.LogError($"Problem applying patch '{patchName}': {ex}");
2931
}
3032
}
3133

3234
// Applies a terrain patch.
33-
internal static void ApplyPatchFile(Stream patchFile, bool forceOriginal = false)
35+
internal static void ApplyPatchFile(
36+
string patchName,
37+
Stream patchFile,
38+
bool forceOriginal = false
39+
)
3440
{
3541
if (patchFile is null)
3642
{
@@ -69,9 +75,9 @@ internal static void ApplyPatchFile(Stream patchFile, bool forceOriginal = false
6975
Int3 id = batchId.Value;
7076

7177
// Lists all batches as they are patched.
72-
Mod.LogInfo($"- Patching batch ({id.x}, {id.y}, {id.z})");
78+
Mod.LogInfo($"Patching batch [{id.x}, {id.y}, {id.z}] for patch '{patchName}'");
7379

74-
ApplyBatchPatch(reader, id, forceOriginal);
80+
ApplyBatchPatch(patchName, reader, id, forceOriginal);
7581
}
7682
catch (EndOfStreamException ex)
7783
{
@@ -94,12 +100,33 @@ internal static void ApplyPatchFile(Stream patchFile, bool forceOriginal = false
94100
}
95101

96102
// All batches that have been patched.
97-
// The Int3 is the ID of the batch and the string is the file name.
98-
internal static readonly Dictionary<Int3, string> patchedBatches =
99-
new Dictionary<Int3, string> { };
103+
// The Int3 is the ID of the batch.
104+
internal static readonly Dictionary<Int3, PatchedBatch> patchedBatches =
105+
new Dictionary<Int3, PatchedBatch> { };
106+
107+
// A batch that has been modified.
108+
internal struct PatchedBatch
109+
{
110+
internal PatchedBatch(string fileName)
111+
{
112+
this.fileName = fileName;
113+
this.octreePatches = new List<string>?[Constants.OCTREES_PER_BATCH];
114+
}
115+
116+
// The name of the new batch file.
117+
internal string fileName;
118+
119+
// A list of the patch names that have been applied for each octree.
120+
internal List<string>?[] octreePatches;
121+
}
100122

101123
// Loads a batch into patchedBatches if necessary, then applies the patch.
102-
private static void ApplyBatchPatch(BinaryReader patch, Int3 batchId, bool forceOriginal)
124+
private static void ApplyBatchPatch(
125+
string patchName,
126+
BinaryReader patch,
127+
Int3 batchId,
128+
bool forceOriginal
129+
)
103130
{
104131
lock (patchedBatches)
105132
{
@@ -109,7 +136,7 @@ private static void ApplyBatchPatch(BinaryReader patch, Int3 batchId, bool force
109136
}
110137
}
111138

112-
PatchOctrees(batchId, patch);
139+
PatchOctrees(patchName, batchId, patch);
113140
}
114141

115142
// Creates a new tempfile for a batch and stores it in patchedBatches.
@@ -128,10 +155,9 @@ string GetPath(string origDir) => Path.Combine(
128155
);
129156

130157
// Search each directory.
131-
string[] dirs = Constants.ORIG_BATCH_DIRS;
132-
for (int i = 0; i < dirs.Length; i++)
158+
foreach (string dir in Constants.ORIG_BATCH_DIRS)
133159
{
134-
string origPath = GetPath(dirs[i]);
160+
string origPath = GetPath(dir);
135161

136162
if (File.Exists(origPath))
137163
{
@@ -143,7 +169,7 @@ string GetPath(string origDir) => Path.Combine(
143169
{
144170
File.Copy(origPath, newPath, overwrite: true);
145171

146-
patchedBatches[batchId] = newPath;
172+
patchedBatches.Add(batchId, new PatchedBatch(newPath));
147173
return;
148174
}
149175
}
@@ -164,28 +190,56 @@ string GetPath(string origDir) => Path.Combine(
164190
writer.Write((uint)0);
165191
}
166192

167-
patchedBatches[batchId] = newPath;
193+
patchedBatches.Add(batchId, new PatchedBatch(newPath));
168194
}
169195
}
170196

171197
// Patches the contents of a batch, assuming it's already in patchedBatches.
172-
private static void PatchOctrees(Int3 batchId, BinaryReader patch)
198+
private static void PatchOctrees(string patchName, Int3 batchId, BinaryReader patch)
173199
{
200+
string fileName = patchedBatches[batchId].fileName;
201+
174202
// Copy the contents of the original file into memory.
175-
byte[] bytes = File.ReadAllBytes(patchedBatches[batchId]);
203+
byte[] bytes = File.ReadAllBytes(fileName);
176204
var original = new BinaryReader(new MemoryStream(buffer: bytes, writable: false));
177205

178206
original.ReadUInt32(); // Discard version bytes.
179207

208+
BitArray patchedOctrees;
209+
180210
// Apply the patch to the target file.
181-
using (FileStream file = File.Open(patchedBatches[batchId], FileMode.Create))
211+
using (FileStream file = File.Open(fileName, FileMode.Create))
182212
{
183213
var target = new BinaryWriter(file);
184214

185215
target.WriteUInt32(Constants.BATCH_VERSION); // Prepend version bytes.
186216

187217
// Call the terrain patcher.
188-
TerrainPatching.Patch(target, original, patch);
218+
patchedOctrees = TerrainPatching.Patch(target, original, patch);
219+
}
220+
221+
var octreePatches = patchedBatches[batchId].octreePatches;
222+
for (int i = 0; i < Constants.OCTREES_PER_BATCH; i++)
223+
{
224+
if (patchedOctrees[i])
225+
{
226+
octreePatches[i] ??= new List<string>();
227+
var patches = octreePatches[i]!;
228+
229+
if (patches.Count > 0)
230+
{
231+
var warning = $"Patch '{patchName}' is overriding ";
232+
warning += patches.Count == 1 ? "patch " : "patches [";
233+
warning += string.Join(",", patches.Select(patch => $"'{patch}'"));
234+
if (patches.Count > 1) { warning += "]"; }
235+
warning += $" in batch [{batchId.x}, {batchId.y}, {batchId.z}]";
236+
warning += $" at octree #{i}!";
237+
238+
Mod.LogWarning(warning);
239+
}
240+
241+
patches.Add(patchName);
242+
}
189243
}
190244
}
191245
}
@@ -206,12 +260,13 @@ private PatchesDir()
206260

207261
foreach (string path in Directory.EnumerateFiles(this.path))
208262
{
209-
if (System.IO.Path.GetExtension(path) == ".optoctrees" &&
210-
!TerrainRegistry.patchedBatches.ContainsValue(path))
263+
if (System.IO.Path.GetExtension(path) == ".optoctrees")
211264
{
212265
File.Delete(path);
213266
}
214267
}
268+
269+
break;
215270
}
216271
}
217272
}
@@ -231,9 +286,11 @@ public static string? Path
231286

232287
internal static class TerrainPatching
233288
{
234-
// Patches a target file, using an original file and a patch file.
235-
public static void Patch(BinaryWriter target, BinaryReader original, BinaryReader patch)
289+
// Patches a target file, using an original file and a patch file. Returns an array
290+
// indicating which octrees were modified.
291+
public static BitArray Patch(BinaryWriter target, BinaryReader original, BinaryReader patch)
236292
{
293+
var patchedOctrees = new BitArray(Constants.OCTREES_PER_BATCH);
237294
int patchedOctreeCount = patch.ReadByte();
238295

239296
if (patchedOctreeCount > Constants.OCTREES_PER_BATCH)
@@ -262,7 +319,9 @@ public static void Patch(BinaryWriter target, BinaryReader original, BinaryReade
262319
{
263320
try
264321
{
265-
octrees[patch.ReadByte()] = patch.ReadBytes(patch.ReadUInt16() * 4);
322+
int octree = patch.ReadByte();
323+
patchedOctrees[octree] = true;
324+
octrees[octree] = patch.ReadBytes(patch.ReadUInt16() * 4);
266325
}
267326
catch (EndOfStreamException)
268327
{
@@ -293,6 +352,8 @@ public static void Patch(BinaryWriter target, BinaryReader original, BinaryReade
293352
target.Write((uint)0);
294353
}
295354
}
355+
356+
return patchedOctrees;
296357
}
297358
}
298359
}

0 commit comments

Comments
 (0)