BukkitWiki

Welcome to the BukkitWiki!

This Wiki is home to Bukkit's documentation and regulations surrounding the Bukkit Project and it's services. Want to help out? We would love to have you! Signup to get started!

READ MORE

BukkitWiki
Advertisement

Die Konfigurations-API ist ein Bündel von Tools die Entwicklern hilft, schnell Konfigurationsdatein zu laden und zu teilen, die von Menschen gelesen und bearbeitet werden können. Aktuell unterstüzt das Sytem nur Dateien die das YAML Schema nutzen. Mit der API können neue Formate hinzugefügt werden, da die übergeordnete API vom Schema unabhängig ist.

Diese Einführung erfordert Wissen über Java, Pluginentwicklung mit Bukkit und objektorientierte Programmierung.

Themen[]

Das Konfigurations Objekt[]

Dein Plugin erweitert JavaPlugin und erbt dabei dessen Methoden und Felder. Die geerbte Methode getConfig() gibt ein Objekt vom Typ org.bukkit.configuration.file.FileConfiguration zurück. Dieses Objekt repräsentiert die config.yml innerhalb deines Pluginordners.

Das erste Mal, wenn getConfig() innerhalb deines Plugins aufgrufen wird, wird die config.yml von deiner Festplatte, sowie Standardwerte aus deiner JAR, geladen. Von nun an wird getConfig() das FileConfiguration Objekt zurückgeben, dass sich im Speicher befindet. Alle Operationen werden auf dieses Objekt angewandt und beeinflussen nicht die Datei auf der Festplatte. Wenn die config.yml nicht existiert, wird dies mit einer leeren Datei gleichgesetzt und hat auch ein leeres FileConfiguration Objekt zur Folge.

Warning Warnung:  Wenn du das zurückgegebende Objekt von getConfig() zuweist, weise es nicht einem statischen Feld zu
Warning Warnung:  Wenn du obiges tust, weise getConfig() der Variable nach dem Neuladen der Konfiguration erneut zu.

Lightbulb Note: Es ist besser nur getConfig() zu nutzen, anstatt es zu speichern

Standardwerte[]

Standardwerte für deine config.yml sollten für den Benutzer bereitsgestellt werden. Wenn die Konfigurationsdatei deines Pluginordners nicht existiert, leer ist, oder ihr Schlüssel fehlen, werden die Werte aus deiner JAR gelesen. Standardwerte sollten in einer YAML-Datei bereitgestellt werden, die exakt dieselbe Struktur hat, wie du es von der config.yml erwartest. Die Datei muss config.yml heißen und im selben Verzeichnis wie deine  plugin.yml liegen. Wenn du die Standardwerte kopieren und überschreiben willst, dann musst du die Methode copyDefaultConfig() des JavaPlugin aufrufen. Wenn du existierende Dateien nicht überschreiben möchtest, setze copyDefaults auf true. 

Wenn du standardmäßig dynamische Werte als Standardwert verwendest, können diese mit der MethodeaddDefault(String, Object) und addDefaults(Map<String,Object>) hinzugefügt.

Werte auslesen[]

Werte aus der Konfiguration lesen erfordert das Nutzen einer der vielen Getter-Methoden. Eine kompllete Liste aller Getter-Methoden kannst du hier finden. Ein paar typische Getter-Methoden sind die Folgenden:

  • getBoolean(String)
  • getInt(String)
  • getString(String)
  • getList(String)
  • getStringList(String)

Schlüssel[]

Das Auslesen von Schlüsseln, die keine Werte darstellen, funktioniert anders als bei den anderen Getter-Methoden. Der Aufruf der Methode liefert eine Liste aller Schlüssel der aktuellen FileConfigurationSection zurück. Um einen speziellen Abschnitt zu erhalten benutzt du die Methode getConfigurationSection(String) bevor du die Methode getKeys(boolean) aufrufst. Der boolsche Wert legt fest, ob die zurückgelieferte Liste rekursiv ist. Bei true werden die Schlüssel und alle Kindschlüssel des Abschnittes zurückgegeben. Bei false lediglich die Schlüssel.

  • getKeys(boolean)
Lightbulb Note: Dies gibt jetzt ein Set von Strings zurück!

Werte setzen[]

Werte schreiben erfordert das Aufrufen der Methode set(String, Object) einer Instanz von Configuration. Im Gegensatz zu den verschiedenen Getter-Methoden des FileConfiguration Objekts, gibt es nur eine Setter-Methode. Nicht alle Objekte können gesetzt werden, lediglich einfache Typen, Strings, Listen und Typen die von ConfigurationSerializable implementiert werden. Dazu zählen z.B. Vector und ItemStack. Um einen Wert zu löschen, setze ihn auf null. Alle Änderungen wirken sich lediglich auf die Kopie der Konfiguration im Speicher aus und sind nicht dauerhaft. Bevor du den Server neustartest, speichere die Konfiguration.

Hier ein paar Beispiele:

// setting a boolean value
this.getConfig().set("path.to.boolean", true);

