Add coordinates system and /warzone

This commit is contained in:
cmastudios 2014-12-05 23:37:03 -06:00
parent 99672561a1
commit 06f7fe9655
4 changed files with 221 additions and 0 deletions

View File

@ -1,5 +1,8 @@
package com.tommytony.war;
import com.google.common.base.Optional;
import com.tommytony.war.command.WarzoneCommand;
import com.tommytony.war.zone.Warzone;
import org.slf4j.Logger;
import org.spongepowered.api.Game;
import org.spongepowered.api.event.state.PreInitializationEvent;
@ -11,6 +14,7 @@ import org.spongepowered.api.util.event.Subscribe;
import java.io.File;
import java.io.FileNotFoundException;
import java.sql.SQLException;
import java.util.Map;
@Plugin(id = "war", name = "War", version = "2.0-SNAPSHOT")
public class WarPlugin {
@ -18,6 +22,7 @@ public class WarPlugin {
private Logger logger;
private File dataDir;
private WarConfig config;
private Map<String, Warzone> zones;
@Subscribe
public void onConstruction(PreInitializationEvent event) throws InstantiationException {
@ -36,11 +41,16 @@ public class WarPlugin {
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"));
for (String zoneName : config.getZones()) {
Warzone zone = new Warzone(this, zoneName);
zones.put(zoneName, zone);
}
}
@Subscribe
public void onStart(ServerStartedEvent event) {
// register commands
game.getCommandDispatcher().register(this, new WarzoneCommand(this), "warzone", "zone");
}
public Game getGame() {
@ -58,4 +68,15 @@ public class WarPlugin {
public WarConfig getConfig() {
return config;
}
public Optional<Warzone> getZone(String zoneName) {
if (zones.containsKey(zoneName)) {
return Optional.of(zones.get(zoneName));
}
return Optional.absent();
}
public Map<String, Warzone> getZones() {
return zones;
}
}

View File

@ -0,0 +1,126 @@
package com.tommytony.war.command;
import com.google.common.base.Optional;
import com.tommytony.war.WarPlugin;
import com.tommytony.war.zone.Warzone;
import org.spongepowered.api.entity.player.Player;
import org.spongepowered.api.util.command.CommandCallable;
import org.spongepowered.api.util.command.CommandException;
import org.spongepowered.api.util.command.CommandSource;
import java.util.ArrayList;
import java.util.List;
/**
* Teleport to warzone.
*/
public class WarzoneCommand implements CommandCallable {
private WarPlugin plugin;
public WarzoneCommand(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 (!(source instanceof Player)) {
return false;
}
String[] argv = arguments.split(" ");
if (argv.length < 1) {
return false;
}
String zoneName = argv[0];
Optional<Warzone> zone = plugin.getZone(zoneName);
if (!zone.isPresent()) {
return false;
}
Player player = (Player) source;
player.teleport(zone.get().getTeleport());
return true;
}
/**
* 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) {
return true;
}
/**
* Get a short one-line description of this command.
*
* @return A description, if available
*/
@Override
public Optional<String> getShortDescription() {
return Optional.of("Teleport to a zone");
}
/**
* Get a longer help text about this command.
*
* @return A help text, if available
*/
@Override
public Optional<String> getHelp() {
return Optional.of("Use this command to teleport to a zone lobby");
}
/**
* Get the usage string of this command.
* <p/>
* <p>A usage string may look like
* {@code [-w &lt;world&gt;] &lt;var1&gt; &lt;var2&gt;}.</p>
*
* @return A usage string
*/
@Override
public String getUsage() {
return "<zone>";
}
/**
* 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 (String zone : plugin.getZones().keySet()) {
if (zone.toLowerCase().startsWith(arguments.toLowerCase()))
suggestions.add(zone);
}
return suggestions;
}
}

View File

@ -1,6 +1,9 @@
package com.tommytony.war.zone;
import com.google.common.base.Optional;
import com.tommytony.war.WarPlugin;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
import java.sql.SQLException;
import java.util.regex.Matcher;
@ -16,6 +19,7 @@ public class Warzone {
private final String name;
private final ZoneStorage db;
private final ZoneConfig config;
private Location teleport;
/**
* Load or create a war zone from the war settings store.
@ -51,4 +55,16 @@ public class Warzone {
public String getName() {
return name;
}
public Location getTeleport() {
try {
Optional<Location> lobby = db.getPosition("lobby", Optional.<World>absent());
if (lobby.isPresent())
return lobby.get();
else throw new RuntimeException("No teleport location found for zone " + name);
} catch (SQLException e) {
plugin.getLogger().error("Retrieving teleport", e);
throw new RuntimeException("Error in retrieving information from database");
}
}
}

View File

@ -1,6 +1,10 @@
package com.tommytony.war.zone;
import com.google.common.base.Optional;
import com.tommytony.war.WarPlugin;
import org.spongepowered.api.math.Vectors;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
import java.io.File;
import java.sql.*;
@ -53,6 +57,9 @@ public class ZoneStorage implements AutoCloseable {
version, DATABASE_VERSION));
} else if (version == 0) {
// brand new database file
Statement stmt = connection.createStatement();
stmt.executeUpdate("CREATE TABLE coordinates (name TEXT UNIQUE, x NUMERIC, y NUMERIC, z NUMERIC, world TEXT)");
stmt.executeUpdate(String.format("PRAGMA user_version = %d", DATABASE_VERSION));
} else if (version < DATABASE_VERSION) {
// upgrade
switch (version) {
@ -64,6 +71,57 @@ public class ZoneStorage implements AutoCloseable {
}
}
/**
* Look up a position in the coordinates table.
*
* @param name Name of stored position.
* @param world World to assign to the new location.
* @return the location of the position, or absent if not found.
* @throws SQLException
*/
public Optional<Location> getPosition(String name, Optional<World> world) throws SQLException {
try (PreparedStatement stmt = connection.prepareStatement(
"SELECT x, y, z, world FROM coordinates WHERE name = ?")) {
stmt.setString(1, name);
try (ResultSet resultSet = stmt.executeQuery()) {
if (resultSet.next()) {
World resultWorld;
if (world.isPresent()) resultWorld = world.get();
else resultWorld = plugin.getGame().getWorld(resultSet.getString("world"));
return Optional.of(new Location(resultWorld, Vectors.create3d(
resultSet.getDouble("x"), resultSet.getDouble("y"), resultSet.getDouble("z"))));
}
}
}
return Optional.absent();
}
/**
* Set a position in the coordinates table to a location.
*
* @param name Name of position in storage.
* @param location Location to write to the storage.
* @throws SQLException
*/
public void setPosition(String name, Location location) throws SQLException {
World world;
if (location.getExtent() instanceof World)
world = (World) location.getExtent();
else throw new IllegalArgumentException("Location must be in a world");
String sql;
if (this.getPosition(name, Optional.<World>absent()).isPresent())
sql = "UPDATE coordinates SET x = ?, y = ?, z = ?, world = ? WHERE name = ?";
else sql = "INSERT INTO coordinates (x, y, z, world, name) VALUES (?, ?, ?, ?, ?)";
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setDouble(1, location.getPosition().getX());
stmt.setDouble(2, location.getPosition().getY());
stmt.setDouble(3, location.getPosition().getZ());
stmt.setString(4, world.getName());
stmt.setString(5, name);
stmt.execute();
}
}
/**
* Closes this resource, relinquishing any underlying resources.
*