Skip to content

Commit a8df952

Browse files
Add lang file updates on version change (#5072)
1 parent 4344910 commit a8df952

File tree

4 files changed

+115
-42
lines changed

4 files changed

+115
-42
lines changed

src/main/java/ch/njol/skript/Skript.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,12 +1218,11 @@ public static Collection<SkriptAddon> getAddons() {
12181218
* @return A {@link SkriptAddon} representing Skript.
12191219
*/
12201220
public static SkriptAddon getAddonInstance() {
1221-
final SkriptAddon a = addon;
1222-
if (a == null)
1223-
return addon = new SkriptAddon(Skript.getInstance())
1224-
.setLanguageFileDirectory("lang");
1225-
else
1226-
return a;
1221+
if (addon == null) {
1222+
addon = new SkriptAddon(Skript.getInstance());
1223+
addon.setLanguageFileDirectory("lang");
1224+
}
1225+
return addon;
12271226
}
12281227

12291228
// ================ CONDITIONS & EFFECTS & SECTIONS ================

src/main/java/ch/njol/skript/config/Config.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,17 @@ public boolean setValues(final Config other) {
186186
public boolean setValues(final Config other, final String... excluded) {
187187
return getMainNode().setValues(other.getMainNode(), excluded);
188188
}
189+
190+
/**
191+
* Compares the keys and values of this Config and another.
192+
* @param other The other Config.
193+
* @param excluded Keys to exclude from this comparison.
194+
* @return True if there are differences in the keys and their values
195+
* of this Config and the other Config.
196+
*/
197+
public boolean compareValues(Config other, String... excluded) {
198+
return getMainNode().compareValues(other.getMainNode(), excluded);
199+
}
189200

190201
@Nullable
191202
public File getFile() {

src/main/java/ch/njol/skript/config/SectionNode.java

Lines changed: 62 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -446,45 +446,80 @@ HashMap<String, String> toMap(final String prefix, final String separator) {
446446
}
447447
return r;
448448
}
449-
449+
450450
/**
451-
* @param other
452-
* @param excluded keys and sections to exclude
453-
* @return <tt>false</tt> if this and the other SectionNode contain the exact same set of keys
451+
* Updates the values of this SectionNode based on the values of another SectionNode.
452+
* @param other The other SectionNode.
453+
* @param excluded Keys to exclude from this update.
454+
* @return True if there are differences in the keys of this SectionNode and the other SectionNode.
454455
*/
455-
public boolean setValues(final SectionNode other, final String... excluded) {
456-
boolean r = false;
457-
for (final Node n : this) {
458-
if (CollectionUtils.containsIgnoreCase(excluded, n.key))
456+
public boolean setValues(SectionNode other, String... excluded) {
457+
return modify(other, false, excluded);
458+
}
459+
460+
/**
461+
* Compares the keys and values of this SectionNode and another.
462+
* @param other The other SectionNode.
463+
* @param excluded Keys to exclude from this comparison.
464+
* @return True if there are no differences in the keys and their values
465+
* of this SectionNode and the other SectionNode.
466+
*/
467+
public boolean compareValues(SectionNode other, String... excluded) {
468+
return !modify(other, true, excluded); // invert as "modify" returns true if different
469+
}
470+
471+
private boolean modify(SectionNode other, boolean compareValues, String... excluded) {
472+
boolean different = false;
473+
474+
for (Node node : this) {
475+
if (CollectionUtils.containsIgnoreCase(excluded, node.key))
459476
continue;
460-
final Node o = other.get(n.key);
461-
if (o == null) {
462-
r = true;
463-
} else {
464-
if (n instanceof SectionNode) {
465-
if (o instanceof SectionNode) {
466-
r |= ((SectionNode) n).setValues((SectionNode) o);
467-
} else {
468-
r = true;
477+
478+
Node otherNode = other.get(node.key);
479+
if (otherNode != null) { // other has this key
480+
if (node instanceof SectionNode) {
481+
if (otherNode instanceof SectionNode) {
482+
different |= ((SectionNode) node).modify((SectionNode) otherNode, compareValues);
483+
} else { // Our node type is different from the old one
484+
different = true;
485+
if (compareValues) // Counting values means we don't need to copy over values
486+
break;
469487
}
470-
} else if (n instanceof EntryNode) {
471-
if (o instanceof EntryNode) {
472-
((EntryNode) n).setValue(((EntryNode) o).getValue());
473-
} else {
474-
r = true;
488+
} else if (node instanceof EntryNode) {
489+
if (otherNode instanceof EntryNode) {
490+
String ourValue = ((EntryNode) node).getValue();
491+
String theirValue = ((EntryNode) otherNode).getValue();
492+
if (compareValues) {
493+
if (!ourValue.equals(theirValue)) {
494+
different = true;
495+
break; // Counting values means we don't need to copy over values
496+
}
497+
} else { // If we don't care about values, just copy over the old one
498+
((EntryNode) node).setValue(theirValue);
499+
}
500+
} else { // Our node type is different from the old one
501+
different = true;
502+
if (compareValues) // Counting values means we don't need to copy over values
503+
break;
475504
}
476505
}
506+
} else { // other is missing this key (which means we have a new key)
507+
different = true;
508+
if (compareValues) // Counting values means we don't need to copy over values
509+
break;
477510
}
478511
}
479-
if (!r) {
480-
for (final Node o : other) {
481-
if (this.get(o.key) == null) {
482-
r = true;
512+
513+
if (!different) {
514+
for (Node otherNode : other) {
515+
if (this.get(otherNode.key) == null) {
516+
different = true;
483517
break;
484518
}
485519
}
486520
}
487-
return r;
521+
522+
return different;
488523
}
489524

490525
}

src/main/java/ch/njol/skript/localization/Language.java

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import ch.njol.skript.SkriptAddon;
2323
import ch.njol.skript.config.Config;
2424
import ch.njol.skript.util.ExceptionUtils;
25+
import ch.njol.skript.util.FileUtils;
2526
import ch.njol.skript.util.Version;
2627
import org.bukkit.plugin.Plugin;
2728
import org.eclipse.jdt.annotation.Nullable;
@@ -197,8 +198,8 @@ public static void loadDefault(SkriptAddon addon) {
197198
englishIs = null;
198199
}
199200
}
200-
HashMap<String, String> def = load(defaultIs, "default");
201-
HashMap<String, String> en = load(englishIs, "english");
201+
HashMap<String, String> def = load(defaultIs, "default", false);
202+
HashMap<String, String> en = load(englishIs, "english", addon == Skript.getAddonInstance());
202203

203204
String v = def.get("version");
204205
if (v == null)
@@ -220,9 +221,9 @@ public static boolean load(String name) {
220221
name = "" + name.toLowerCase(Locale.ENGLISH);
221222

222223
localizedLanguage = new HashMap<>();
223-
boolean exists = load(Skript.getAddonInstance(), name);
224+
boolean exists = load(Skript.getAddonInstance(), name, true);
224225
for (SkriptAddon addon : Skript.getAddons()) {
225-
exists |= load(addon, name);
226+
exists |= load(addon, name, false);
226227
}
227228
if (!exists) {
228229
if (name.equals("english")) {
@@ -241,18 +242,18 @@ public static boolean load(String name) {
241242
return true;
242243
}
243244

244-
private static boolean load(SkriptAddon addon, String name) {
245+
private static boolean load(SkriptAddon addon, String name, boolean tryUpdate) {
245246
if (addon.getLanguageFileDirectory() == null)
246247
return false;
247248
// Backwards addon compatibility
248249
if (name.equals("english") && addon.plugin.getResource(addon.getLanguageFileDirectory() + "/default.lang") == null)
249250
return true;
250251

251-
HashMap<String, String> l = load(addon.plugin.getResource(addon.getLanguageFileDirectory() + "/" + name + ".lang"), name);
252+
HashMap<String, String> l = load(addon.plugin.getResource(addon.getLanguageFileDirectory() + "/" + name + ".lang"), name, tryUpdate);
252253
File file = new File(addon.plugin.getDataFolder(), addon.getLanguageFileDirectory() + File.separator + name + ".lang");
253254
try {
254255
if (file.exists())
255-
l.putAll(load(new FileInputStream(file), name));
256+
l.putAll(load(new FileInputStream(file), name, tryUpdate));
256257
} catch (FileNotFoundException e) {
257258
assert false;
258259
}
@@ -289,11 +290,38 @@ private static boolean load(SkriptAddon addon, String name) {
289290
return true;
290291
}
291292

292-
private static HashMap<String, String> load(@Nullable InputStream in, String name) {
293+
private static HashMap<String, String> load(@Nullable InputStream in, String name, boolean tryUpdate) {
293294
if (in == null)
294295
return new HashMap<>();
296+
295297
try {
296-
return new Config(in, name + ".lang", false, false, ":").toMap(".");
298+
Config langConfig = new Config(in, name + ".lang", false, false, ":");
299+
300+
if (tryUpdate && !Skript.getVersion().toString().equals(langConfig.get("version"))) {
301+
String langFileName = "lang/" + name + ".lang";
302+
303+
InputStream newConfigIn = Skript.getInstance().getResource(langFileName);
304+
if (newConfigIn == null) {
305+
Skript.error("The lang file '" + name + ".lang' is outdated, but Skript couldn't find the newest version of it in its jar.");
306+
return new HashMap<>();
307+
}
308+
Config newLangConfig = new Config(newConfigIn, "Skript.jar/" + langFileName, false, false, ":");
309+
newConfigIn.close();
310+
311+
File langFile = new File(Skript.getInstance().getDataFolder(), langFileName);
312+
if (!newLangConfig.compareValues(langConfig, "version")) {
313+
File langFileBackup = FileUtils.backup(langFile);
314+
newLangConfig.getMainNode().set("version", Skript.getVersion().toString());
315+
langConfig = newLangConfig;
316+
langConfig.save(langFile);
317+
Skript.info("The lang file '" + name + ".lang' has been updated to the latest version. A backup of your old lang file has been created as " + langFileBackup.getName());
318+
} else { // Only the version changed, don't bother creating a backup
319+
langConfig.getMainNode().set("version", Skript.getVersion().toString());
320+
langConfig.save(langFile);
321+
}
322+
}
323+
324+
return langConfig.toMap(".");
297325
} catch (IOException e) {
298326
//noinspection ThrowableNotThrown
299327
Skript.exception(e, "Could not load the language file '" + name + ".lang': " + ExceptionUtils.toString(e));

0 commit comments

Comments
 (0)