War 2.0 for SpongeAPI started!

Just started rewriting a bit, in case this API really does come
through eventually. Sponge is scheduled for release in November.

Whadya think @taoneill ?
Pouvez-vous nous aider @kugick ?
This commit is contained in:
cmastudios 2014-10-27 16:43:13 -05:00
parent e786c09bd0
commit 1d54a2a6c0
6 changed files with 607 additions and 0 deletions

5
sponge/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
target/
war.iml
.project
.classpath
.workspace/

181
sponge/pom.xml Normal file
View File

@ -0,0 +1,181 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tommytony</groupId>
<artifactId>war</artifactId>
<version>2.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>War</name>
<url>http://war.tommytony.com</url>
<description>The original TDM/CTF plugin for Minecraft</description>
<inceptionYear>2010</inceptionYear>
<licenses>
<license>
<name>MIT License</name>
<url>http://opensource.org/licenses/MIT</url>
<distribution>repo</distribution>
</license>
</licenses>
<organization>
<name>TeamWar</name>
<url>http://community.tommytony.com</url>
</organization>
<developers>
<developer>
<id>cmastudios</id>
<name>Connor Monahan</name>
<email>cma@tommytony.com</email>
<url>https://cmastudios.me</url>
<organization>TeamWar</organization>
<organizationUrl>http://community.tommytony.com</organizationUrl>
<roles>
<role>maintainer</role>
</roles>
<timezone>America/Chicago</timezone>
</developer>
<developer>
<id>tommytony</id>
<name>Thomas-Antoine O'Neill</name>
<email>taoneill@tommytony.com</email>
<url>http://tommytony.com</url>
<organization>TeamWar</organization>
<organizationUrl>http://community.tommytony.com</organizationUrl>
<roles>
<role>dictator</role>
</roles>
<timezone>America/Montreal</timezone>
</developer>
</developers>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/taoneill/war/issues</url>
</issueManagement>
<ciManagement>
<system>Jenkins</system>
<url>http://ci.tommytony.com</url>
</ciManagement>
<mailingLists>
<mailingList>
<name>Google Groups</name>
<subscribe>minecraft-war+subscribe@googlegroups.com</subscribe>
<unsubscribe>minecraft-war+unsubscribe@googlegroups.com</unsubscribe>
<post>minecraft-war@googlegroups.com</post>
<archive>https://groups.google.com/forum/#!forum/minecraft-war</archive>
</mailingList>
</mailingLists>
<scm>
<connection>scm:git:https://github.com/taoneill/war.git</connection>
<developerConnection>scm:git:https://github.com/taoneill/war.git</developerConnection>
<tag>HEAD</tag>
<url>https://github.com/taoneill/war</url>
</scm>
<distributionManagement>
<downloadUrl>http://war.tommytony.com</downloadUrl>
<repository>
<id>war-repo</id>
<name>War Jenkins Maven Builds</name>
<url>http://ci.tommytony.com/plugin/repository/everything/</url>
</repository>
</distributionManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>war-repo</id>
<url>http://ci.tommytony.com/plugin/repository/everything/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spongepowered</groupId>
<artifactId>spongeapi</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.7.2</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.14</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>7</source>
<target>7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.7.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>org.xerial:sqlite-jdbc</include>
<include>org.yaml:snakeyaml</include>
</includes>
</artifactSet>
<minimizeJar>false</minimizeJar>
<relocations>
<relocation>
<pattern>org.sqlite</pattern>
<shadedPattern>com.tommytony.war.sqlite</shadedPattern>
</relocation>
<relocation>
<pattern>org.ibex</pattern>
<shadedPattern>com.tommytony.war.ibex</shadedPattern>
</relocation>
<relocation>
<pattern>org.yaml.snakeyaml</pattern>
<shadedPattern>com.tommytony.war.yaml</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<filtering>true</filtering>
<directory>${basedir}/src/main/resources/</directory>
</resource>
</resources>
</build>
</project>

View File

