Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 79 additions & 16 deletions src/main/java/com/bentahsin/configuration/Configuration.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.bentahsin.configuration;

import com.bentahsin.configuration.annotation.Backup;
import com.bentahsin.configuration.annotation.ConfigVersion;
import com.bentahsin.configuration.core.ConfigMapper;
import com.bentahsin.configuration.util.BackupHandler;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
Expand All @@ -22,11 +25,11 @@ public Configuration(JavaPlugin plugin) {
}

/**
* Config dosyasını başlatır, yükler ve eksik ayarları tamamlar.
* Bu metod aynı zamanda "Reload" işlemi için de kullanılabilir.
* Initializes, loads, and completes missing settings for the config file.
* This method can also be used for the "Reload" operation (logic-wise).
*
* @param configInstance Config sınıfının örneği (örn: new AntiAfkConfig())
* @param fileName Dosya adı (örn: "config.yml")
* @param configInstance The instance of the config class (e.g., new AntiAfkConfig())
* @param fileName The file name (e.g., "config.yml")
*/
public void init(Object configInstance, String fileName) {
File file = new File(plugin.getDataFolder(), fileName);
Expand All @@ -36,34 +39,61 @@ public void init(Object configInstance, String fileName) {
}

YamlConfiguration yamlConfig = new YamlConfiguration();
boolean loadFailed = false;

try {
yamlConfig.load(file);
} catch (IOException | InvalidConfigurationException e) {
plugin.getLogger().log(Level.SEVERE, "Config dosyası okunamadı veya bozuk: " + fileName, e);
} catch (InvalidConfigurationException e) {
plugin.getLogger().severe("!!! Critical Error !!!");
plugin.getLogger().severe(fileName + " is broken! Please check the YAML format.");

handleBackupOnFailure(configInstance, file);
loadFailed = true;
} catch (IOException e) {
plugin.getLogger().log(Level.SEVERE, "Config file could not be read or is corrupt: " + fileName, e);
return;
}

mapper.loadFromConfig(configInstance, yamlConfig);
if (!loadFailed) {
handleBackupOnMigration(configInstance, yamlConfig, file);
}

if (!loadFailed) {
mapper.loadFromConfig(configInstance, yamlConfig);
}

if (!loadFailed) {
mapper.handleVersion(configInstance, yamlConfig);
} else if (configInstance.getClass().isAnnotationPresent(ConfigVersion.class)) {
int v = configInstance.getClass().getAnnotation(ConfigVersion.class).value();
yamlConfig.set("config-version", v);
}

mapper.saveToConfig(configInstance, yamlConfig);

try {
yamlConfig.save(file);
if (loadFailed) {
plugin.getLogger().warning("Broken file has been backed up and " + fileName + " has been recreated with default settings.");
}
} catch (IOException e) {
plugin.getLogger().log(Level.SEVERE, "Config güncellenirken hata oluştu: " + fileName, e);
plugin.getLogger().log(Level.SEVERE, "Error occurred while updating config: " + fileName, e);
}
}

/**
* Yapılandırmayı sadece yeniden yükler (init ile aynı işlevi görür, okunabilirlik için).
* Reloads the configuration.
* Essentially calls init() but also triggers @OnReload methods.
*/
@SuppressWarnings("unused")
public void reload(Object configInstance, String fileName) {
init(configInstance, fileName);
mapper.runOnReload(configInstance);
}

/**
* Mevcut nesne durumunu dosyaya kaydeder.
* Oyun içi komutla ayar değiştirdiğinde bunu çağırabilirsin.
* Saves the current object state to the file.
* Can be called when changing settings via in-game commands.
*/
@SuppressWarnings("unused")
public void save(Object configInstance, String fileName) {
Expand All @@ -75,20 +105,20 @@ public void save(Object configInstance, String fileName) {
yamlConfig.load(file);
}
} catch (Exception e) {
plugin.getLogger().warning("Mevcut config yüklenemedi, üzerine yazılıyor: " + fileName);
plugin.getLogger().warning("Could not load existing config, overwriting: " + fileName);
}