// setting a String
String string = "Hello World!";
this.getConfig().set("path.to.string", stringValue);

// Setting a List of Strings
// The List of Strings is first defined in this array
String[] listOfStrings = {"Hello World", "Welcome to Bukkit", "Have a Good Day!"};
this.getConfig().set("path.to.list", Arrays.asList(listOfStrings);

// Setting a vector
// event is assumed to be an existing event inside an "onEvent" method.
Vector vector = event.getPlayer().getLocation().toVector();
this.getConfig().set("path.to.vector", vector);

// Erasing a value
this.getConfig().set("path.to.value", null);


HashMaps[]

Wenn du eine HashMap schreiben willst, musst du eine ConfigurationSection erstellen. Du kannst eine HashMap nur speichern, wenn der Schlüssel ein String und der Wert ein bereits ein ConfigurationSerializable Objekt ist.

createSection (String path, Map< String, Object > map);

Die Datei speichern[]

Wenn du Änderungen am FileConfiguration Objekt vornimmst und diese behalten möchtest, musst du diese auf die Festplatte speichern. Dafür rufst du die Methode saveConfig() auf. Ist bereits eine Datei vorhanden wird diese überschrieben. 

this.saveConfig();

Von der Festplatte neuladen[]

Wenn du glaubst das der Nutzer die config.yml verändert hat, werden diese nicht automatisch im Speicher übernommen. Die Methode reloadConfig() lädt die Konfiguration erneut von der Festplatte. Diese Operation zerstört alle Änderungen im Speicher. 

this.reloadConfig();

Fortgeschrittene Themen[]

Nachfolgend einige fortgeschrittene Themen für fortgeschrittene Plugins.

Optionen[]

Jedes FileConfiguration-Objekt ist mit einem FileConfigurationOptions-Objekt assoziert. Dieses kontrolliert das Verhalten der FileConfiguration. Die Methode FileConfiguration.options() gibt das verantwortliche  FileConfigurationOptions-Objekt zurück. Damit kannst du Optionen überprüfen und setzen. Aktuell gibt es vier Optionen. Bedenke, dass bestimmte Methoden überladen sind. copyDefaults() zum Beispiel gibt einen booleschen Wert zurück und copyDefaults(boolean) gibt self zurück, hat jedoch Nebeneffekte, die den Status verändern.

copyDefaults[]

Die copyDefaults-Option verändert das Verhalten der "Speichern"-Methode einer Konfiguration. Standardmäßig werden die Standardwerte nicht in die Zieldatei geschrieben. Wenn auf true gesetzt, werden auch Standardwerte in die Zieldatei geschrieben. Einmal gespeichert wirst du nicht mehr in der Lage sein, zwischen Standardwert und "echtem" Wert zu unterscheiden.

pathSeperator[]

Die Option pathSeperator verändert den Char, welcher genutzt wird, um beim Setzen des Pfades mit addDefault(String path, Object value) die Ebenen der Konfiguration zu abzugrenzen. Standardmäßig ist es "." (Punkt), aber dies kann zu jedem anderen Char geändert werden.

header[]

Der Header ist der Kommentarblock am Anfang der YAML-Datei. Die Option erhält den String, der in die Datei geschrieben wird. Er ist der einzige Kommentar, welcher von der Configuration API kopiert werden kann.

copyHeader[]

Wenn copyHeader() true zurückliefert, wird der Header beim Speichern von der Standardquelle kopiert.

Methoden um eigene Konfigurationen zu Laden, Aktualisieren und Speichern[]

Wenn du zusätzliche YAML-Dateien benötigst, um Konfigurationsinfos oder statische zusätzliche Spielinformationen zu speichern, musst du eigene Methoden schreiben, um auf diese zusätzlichen Konfigurationsdateien zu greifen zu können. Den Model Prinzipien des JavaPlugin folgend, hier ein Beispiel, wie du deine eigenen Methoden zum Lesen und Schreiben eigener Konfigurationsdateien schreiben könntest. Da diese Dateien zu deinem Plugin gehören, kannst du diese Methode in deine Grund-Klasse packen. Du muss die folgenden Methoden für jede YAML-Datei schreiben. Der Vorteil besteht darin, dass du diese genauso nutzen kannst, wie die für die config.yml bereitgestellten Methoden.

Zuerst musst du zwei Felder deklarieren und diese für die benutzerdefinierte Konfiugration initialisieren. Eine um die FileConfiguration zu speichern und eine um die Datei zu speichern. Das File Objekt repräsentiert die Datei auf der Festplatte, die FileConfiguration repräsentiert den Inhalt der Konfiguration.

private FileConfiguration customConfig = null;
private File customConfigurationFile = null;

Dannach schreibe die Methode, die für das Laden der Konfiguration von der Platte, zu ständig ist. Diese wird die Datei laden und die JAR nach der standardmäßigen customConfig.yml durchsuchen.

public void reloadCustomConfig() {
    if (customConfigFile == null) {
    customConfigFile = new File(getDataFolder(), "customConfig.yml");
    }
    customConfig = YamlConfiguration.loadConfiguration(customConfigFile);

    // Schaut nach den Standardwerten in der jar
    InputStream defConfigStream = getResource("customConfig.yml");
    if (defConfigStream != null) {
        YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream);
        customConfig.setDefaults(defConfig);
    }
}