@ -0,0 +1,133 @@
package com.tommytony.war;
import com.google.common.collect.ImmutableList;
import org.spongepowered.api.entity.Player;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
/**
* The main war configuration database.
*/
public class WarConfig implements Closeable {
private final WarPlugin plugin;
/**
* Database configuration descriptor.
*/
private Connection conn;
/**
* Load the war config database for future use.
*
* @param file War configuration database location.
* @throws FileNotFoundException
* @throws SQLException
*/
public WarConfig(WarPlugin plugin, File file) throws FileNotFoundException, SQLException {
this.plugin = plugin;
if (!file.exists())
throw new FileNotFoundException("Can't find war main database");
conn = DriverManager.getConnection("jdbc:sqlite:" + file.getPath());
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS settings (option TEXT, value BLOB)");
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS zones (name TEXT)");
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS zonemakers (uuid TEXT)");
}
}
/**
* 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(WarSetting setting) throws SQLException {
try (PreparedStatement stmt = conn.prepareStatement("SELECT value FROM settings WHERE option = ?")) {
stmt.setString(1, setting.name());
try (ResultSet result = stmt.executeQuery()) {
if (result.next()) {
return result.getInt(1);
} else {
return (int) setting.defaultValue;
}
}
}
}
/**
* Load all the enabled war zones on the server.
*
* @return list of war zones.
* @throws SQLException
*/
public Collection<String> getZones() throws SQLException {
ArrayList<String> zones = new ArrayList<>();
try (Statement stmt = conn.createStatement();
ResultSet result = stmt.executeQuery("SELECT name FROM zones")) {
while (result.next()) {
zones.add(result.getString(1));
}
}
return ImmutableList.copyOf(zones);
}
/**
* Get server zone makers. These people have permission to create zones.
*
* @return list of zone makers.
* @throws SQLException
*/
public Collection<Player> getZoneMakers() throws SQLException {
ArrayList<Player> makers = new ArrayList<>();
try (Statement stmt = conn.createStatement();
ResultSet result = stmt.executeQuery("SELECT uuid FROM zonemakers")) {
while (result.next()) {
UUID playerId = UUID.fromString(result.getString(1));
if (playerId == null)
continue;
Player player = plugin.getGame().getPlayer(playerId);
if (player == null)
continue;
makers.add(player);
}
}
return ImmutableList.copyOf(makers);
}
/**
* Closes this stream and releases any system resources associated
* with it. If the stream is already closed then invoking this
* method has no effect.
*
* @throws java.io.IOException if an I/O error occurs
*/
@Override
public void close() throws IOException {
try {
conn.close();
} catch (SQLException e) {
throw new IOException(e);
}
}
/**
* Possible types of settings stored in the war server config database.
*/
public enum WarSetting {
MAXZONES(Integer.class, 20);
private final Class<?> dataType;
private final Object defaultValue;
private WarSetting(Class<?> dataType, Object defaultValue) {
this.dataType = dataType;
this.defaultValue = defaultValue;
}
}
}

View File

@ -0,0 +1,51 @@
package com.tommytony.war;
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.ServerStartingEvent;
import org.spongepowered.api.plugin.Plugin;
import java.io.File;
import java.io.FileNotFoundException;
import java.sql.SQLException;
@Plugin(id = "war", name = "War", version = "2.0-SNAPSHOT")
public class WarPlugin {
private Game game;
private Logger logger;
private File dataDir;
private WarConfig config;
@SpongeEventHandler
public void onConstruction(PreInitializationEvent event) throws InstantiationException {
game = event.getGame();
logger = event.getPluginLog();
dataDir = event.getConfigurationDirectory();
try {
Class.forName("com.tommytony.war.sqlite.JDBC").newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new InstantiationException("Failed to load SQLite database");
}
}
@SpongeEventHandler
public void onStartUp(ServerStartingEvent event) throws FileNotFoundException, SQLException {
if (!dataDir.exists() && !dataDir.mkdirs())
throw new FileNotFoundException("Failed to make War data folder at " + dataDir.getPath());
config = new WarConfig(this, new File(dataDir, "war.sl3"));
}
public Game getGame() {
return game;
}
public Logger getLogger() {
return logger;
}
public WarConfig getConfig() {
return config;
}
}

View File