mapper.saveToConfig(configInstance, yamlConfig);

try {
yamlConfig.save(file);
} catch (IOException e) {
plugin.getLogger().log(Level.SEVERE, "Config kaydedilemedi: " + fileName, e);
plugin.getLogger().log(Level.SEVERE, "Could not save config: " + fileName, e);
}
}

/**
* Dosya oluşturma mantığı (Private Helper)
* Internal helper logic for file creation.
*/
private void createFile(File file, String fileName) {
try {
Expand All @@ -100,11 +130,44 @@ private void createFile(File file, String fileName) {
plugin.saveResource(fileName, false);
} else {
if (file.createNewFile()) {
plugin.getLogger().info("Yeni config dosyası oluşturuldu: " + fileName);
plugin.getLogger().info("New config file created: " + fileName);
}
}
} catch (IOException e) {
plugin.getLogger().log(Level.SEVERE, "Config dosyası oluşturulamadı: " + fileName, e);
plugin.getLogger().log(Level.SEVERE, "Could not create config file: " + fileName, e);
}
}

/**
* Helper: Checks and handles backup on failure (Syntax Error).
*/
private void handleBackupOnFailure(Object instance, File file) {
if (instance.getClass().isAnnotationPresent(Backup.class)) {
Backup backup = instance.getClass().getAnnotation(Backup.class);
if (backup.enabled() && backup.onFailure()) {
plugin.getLogger().info("Backing up broken file...");
BackupHandler.createBackup(plugin, file, backup.path(), "broken");
}
}
}

/**
* Helper: Checks and handles backup on version migration.
*/
private void handleBackupOnMigration(Object instance, YamlConfiguration config, File file) {
if (instance.getClass().isAnnotationPresent(Backup.class) &&
instance.getClass().isAnnotationPresent(ConfigVersion.class)) {

Backup backup = instance.getClass().getAnnotation(Backup.class);
ConfigVersion versionAnno = instance.getClass().getAnnotation(ConfigVersion.class);

int fileVersion = config.getInt("config-version", 0);
int classVersion = versionAnno.value();

if (fileVersion < classVersion && backup.enabled() && backup.onMigration()) {
plugin.getLogger().info("Upgrading version (" + fileVersion + " -> " + classVersion + "). Backing up...");
BackupHandler.createBackup(plugin, file, backup.path(), "v" + fileVersion);
}
}
}
}
33 changes: 33 additions & 0 deletions src/main/java/com/bentahsin/configuration/annotation/Backup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.bentahsin.configuration.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Backup {
/**
* Enables or disables the backup system.
*/
boolean enabled() default true;

/**
* The folder path where backups will be stored.
* Specifies the location inside the plugin folder.
*/
String path() default "backups";

/**
* If a YAML error (syntax error) occurs while loading the config,
* should a backup of the corrupted file be taken?
*/
boolean onFailure() default true;

/**
* When the config version changes (migration),
* should a backup of the old config file be taken?
*/
boolean onMigration() default true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.bentahsin.configuration.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Specifies the version of the config file.
* If the "config-version" value in the file is lower than this value,
* the library adds missing settings to the file and updates the version.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ConfigVersion {
int value() default 1;
}
14 changes: 14 additions & 0 deletions src/main/java/com/bentahsin/configuration/annotation/OnReload.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.bentahsin.configuration.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Marks methods to be executed when the config is reloaded.
* Example: To refresh database connections or clear caches.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnReload {}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public ItemStack convertToField(Map<String, Object> source) {
return item;

} catch (Exception e) {
Bukkit.getLogger().log(Level.WARNING, "[Configuration] ItemStack dönüştürülürken hata oluştu!", e);
Bukkit.getLogger().log(Level.WARNING, "[Configuration] Encountered an error while transforming ItemStack!", e);
return new ItemStack(Material.AIR);
}
}
Expand Down
Loading