Added a sort of config framework

Cascading downwards
This commit is contained in:
cmastudios 2014-10-27 18:28:03 -05:00
parent 1d54a2a6c0
commit 2280e5d857
7 changed files with 254 additions and 2 deletions

View File

@ -108,7 +108,7 @@
</dependency>
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>spongeapi</artifactId>
<artifactId>SpongeAPI</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>

View File

@ -1,6 +1,7 @@
package com.tommytony.war;
import com.google.common.collect.ImmutableList;
import com.tommytony.war.zone.ZoneConfig;
import org.spongepowered.api.entity.Player;
import java.io.Closeable;
@ -17,6 +18,7 @@ import java.util.UUID;
*/
public class WarConfig implements Closeable {
private final WarPlugin plugin;
private final ZoneConfig zoneDefaults;
/**
* Database configuration descriptor.
*/
@ -39,6 +41,7 @@ public class WarConfig implements Closeable {
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS zones (name TEXT)");
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS zonemakers (uuid TEXT)");
}
zoneDefaults = new ZoneConfig(conn, "zone_settings");
}
/**
@ -55,12 +58,21 @@ public class WarConfig implements Closeable {
if (result.next()) {
return result.getInt(1);
} else {
return (int) setting.defaultValue;
return (Integer) setting.defaultValue;
}
}
}
}
/**
* Get access to zone default settings.
*
* @return controller of server zone defaults.
*/
public ZoneConfig getZoneDefaults() {
return zoneDefaults;
}
/**
* Load all the enabled war zones on the server.
*

View File

@ -4,6 +4,7 @@ import org.apache.logging.log4j.Logger;
import org.spongepowered.api.Game;
import org.spongepowered.api.event.SpongeEventHandler;
import org.spongepowered.api.event.state.PreInitializationEvent;
import org.spongepowered.api.event.state.ServerStartedEvent;
import org.spongepowered.api.event.state.ServerStartingEvent;
import org.spongepowered.api.plugin.Plugin;
@ -37,6 +38,11 @@ public class WarPlugin {
config = new WarConfig(this, new File(dataDir, "war.sl3"));
}
@SpongeEventHandler
public void onStart(ServerStartedEvent event) {
// register commands
}
public Game getGame() {
return game;
}
@ -45,6 +51,10 @@ public class WarPlugin {
return logger;
}
public File getDataDir() {
return dataDir;
}
public WarConfig getConfig() {
return config;
}

View File

@ -0,0 +1,54 @@
package com.tommytony.war.zone;
import com.tommytony.war.WarPlugin;
import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Representation of a war zone area, blocks, and settings.
* Each zone is to only have one instance of Warzone.class at any given time while the server is running.
*/
public class Warzone {
private static Pattern zoneName = Pattern.compile("[./%]+");
private final WarPlugin plugin;
private final String name;
private final ZoneStorage db;
private final ZoneConfig config;
/**
* Load or create a war zone from the war settings store.
*
* @param plugin Instance of the plugin War.
* @param name Name of the zone. Used to locate the zone data file.
*/
public Warzone(WarPlugin plugin, String name) {
this.plugin = plugin;
this.name = name;
try {
this.db = new ZoneStorage(this, plugin);
this.config = new ZoneConfig(db.getConnection(), "settings", plugin.getConfig().getZoneDefaults());
} catch (SQLException ex) {
plugin.getLogger().error("Failed to load zone database and settings", ex);
throw new RuntimeException("Can't create/load database for warzone " + name);
}
}
/**
* Check if the specified name is valid for a zone.
* Specifically, characters that could be part of a file path or web URL.
* '.', '/', and '%' are invalid.
*
* @param name Potential zone name to check.
* @return true if the name can be used.
*/
public static boolean zoneNameValid(String name) {
Matcher m = zoneName.matcher(name);
return m.find();
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,75 @@
package com.tommytony.war.zone;
import java.sql.*;
/**
* The zone configuration settings database.
*/
public class ZoneConfig {
/**
* Database configuration descriptor.
*/
private final Connection conn;
/**
* Table of values to manage. May be a table in a zone database or the main war database.
*/
private final String table;
/**
* Root zone config, for fallback. Null if this is the war main settings.
*/
private final ZoneConfig parent;
/**
* Manages a zone configuration section.
*
* @param database Active database to use.
* @param table Table name to use in database. Created if it does not exist. Needs to be trusted input.
* @param parent Parent zone config, for fallback. Could be zone config for a team or war global for zones.
* @throws SQLException
*/
public ZoneConfig(Connection database, String table, ZoneConfig parent) throws SQLException {
this.conn = database;
this.table = table;
this.parent = parent;
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate(String.format("CREATE TABLE IF NOT EXISTS %s (option TEXT, value BLOB)", table));
}
}
/**
* Manages a zone configuration section.
*
* @param database Active database to use.
* @param table Table name to use in database. Created if it does not exist. Needs to be trusted input.
* @throws SQLException
*/
public ZoneConfig(Connection database, String table) throws SQLException {
this(database, table, null);
}
/**
* Get the value of an integer setting.
*
* @param setting The type of setting to look up.
* @return the value of the setting or the default if not found.
* @throws SQLException
*/
public int getInt(ZoneSetting setting) throws SQLException {
try (PreparedStatement stmt = conn.prepareStatement(String.format("SELECT value FROM %s WHERE option = ?", table))) {
stmt.setString(1, setting.name());
try (ResultSet result = stmt.executeQuery()) {
if (result.next()) {
// found an override for this config level
return result.getInt(1);
} else if (parent != null) {
// look for it in zone/global configs; will be recursive upwards
return parent.getInt(setting);
} else {
// the hard-coded value for fallback
return (Integer) setting.getDefaultValue();
}
}
}
}
}

View File

@ -0,0 +1,25 @@
package com.tommytony.war.zone;
/**
* Settings that can be changed on a per-zone basis.
* Some can be overridden per-team.
*/
public enum ZoneSetting {
/**
* Maximum players in a zone or team. Zone max is still observed even if team settings allow for more.
*/
MAXPLAYERS(Integer.class, 10, true);
private final Class<?> dataType;
private final Object defaultValue;
private final boolean perTeam;
private ZoneSetting(Class<?> dataType, Object defaultValue, boolean perTeam) {
this.dataType = dataType;
this.defaultValue = defaultValue;
this.perTeam = perTeam;
}
public Object getDefaultValue() {
return defaultValue;
}
}

View File

@ -0,0 +1,76 @@
package com.tommytony.war.zone;
import com.tommytony.war.WarPlugin;
import java.io.File;
import java.sql.*;
/**
* Manages the war zone database file, which contains all the data for the war zone.
*/
public class ZoneStorage implements AutoCloseable {
private static int DATABASE_VERSION = 1;
private final Warzone zone;
private final WarPlugin plugin;
private final Connection connection;
private final File dataStore;
/**
* Initiates a database for a new or existing database.
*
* @param zone The server war zone object for this database.
* @param plugin The war plugin, for storage information and configuration.
* @throws SQLException
*/
ZoneStorage(Warzone zone, WarPlugin plugin) throws SQLException {
this.zone = zone;
this.plugin = plugin;
dataStore = new File(plugin.getDataDir(), String.format("%s.warzone", zone.getName()));
connection = DriverManager.getConnection("jdbc:sqlite:" + dataStore.getPath());
this.upgradeDatabase();
}
Connection getConnection() {
return connection;
}
/**
* Check the database stored version information and perform upgrade tasks if necessary.
*
* @throws SQLException
*/
private void upgradeDatabase() throws SQLException {
int version;
try (
Statement stmt = connection.createStatement();
ResultSet resultSet = stmt.executeQuery("PRAGMA user_version");
) {
version = resultSet.getInt("user_version");
}
if (version > DATABASE_VERSION) {
// version is from a future version
throw new IllegalStateException(String.format("Unsupported zone version: %d. War current version: %d",
version, DATABASE_VERSION));
} else if (version == 0) {
// brand new database file
} else if (version < DATABASE_VERSION) {
// upgrade
switch (version) {
// none yet
default:
// some odd bug or people messing with their database
throw new IllegalStateException(String.format("Unsupported zone version: %d.", version));
}
}
}
/**
* Closes this resource, relinquishing any underlying resources.
*
* @throws Exception if this resource cannot be closed
*/
@Override
public void close() throws Exception {
connection.close();
}
}