feat: config version and improvements

This commit is contained in:
ineanto 2023-12-19 19:57:08 +01:00
parent 29e50966fd
commit a064352492
17 changed files with 198 additions and 53 deletions

View file

@ -70,6 +70,9 @@ tasks {
processResources { processResources {
from("src/main/resources") from("src/main/resources")
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
filesMatching("config.yml") {
expand("version" to version)
}
filesMatching("plugin.yml") { filesMatching("plugin.yml") {
expand("version" to version) expand("version" to version)
} }

View file

@ -24,6 +24,8 @@ import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SimpleItem; import xyz.xenondevs.invui.item.impl.SimpleItem;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
public class NickoBukkit extends JavaPlugin { public class NickoBukkit extends JavaPlugin {
private static NickoBukkit plugin; private static NickoBukkit plugin;
@ -67,7 +69,6 @@ public class NickoBukkit extends JavaPlugin {
getLogger().warning("Issues regarding Nicko being used in offline mode will be ignored for now."); getLogger().warning("Issues regarding Nicko being used in offline mode will be ignored for now.");
} }
if (!MinecraftVersion.WILD_UPDATE.atOrAbove()) { if (!MinecraftVersion.WILD_UPDATE.atOrAbove()) {
getLogger().severe("This version (" + MinecraftVersion.getCurrentVersion().getVersion() + ") is not supported by Nicko!"); getLogger().severe("This version (" + MinecraftVersion.getCurrentVersion().getVersion() + ") is not supported by Nicko!");
dataStore.getStorage().setError(true); dataStore.getStorage().setError(true);
@ -91,6 +92,20 @@ public class NickoBukkit extends JavaPlugin {
} }
if (!unitTesting) { if (!unitTesting) {
// Migrate configuration (1.0.8-RC1)
if (configuration.getVersion() == null
|| configuration.getVersion().isEmpty()
|| configuration.getVersionObject().compareTo(Configuration.VERSION) != 0) {
getLogger().info("Migrating configuration file from older version...");
try {
Files.copy(configurationManager.getFile().toPath(), configurationManager.getBackupFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
Files.delete(configurationManager.getFile().toPath());
configurationManager.saveDefaultConfig();
} catch (IOException e) {
getLogger().severe("Failed to migrate your configuration!");
}
}
try { try {
Class.forName("io.papermc.paper.threadedregions.RegionizedServerInitEvent"); Class.forName("io.papermc.paper.threadedregions.RegionizedServerInitEvent");
getLogger().warning("Nicko has not been tested against Folia and might not work at all!"); getLogger().warning("Nicko has not been tested against Folia and might not work at all!");
@ -149,7 +164,10 @@ public class NickoBukkit extends JavaPlugin {
public Configuration getNickoConfig() { public Configuration getNickoConfig() {
try { try {
if (configuration == null) { return configuration = configurationManager.load(); } if (configuration == null) {
configuration = configurationManager.load();
getLogger().info("Configuration file loaded.");
}
return configuration; return configuration;
} catch (IOException e) { } catch (IOException e) {
getLogger().severe("Failed to load the configuration file!"); getLogger().severe("Failed to load the configuration file!");

View file

@ -1,29 +1,48 @@
package xyz.ineanto.nicko.config; package xyz.ineanto.nicko.config;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import xyz.ineanto.nicko.version.Version;
public class Configuration { public class Configuration {
public static final Version VERSION = new Version(1, 0, 8);
public static final Configuration DEFAULT = new Configuration(VERSION.toString(),
DefaultDataSources.SQL_EMPTY,
DefaultDataSources.REDIS_EMPTY,
"§6Nicko §8§l| §r",
false);
private final transient Version versionObject;
@JsonProperty("version")
private final String version;
@JsonProperty("sql") @JsonProperty("sql")
private final SQLDataSourceConfiguration sqlConfiguration; private final SQLDataSourceConfiguration sqlConfiguration;
@JsonProperty("redis") @JsonProperty("redis")
private final DataSourceConfiguration redisConfiguration; private final DataSourceConfiguration redisConfiguration;
@JsonProperty("prefix")
private final String prefix; private final String prefix;
@JsonProperty("customLocale")
private final Boolean customLocale; private final Boolean customLocale;
public Configuration(SQLDataSourceConfiguration sqlConfiguration, DataSourceConfiguration redisConfiguration, String prefix, Boolean customLocale) { public Configuration(@JsonProperty("version") String version,
@JsonProperty("sql") SQLDataSourceConfiguration sqlConfiguration,
@JsonProperty("redis") DataSourceConfiguration redisConfiguration,
@JsonProperty("prefix") String prefix,
@JsonProperty("customLocale") Boolean customLocale) {
this.version = version;
this.versionObject = Version.fromString(version);
this.sqlConfiguration = sqlConfiguration; this.sqlConfiguration = sqlConfiguration;
this.redisConfiguration = redisConfiguration; this.redisConfiguration = redisConfiguration;
this.prefix = prefix; this.prefix = prefix;
this.customLocale = customLocale; this.customLocale = customLocale;
} }
public Configuration() { public String getVersion() {
this( return version;
new SQLDataSourceConfiguration(false, "", 3306, "", "", true), }
new DataSourceConfiguration(false, "", 6379, "", ""),
"", public Version getVersionObject() {
false return versionObject;
);
} }
public SQLDataSourceConfiguration getSqlConfiguration() { public SQLDataSourceConfiguration getSqlConfiguration() {

View file

@ -7,16 +7,25 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import java.io.*; import java.io.*;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.logging.Logger; import java.util.logging.Logger;
public class ConfigurationManager { public class ConfigurationManager {
private final Logger logger = Logger.getLogger("ConfigurationManager"); private final Logger logger = Logger.getLogger("ConfigurationManager");
private final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); private final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
private final File file; private final File file;
private final File backupFile;
public ConfigurationManager(File directory) { public ConfigurationManager(File directory) {
final String date = Instant.now()
.atZone(ZoneId.systemDefault())
.format(DateTimeFormatter.ofPattern("dd-MM-yyyy"));
this.file = new File(directory, "config.yml"); this.file = new File(directory, "config.yml");
this.backupFile = new File(directory, "config.old-" + date + ".yml");
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
} }
public void save(Configuration configuration) throws IOException { public void save(Configuration configuration) throws IOException {
@ -47,4 +56,12 @@ public class ConfigurationManager {
return mapper.readValue(reader, Configuration.class); return mapper.readValue(reader, Configuration.class);
} }
} }
public File getFile() {
return file;
}
public File getBackupFile() {
return backupFile;
}
} }

View file

@ -15,6 +15,7 @@ import xyz.ineanto.nicko.gui.items.common.choice.ChoiceCallback;
import xyz.ineanto.nicko.i18n.I18N; import xyz.ineanto.nicko.i18n.I18N;
import xyz.ineanto.nicko.i18n.I18NDict; import xyz.ineanto.nicko.i18n.I18NDict;
import xyz.ineanto.nicko.profile.NickoProfile; import xyz.ineanto.nicko.profile.NickoProfile;
import xyz.xenondevs.invui.item.builder.AbstractItemBuilder;
import xyz.xenondevs.invui.item.builder.ItemBuilder; import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.builder.SkullBuilder; import xyz.xenondevs.invui.item.builder.SkullBuilder;
import xyz.xenondevs.invui.item.impl.AsyncItem; import xyz.xenondevs.invui.item.impl.AsyncItem;
@ -27,6 +28,7 @@ import java.util.Optional;
public class PlayerInformationItem extends AsyncItem { public class PlayerInformationItem extends AsyncItem {
private final Player target; private final Player target;
private final NickoProfile profile; private final NickoProfile profile;
private final I18N i18n;
public PlayerInformationItem(I18N i18n, Player target) { public PlayerInformationItem(I18N i18n, Player target) {
super(new SuppliedItem(() -> { super(new SuppliedItem(() -> {
@ -39,11 +41,19 @@ public class PlayerInformationItem extends AsyncItem {
if (optionalProfile.isPresent()) { if (optionalProfile.isPresent()) {
final NickoProfile profile = optionalProfile.get(); final NickoProfile profile = optionalProfile.get();
return i18n.translateItem(skull, I18NDict.GUI.Admin.CHECK, final AbstractItemBuilder<?> headItem = i18n.translateItem(skull, I18NDict.GUI.Admin.CHECK,
target.getName(), target.getName(),
(profile.hasData() ? "§a✔" : "§c❌"), (profile.hasData() ? "§a✔" : "§c❌"),
(profile.getName() == null ? "§7N/A" : profile.getName()), (profile.getName() == null ? "§7N/A" : profile.getName()),
(profile.getSkin() == null ? "§7N/A" : profile.getSkin())); (profile.getSkin() == null ? "§7N/A" : profile.getSkin()));
if (!profile.hasData()) {
// Remove the last 2 lines of the lore.
headItem.removeLoreLine(headItem.getLore().size() - 1);
headItem.removeLoreLine(headItem.getLore().size() - 1);
}
return headItem;
} }
} catch (MojangApiUtils.MojangApiException | IOException e) { } catch (MojangApiUtils.MojangApiException | IOException e) {
NickoBukkit.getInstance().getLogger().severe("Unable to get head for specified UUID ( " + target.getUniqueId() + ")! (GUI/PlayerCheck)"); NickoBukkit.getInstance().getLogger().severe("Unable to get head for specified UUID ( " + target.getUniqueId() + ")! (GUI/PlayerCheck)");
@ -53,6 +63,7 @@ public class PlayerInformationItem extends AsyncItem {
"§c§l?!?", "§7N/A", "§7N/A", "§7N/A" "§c§l?!?", "§7N/A", "§7N/A", "§7N/A"
); );
}); });
this.i18n = i18n;
this.target = target; this.target = target;
this.profile = NickoBukkit.getInstance().getDataStore().getData(target.getUniqueId()).orElse(NickoProfile.EMPTY_PROFILE); this.profile = NickoBukkit.getInstance().getDataStore().getData(target.getUniqueId()).orElse(NickoProfile.EMPTY_PROFILE);
} }
@ -67,7 +78,6 @@ public class PlayerInformationItem extends AsyncItem {
public void onConfirm() { public void onConfirm() {
final AppearanceManager appearanceManager = new AppearanceManager(target); final AppearanceManager appearanceManager = new AppearanceManager(target);
appearanceManager.reset(); appearanceManager.reset();
final I18N i18n = new I18N(player);
player.sendMessage(i18n.translate(I18NDict.Event.Admin.Check.REMOVE_SKIN, target.getName())); player.sendMessage(i18n.translate(I18NDict.Event.Admin.Check.REMOVE_SKIN, target.getName()));
} }

View file

@ -0,0 +1,33 @@
package xyz.ineanto.nicko.version;
import org.jetbrains.annotations.NotNull;
import java.util.Comparator;
public record Version(int major, int minor, int patch) implements Comparable<Version> {
@Override
public int compareTo(@NotNull Version otherVersion) {
final Comparator<Version> comparator = Comparator
.comparingInt(Version::major)
.thenComparingInt(Version::minor)
.thenComparingInt(Version::patch);
return comparator.compare(this, otherVersion);
}
@Override
public String toString() {
return major + "." + minor + "." + patch;
}
public static Version fromString(String versionString) {
if (versionString == null || versionString.isEmpty()) { return new Version(0, 0, 0); }
final String[] split = versionString.split("\\.");
try {
return new Version(Integer.parseInt(split[0]),
Integer.parseInt(split[1]),
Integer.parseInt(split[2]));
} catch (NumberFormatException exception) {
return new Version(0, 0, 0);
}
}
}

View file

@ -1,7 +1,7 @@
# Nicko ${project.version} - Config: # Nicko ${version} - Config:
# Don't modify this. # Specifies the configuration version.
# No, like... really. # Do NOT modify this field.
version: "1.0.8" version: "1.0.8"
############ ############

View file

@ -1,5 +1,3 @@
version: "1.0.8"
error: error:
generic: "An unknown error occurred." generic: "An unknown error occurred."
permission: "§cYou do not have the required permission." permission: "§cYou do not have the required permission."

View file

@ -1,5 +1,3 @@
version: "1.0.8"
error: error:
generic: "Une erreur inconnue c'est produite." generic: "Une erreur inconnue c'est produite."
permission: "§cVous ne possédez pas la permission." permission: "§cVous ne possédez pas la permission."

View file

@ -7,7 +7,6 @@ import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import xyz.ineanto.nicko.NickoBukkit; import xyz.ineanto.nicko.NickoBukkit;
import xyz.ineanto.nicko.config.Configuration; import xyz.ineanto.nicko.config.Configuration;
import xyz.ineanto.nicko.config.DefaultDataSources;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
@ -16,11 +15,7 @@ public class NickoPluginTest {
@BeforeAll @BeforeAll
public static void setup() { public static void setup() {
final Configuration config = new Configuration( final Configuration config = Configuration.DEFAULT;
DefaultDataSources.MARIADB_EMPTY,
DefaultDataSources.REDIS_EMPTY,
"",
false);
MockBukkit.mock(); MockBukkit.mock();
plugin = MockBukkit.load(NickoBukkit.class, config); plugin = MockBukkit.load(NickoBukkit.class, config);
} }

View file

@ -7,7 +7,6 @@ import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import xyz.ineanto.nicko.NickoBukkit; import xyz.ineanto.nicko.NickoBukkit;
import xyz.ineanto.nicko.config.Configuration; import xyz.ineanto.nicko.config.Configuration;
import xyz.ineanto.nicko.config.DefaultDataSources;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
@ -17,11 +16,7 @@ public class ConfigurationTest {
@BeforeAll @BeforeAll
public static void setup() { public static void setup() {
MockBukkit.mock(); MockBukkit.mock();
final Configuration config = new Configuration( final Configuration config = Configuration.DEFAULT;
DefaultDataSources.SQL_EMPTY,
DefaultDataSources.REDIS_EMPTY,
"",
false);
plugin = MockBukkit.load(NickoBukkit.class, config); plugin = MockBukkit.load(NickoBukkit.class, config);
} }

View file

@ -0,0 +1,72 @@
package xyz.ineanto.nicko.test.config;
import be.seeseemelk.mockbukkit.MockBukkit;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import xyz.ineanto.nicko.NickoBukkit;
import xyz.ineanto.nicko.config.Configuration;
import xyz.ineanto.nicko.config.DefaultDataSources;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ConfigurationVersionTest {
private static NickoBukkit plugin;
@BeforeAll
public static void setup() {
MockBukkit.mock();
final Configuration configuration = Configuration.DEFAULT;
plugin = MockBukkit.load(NickoBukkit.class, configuration);
}
@Test
@DisplayName("Compare configuration version")
public void compareConfigurationVersion() {
final Configuration configuration = new Configuration(Configuration.VERSION.toString(),
DefaultDataSources.SQL_EMPTY,
DefaultDataSources.REDIS_EMPTY,
"",
false);
assertEquals(configuration.getVersionObject().compareTo(Configuration.VERSION), 0);
}
@Test
@DisplayName("Compare newer configuration version")
public void compareNewerConfigurationVersion() {
final Configuration configuration = new Configuration("24.1.0",
DefaultDataSources.SQL_EMPTY,
DefaultDataSources.REDIS_EMPTY,
"",
false);
assertEquals(configuration.getVersionObject().compareTo(Configuration.VERSION), 1);
}
@Test
@DisplayName("Compare older configuration version")
public void compareOlderConfigurationVersion() {
final Configuration configuration = new Configuration("0.23.3",
DefaultDataSources.SQL_EMPTY,
DefaultDataSources.REDIS_EMPTY,
"",
false);
assertEquals(configuration.getVersionObject().compareTo(Configuration.VERSION), -1);
}
@Test
@DisplayName("Compare unknown configuration version")
public void compareUnknownConfigurationVersion() {
final Configuration configuration = new Configuration(null,
DefaultDataSources.SQL_EMPTY,
DefaultDataSources.REDIS_EMPTY,
"",
false);
assertEquals(configuration.getVersionObject().compareTo(Configuration.VERSION), -1);
}
@AfterAll
public static void shutdown() {
MockBukkit.unmock();
}
}

View file

@ -8,7 +8,6 @@ import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import xyz.ineanto.nicko.NickoBukkit; import xyz.ineanto.nicko.NickoBukkit;
import xyz.ineanto.nicko.config.Configuration; import xyz.ineanto.nicko.config.Configuration;
import xyz.ineanto.nicko.config.DefaultDataSources;
import xyz.ineanto.nicko.i18n.I18N; import xyz.ineanto.nicko.i18n.I18N;
import xyz.ineanto.nicko.i18n.I18NDict; import xyz.ineanto.nicko.i18n.I18NDict;
import xyz.ineanto.nicko.i18n.ItemTranslation; import xyz.ineanto.nicko.i18n.ItemTranslation;
@ -21,11 +20,7 @@ public class ItemTranslationTest {
@BeforeAll @BeforeAll
public static void setup() { public static void setup() {
final Configuration config = new Configuration( final Configuration config = Configuration.DEFAULT;
DefaultDataSources.SQL_EMPTY,
DefaultDataSources.REDIS_EMPTY,
"",
false);
MockBukkit.mock(); MockBukkit.mock();
MockBukkit.load(NickoBukkit.class, config); MockBukkit.load(NickoBukkit.class, config);
} }

View file

@ -7,7 +7,6 @@ import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import xyz.ineanto.nicko.NickoBukkit; import xyz.ineanto.nicko.NickoBukkit;
import xyz.ineanto.nicko.config.Configuration; import xyz.ineanto.nicko.config.Configuration;
import xyz.ineanto.nicko.config.DefaultDataSources;
import xyz.ineanto.nicko.i18n.I18N; import xyz.ineanto.nicko.i18n.I18N;
import xyz.ineanto.nicko.i18n.I18NDict; import xyz.ineanto.nicko.i18n.I18NDict;
import xyz.ineanto.nicko.i18n.Locale; import xyz.ineanto.nicko.i18n.Locale;
@ -17,11 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class TranslationTest { public class TranslationTest {
@BeforeAll @BeforeAll
public static void setup() { public static void setup() {
final Configuration config = new Configuration( final Configuration config = Configuration.DEFAULT;
DefaultDataSources.SQL_EMPTY,
DefaultDataSources.REDIS_EMPTY,
"",
false);
MockBukkit.mock(); MockBukkit.mock();
MockBukkit.load(NickoBukkit.class, config); MockBukkit.load(NickoBukkit.class, config);
} }

View file

@ -3,14 +3,13 @@ package xyz.ineanto.nicko.test.storage;
import be.seeseemelk.mockbukkit.MockBukkit; import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock; import be.seeseemelk.mockbukkit.ServerMock;
import be.seeseemelk.mockbukkit.entity.PlayerMock; import be.seeseemelk.mockbukkit.entity.PlayerMock;
import xyz.ineanto.nicko.NickoBukkit;
import xyz.ineanto.nicko.config.Configuration;
import xyz.ineanto.nicko.config.DefaultDataSources;
import xyz.ineanto.nicko.profile.NickoProfile;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import xyz.ineanto.nicko.NickoBukkit;
import xyz.ineanto.nicko.config.Configuration;
import xyz.ineanto.nicko.profile.NickoProfile;
import java.util.Optional; import java.util.Optional;
@ -22,11 +21,7 @@ public class MapCacheTest {
@BeforeAll @BeforeAll
public static void setup() { public static void setup() {
final Configuration config = new Configuration( final Configuration config = Configuration.DEFAULT;
DefaultDataSources.SQL_EMPTY,
DefaultDataSources.REDIS_EMPTY,
"",
false);
final ServerMock server = MockBukkit.mock(); final ServerMock server = MockBukkit.mock();
plugin = MockBukkit.load(NickoBukkit.class, config); plugin = MockBukkit.load(NickoBukkit.class, config);
player = server.addPlayer(); player = server.addPlayer();

View file

@ -24,6 +24,7 @@ public class RedisCacheTest {
@BeforeAll @BeforeAll
public static void setup() { public static void setup() {
final Configuration config = new Configuration( final Configuration config = new Configuration(
"",
DefaultDataSources.SQL_EMPTY, DefaultDataSources.SQL_EMPTY,
new DataSourceConfiguration(true, "127.0.0.1", 6379, "", ""), new DataSourceConfiguration(true, "127.0.0.1", 6379, "", ""),
"", "",

View file

@ -24,6 +24,7 @@ public class SQLStorageTest {
@BeforeAll @BeforeAll
public static void setup() { public static void setup() {
final Configuration config = new Configuration( final Configuration config = new Configuration(
"",
new SQLDataSourceConfiguration(true, "127.0.0.1", 3306, "root", "12345", true), new SQLDataSourceConfiguration(true, "127.0.0.1", 3306, "root", "12345", true),
DefaultDataSources.REDIS_EMPTY, DefaultDataSources.REDIS_EMPTY,
"", "",