@ -0,0 +1,134 @@
package com.tommytony.war.command;
import com.google.common.collect.ImmutableList;
import com.tommytony.war.WarConfig;
import com.tommytony.war.WarPlugin;
import org.spongepowered.api.entity.Player;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.util.command.CommandCallable;
import org.spongepowered.api.util.command.CommandException;
import org.spongepowered.api.util.command.CommandSource;
import org.spongepowered.api.util.command.Description;
import javax.annotation.Nullable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class WarConfigCommand implements CommandCallable {
private final WarPlugin plugin;
public WarConfigCommand(WarPlugin plugin) {
this.plugin = plugin;
}
/**
* Execute the command based on input arguments.
* <p/>
* <p>The implementing class must perform the necessary permission
* checks.</p>
*
* @param source The caller of the command
* @param arguments The raw arguments for this command
* @param parents A stack of parent commands, where the first entry is
* the root command
* @return Whether a command was processed
* @throws org.spongepowered.api.util.command.CommandException Thrown on a command error
*/
@Override
public boolean call(CommandSource source, String arguments, List<String> parents) throws CommandException {
if (!testPermission(source)) {
source.sendMessage("You do not have permission for this command.");
return true;
}
source.sendMessage("you do have permission");
return false;
}
/**
* Get a description of the command, detailing usage information.
*
* @return The command description
*/
@Override
public Description getDescription() {
return new Description() {
@Nullable
@Override
public String getShortDescription() {
return "View/modify war config";
}
@Nullable
@Override
public String getHelp() {
return "Allows viewing of the war server config or changing various settings.";
}
@Override
public String getUsage() {
return "[-p] setting:value...";
}
@Override
public List<String> getPermissions() {
return ImmutableList.of("war.admin", "war.admin.config");
}
};
}
/**
* Test whether this command can probably be executed by the given source.
* <p/>
* <p>If implementations are unsure if the command can be executed by
* the source, {@code true} should be returned. Return values of this method
* may be used to determine whether this command is listed in command
* listings.</p>
*
* @param source The caller of the command
* @return Whether permission is (probably) granted
*/
@Override
public boolean testPermission(CommandSource source) {
if (source instanceof Player) {
try {
if (plugin.getConfig().getZoneMakers().contains(source)) {
source.sendMessage("You are a zone maker.");
return true;
}
} catch (SQLException e) {
plugin.getLogger().error("Loading zone makers for testing permission", e);
}
}
if (source instanceof Subject && ((Subject) source).isPermitted("war.admin.config")) {
source.sendMessage("You are a war admin.");
return true;
}
if (!(source instanceof Player) && !(source instanceof Subject)) {
source.sendMessage("You are console or something.");
return true;
}
return false;
}
/**
* Get a list of suggestions based on input.
* <p/>
* <p>If a suggestion is chosen by the user, it will replace the last
* word.</p>
*
* @param source The command source
* @param arguments The arguments entered up to this point
* @return A list of suggestions
* @throws org.spongepowered.api.util.command.CommandException Thrown if there was a parsing error
*/
@Override
public List<String> getSuggestions(CommandSource source, String arguments) throws CommandException {
ArrayList<String> suggestions = new ArrayList<>();
for (WarConfig.WarSetting setting : WarConfig.WarSetting.values()) {
if (setting.name().toLowerCase().startsWith(arguments.toLowerCase()))
suggestions.add(setting.name().toLowerCase() + ":");
}
return suggestions;
}
}

View File

@ -0,0 +1,103 @@
package com.tommytony.war.struct;
import org.spongepowered.api.block.Block;
import org.spongepowered.api.math.Vector3d;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.extent.BlockVolume;
/**
* A selection of blocks in the world. Identified by two corners.
*/
public class Region implements BlockVolume {
/**
* One corner of the selection.
*/
private Location first;
/**
* The second corner of the selection.
*/
private Location second;
public Region(Location first, Location second) {
this.first = first;
this.second = second;
}
/**
* Calculate the minimum value of the selection.
*
* @return the minimum value.
*/
public Location getMin() {
return new Location(first.getExtent(), first.getPosition().min(second.getPosition()));
}
/**
* Calculate the maximum value of the selection.
*
* @return the maximum value.
*/
public Location getMax() {
return new Location(first.getExtent(), first.getPosition().max(second.getPosition()));
}
/**
* Get the size of the region in the X dimension.
*
* @return X dimension length.
*/
public int getSizeX() {
return getMax().getBlock().getX() - getMin().getBlock().getX();
}
/**
* Get the size of the region in the Y dimension.
*
* @return Y dimension length.
*/
public int getSizeY() {
return getMax().getBlock().getY() - getMin().getBlock().getY();
}
/**
* Get the size of the region in the Z dimension.
*
* @return Z dimension length.
*/
public int getSizeZ() {
return getMax().getBlock().getZ() - getMin().getBlock().getZ();
}
/**
* Get the total area of the region.
*
* @return region total area.
*/
public int getSize() {
return getSizeX() * getSizeY() * getSizeZ();
}
/**
* Get a representation of the block at the given position.
*
* @param position The position
* @return The block
*/
@Override
public Block getBlock(Vector3d position) {
return first.getExtent().getBlock(position);
}
/**
* Get a representation of the block at the given position.
*
* @param x The X position
* @param y The Y position
* @param z The Z position
* @return The block
*/
@Override
public Block getBlock(int x, int y, int z) {
return first.getExtent().getBlock(x, y, z);
}
}