mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-14 00:14:09 +00:00
Make ID reassignment safe, and apply it to quests too
The free-ID search only consulted the global map, so it could pick an id the same category still held further down the iteration - and renameTo silently overwrites on POSIX, so the rename then destroyed that entry's file. It now skips ids held by the category and any file already on disk. Quests had the same discard-on-collision behaviour and now get the same reassignment, including re-registering shared quests under the new id.
This commit is contained in:
1 parent
1d0b640c61
commit
179fd4f834
2 files changed
+56
-6
No files matched your search
@@ -70,6 +70,7 @@ public class QuestController implements IQuestHandler {
|
||||
if (!file.isDirectory())
|
||||
continue;
|
||||
QuestCategory category = loadCategoryDir(file);
|
||||
List<Quest> reassigned = new ArrayList<Quest>();
|
||||
Iterator<Integer> ite = category.quests.keySet().iterator();
|
||||
while (ite.hasNext()) {
|
||||
int id = ite.next();
|
||||
@@ -77,8 +78,39 @@ public class QuestController implements IQuestHandler {
|
||||
lastUsedQuestID = id;
|
||||
Quest quest = category.quests.get(id);
|
||||
if (quests.containsKey(id)) {
|
||||
LogWriter.error("Duplicate id " + quest.id + " from category " + category.title);
|
||||
// Quest IDs live in the filename, not inside the JSON body,
|
||||
// so a simple rename permanently resolves the conflict.
|
||||
File catDir = new File(getDir(), category.title);
|
||||
|
||||
// Find the next free ID. It has to clear three things: the ids already
|
||||
// registered globally, the ids this category still holds but has not
|
||||
// reached yet, and any file already on disk - renameTo overwrites
|
||||
// silently on POSIX, so landing on an existing file would destroy it.
|
||||
int newId = lastUsedQuestID;
|
||||
do {
|
||||
newId++;
|
||||
} while (quests.containsKey(newId)
|
||||
|| category.quests.containsKey(newId)
|
||||
|| new File(catDir, newId + ".json").exists());
|
||||
lastUsedQuestID = newId;
|
||||
|
||||
File oldFile = new File(catDir, id + ".json");
|
||||
File newFile = new File(catDir, newId + ".json");
|
||||
boolean renamed = oldFile.renameTo(newFile);
|
||||
|
||||
quest.id = newId;
|
||||
ite.remove();
|
||||
reassigned.add(quest);
|
||||
|
||||
if (renamed) {
|
||||
LogWriter.info("Quest ID conflict: reassigned \"" + quest.title
|
||||
+ "\" from id " + id + " to " + newId
|
||||
+ " in category \"" + category.title + "\"");
|
||||
} else {
|
||||
LogWriter.error("Quest ID conflict: could not rename file for \""
|
||||
+ quest.title + "\" (id " + id
|
||||
+ " in category \"" + category.title + "\") to " + newId);
|
||||
}
|
||||
} else {
|
||||
quests.put(id, quest);
|
||||
if (quest.profileOptions.enableOptions
|
||||
@@ -88,6 +120,16 @@ public class QuestController implements IQuestHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Re-register reassigned quests under their new IDs.
|
||||
for (Quest quest : reassigned) {
|
||||
quests.put(quest.id, quest);
|
||||
category.quests.put(quest.id, quest);
|
||||
if (quest.profileOptions.enableOptions
|
||||
&& (quest.profileOptions.completeControl == EnumProfileSync.Shared
|
||||
|| quest.profileOptions.cooldownControl == EnumProfileSync.Shared)) {
|
||||
sharedQuests.put(quest.id, quest);
|
||||
}
|
||||
}
|
||||
lastUsedCatID++;
|
||||
category.id = lastUsedCatID;
|
||||
categories.put(category.id, category);
|
||||
|
||||
Reference in new issue
Block a user