Als nächstes musst du eine Getter-Methode schreiben. Prüfe ob customConfig null ist, wenn sie von der Platte geladen wurde.

public FileConfiguration getCustomConfig() {
    if (customConfig == null) {
        reloadCustomConfig();
    }
    return customConfig;
}

Abschließen schreibe die Methode zum Abspeichern. Diese speichert die Änderungen und überschreibt die Datei auf der Festplatte.

public void saveCustomConfig() {
    if (customConfig == null || customConfigFile == null) {
    return;
    }
    try {
        customConfig.save(customConfigFile);
    } catch (IOException ex) {
        Logger.getLogger(JavaPlugin.class.getName()).log(Level.SEVERE, "Konfiguration konnte nicht nach " + customConfigFile + " geschrieben werden.", ex);
    }
}

Nachdem du diese Methoden in die Hauptklasse deines Plugins eingefügt hast, kannst du sie auf die selbe Art und Weise nutzen, wie die geerbten Methoden getConfig(), reloadConfig() und saveConfig().

Serialisieren und Deserialisieren von Objekten[]

Jedes Objekt das du serialisieren möchtest muss das Interface ConfigurationSerializable implentieren. Serialisierte Objkete erlauben es dem Entwickler schnell Spielinformationen zu speichern und ermöglichen das einfache Laden. Es vereinfacht stark Aufgaben, wie z.B., das Speichern einer Location in YAML. Ein Entwickler kann eine Wrapper-Klasse serialisieren, die Methoden bereitstellt, um eine Location zu laden.

Zusätzlich zur Implementation des Interfaces musst du eines der Folgenden implementieren:

  • Ein Konstruktor der eine einzelne Map implementiert.
  • Eine statische Methode "deserialize" die eine einzelne Map akzeptiert und eine Klasse zurück gibt.
  • Eine statische Methode "valueOf" die eine einzelne Map akzeptiert und eine Klasse zurück gibt.

Du musst außerdem die Klasse mit ConfigurationSerialization registrieren, bevor du versucht ein Objekt zu deserialisieren. Dieser Ausdruck kann in einem statischen, initialisierenden Block deiner Klasse abgelegt werden.

ConfigurationSerialization.registerClass(Class<? extends ConfigurationSerializable> class)


Lightbulb Note: ein verzweigtes ConfigurationSerializable Objekt wird als Typ Map zurückgegeben und muss als solches gecasted werden. Weiterhin muss es an eine der Deserialisierungs-Methoden gegeben werden, wenn die Eltern-Klasse deserialisiert wird.

Aliase[]

Du kannst deiner Klasse einen Alias bereitstellen, sodass sie nicht mit dem vollwertigen Namen der Klasse serialisiert wird. Das tust do mit der SerializeAs Annotation in der Klasse die ConfigurationSerializable implementiert.

@SerilizeAs(String alias)

Wenn du eine Klasse mit Alias registrierst, dann muss der Alias bereits zur Registrierung bereitgestellt werden.

ConfigurationSerialization.registerClass(Class<? extends ConfigurationSerializable> class, String alias)

Beispiele[]

Unten findest du ein Beispiel für ein Plugin, welches die neue Konfigurations API nutzt, um Nachrichten zu speichern, die als MOTD angezeigt werden, wenn ein Spieler beitritt. Es folgt nicht dem gewünschten Stil und Layout, da es in 50 Zeilen Platz finden sollte.

import java.util.*;
import org.bukkit.command.*;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.event.Event.*;
import org.bukkit.event.player.PlayerListener;

public class SimpleMOTD extends JavaPlugin {

    public void onDisable() {
        System.out.println(this.toString() + " disabled");
    }

    public void onEnable() {
        this.getServer().getPluginManager().registerEvent(Type.PLAYER_JOIN,
                new PlayerListener() {

                    @Override
                    public void onPlayerJoin(PlayerJoinEvent event) {
                        event.getPlayer().sendMessage(getConfig().getString("message"));
                    }
                },
                Priority.Normal,
                this);

        this.getCommand("rules").setExecutor(new CommandExecutor() {

            public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
                List<String> rules = getConfig().getList("rules");
                Iterator<String> iter = rules.iterator();
                while (iter.hasNext()) {
                    sender.sendMessage(iter.next());
                }
                return true;
            }
        });

        this.getConfig().options().copyDefaults(true);
        saveConfig();
        System.out.println(this.toString() + " enabled");
    }
}

The default config.yml

# default config.yml
message: Hello World and Welcome! :)
rules:
- Play Nice
- Respect others
- Have Fun
Language   EnglishбеларускаяDeutschespañolsuomifrançaisitaliano한국어Nederlandsnorskpolskiportuguêsрусскийlietuviųčeština
Advertisement