Initial Development
- Add Stop Complete
This commit is contained in:
commit
3566555893
31 files changed
+1018
No files matched your search
@@ -0,0 +1,72 @@
|
||||
|
||||
package com.rsscripting.rstaxi;
|
||||
|
||||
import com.rsscripting.rstaxi.commands.CabCommand;
|
||||
import com.rsscripting.rstaxi.language.LanguageManager;
|
||||
import com.rsscripting.rstaxi.database.DatabaseManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public final class RSTaxi extends JavaPlugin {
|
||||
|
||||
private LanguageManager languageManager;
|
||||
private DatabaseManager databaseManager;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
|
||||
saveDefaultConfig();
|
||||
|
||||
if (!new java.io.File(getDataFolder(), "language/en_us.yml").exists()) {
|
||||
saveResource("language/en_us.yml", false);
|
||||
}
|
||||
|
||||
languageManager = new LanguageManager(this);
|
||||
languageManager.load();
|
||||
|
||||
databaseManager = new DatabaseManager(this);
|
||||
|
||||
try {
|
||||
databaseManager.connect();
|
||||
databaseManager.initialize();
|
||||
} catch (java.sql.SQLException e) {
|
||||
getLogger().severe("Failed to initialize SQLite database!");
|
||||
getLogger().severe(e.getMessage());
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (getCommand("cab") == null) {
|
||||
getLogger().severe("Command 'cab' is missing from plugin.yml!");
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
|
||||
getCommand("cab").setExecutor(new CabCommand(this));
|
||||
|
||||
getLogger().info("RS-Taxi has been enabled!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
|
||||
if (databaseManager != null) {
|
||||
databaseManager.close();
|
||||
}
|
||||
|
||||
getLogger().info("RS-Taxi has been disabled!");
|
||||
|
||||
|
||||
}
|
||||
|
||||
public LanguageManager getLanguageManager() {
|
||||
return languageManager;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public DatabaseManager getDatabaseManager() {
|
||||
return databaseManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
|
||||
package com.rsscripting.rstaxi.commands;
|
||||
|
||||
import com.rsscripting.rstaxi.RSTaxi;
|
||||
import com.rsscripting.rstaxi.platform.PlatformValidator;
|
||||
import com.rsscripting.rstaxi.stops.StopManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public final class CabCommand implements CommandExecutor {
|
||||
|
||||
private final RSTaxi plugin;
|
||||
private final PlatformValidator platformValidator;
|
||||
private final StopManager stopManager;
|
||||
|
||||
public CabCommand(RSTaxi plugin) {
|
||||
this.plugin = plugin;
|
||||
this.platformValidator = new PlatformValidator(plugin);
|
||||
this.stopManager = new StopManager(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(
|
||||
CommandSender sender,
|
||||
Command command,
|
||||
String label,
|
||||
String[] args
|
||||
) {
|
||||
if (args.length == 0) {
|
||||
return handleTravel(sender, args);
|
||||
}
|
||||
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "add" -> {
|
||||
return handleAdd(sender, args);
|
||||
}
|
||||
case "update" -> {
|
||||
return handleUpdate(sender, args);
|
||||
}
|
||||
case "edit" -> {
|
||||
return handleEdit(sender, args);
|
||||
}
|
||||
case "remove" -> {
|
||||
return handleRemove(sender, args);
|
||||
}
|
||||
case "list" -> {
|
||||
return handleList(sender);
|
||||
}
|
||||
default -> {
|
||||
return handleTravel(sender, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleTravel(
|
||||
CommandSender sender,
|
||||
String[] args
|
||||
) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(
|
||||
plugin.getLanguageManager()
|
||||
.getMessage("general.player-only")
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("rs-cab.use")) {
|
||||
player.sendMessage(
|
||||
plugin.getLanguageManager()
|
||||
.getMessage("general.no-permission")
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Travel behavior will be implemented in Phase 2.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private boolean handleAdd(
|
||||
CommandSender sender,
|
||||
String[] args
|
||||
) {
|
||||
if (!sender.hasPermission("rs-cab.add")) {
|
||||
sender.sendMessage(plugin.getLanguageManager()
|
||||
.getMessage("general.no-permission"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(plugin.getLanguageManager()
|
||||
.getMessage("general.player-only"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String arguments = String.join(" ", args)
|
||||
.substring("add".length()).trim();
|
||||
|
||||
String name;
|
||||
String icon;
|
||||
|
||||
if (arguments.startsWith("'")) {
|
||||
int closingQuote = arguments.indexOf('\'', 1);
|
||||
|
||||
if (closingQuote < 2) {
|
||||
sender.sendMessage(plugin.getLanguageManager()
|
||||
.getMessage("general.invalid-usage"));
|
||||
return true;
|
||||
}
|
||||
|
||||
name = arguments.substring(1, closingQuote);
|
||||
icon = arguments.substring(closingQuote + 1).trim();
|
||||
} else {
|
||||
String[] parts = arguments.split("\\s+");
|
||||
|
||||
if (parts.length != 2) {
|
||||
sender.sendMessage(plugin.getLanguageManager()
|
||||
.getMessage("general.invalid-usage"));
|
||||
return true;
|
||||
}
|
||||
|
||||
name = parts[0];
|
||||
icon = parts[1];
|
||||
}
|
||||
|
||||
if (name.isBlank() || icon.isBlank()
|
||||
|| icon.contains(" ")) {
|
||||
sender.sendMessage(plugin.getLanguageManager()
|
||||
.getMessage("general.invalid-usage"));
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
if (stopManager.exists(name)) {
|
||||
sender.sendMessage(plugin.getLanguageManager()
|
||||
.getMessage("stop.already-exists",
|
||||
Map.of("stop", name)));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!platformValidator.isValid(player)) {
|
||||
sender.sendMessage(plugin.getLanguageManager()
|
||||
.getMessage("platform.invalid"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (stopManager.add(name, icon, player.getLocation())) {
|
||||
sender.sendMessage(plugin.getLanguageManager()
|
||||
.getMessage("stop.added",
|
||||
Map.of("stop", name)));
|
||||
} else {
|
||||
sender.sendMessage(plugin.getLanguageManager()
|
||||
.getMessage("stop.already-exists",
|
||||
Map.of("stop", name)));
|
||||
}
|
||||
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
plugin.getLogger().severe(
|
||||
"Failed to create taxi stop: " + e.getMessage()
|
||||
);
|
||||
sender.sendMessage(plugin.getLanguageManager()
|
||||
.getMessage("stop.creation-error"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private boolean handleUpdate(
|
||||
CommandSender sender,
|
||||
String[] args
|
||||
) {
|
||||
return checkPermission(sender, "rs-cab.edit");
|
||||
}
|
||||
|
||||
private boolean handleEdit(
|
||||
CommandSender sender,
|
||||
String[] args
|
||||
) {
|
||||
return checkPermission(sender, "rs-cab.edit");
|
||||
}
|
||||
|
||||
private boolean handleRemove(
|
||||
CommandSender sender,
|
||||
String[] args
|
||||
) {
|
||||
return checkPermission(sender, "rs-cab.delete");
|
||||
}
|
||||
|
||||
private boolean handleList(CommandSender sender) {
|
||||
return checkPermission(sender, "rs-cab.use");
|
||||
}
|
||||
|
||||
private boolean checkPermission(
|
||||
CommandSender sender,
|
||||
String permission
|
||||
) {
|
||||
if (!sender.hasPermission(permission)) {
|
||||
sender.sendMessage(
|
||||
plugin.getLanguageManager()
|
||||
.getMessage("general.no-permission")
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
|
||||
package com.rsscripting.rstaxi.database;
|
||||
|
||||
import com.rsscripting.rstaxi.RSTaxi;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public final class DatabaseManager {
|
||||
|
||||
private final RSTaxi plugin;
|
||||
private Connection connection;
|
||||
|
||||
public DatabaseManager(RSTaxi plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void connect() throws SQLException {
|
||||
File folder = plugin.getDataFolder();
|
||||
|
||||
if (!folder.exists() && !folder.mkdirs()) {
|
||||
throw new SQLException(
|
||||
"Could not create plugin data folder."
|
||||
);
|
||||
}
|
||||
|
||||
File databaseFile = new File(folder, "taxi.db");
|
||||
String url = "jdbc:sqlite:" + databaseFile.getAbsolutePath();
|
||||
|
||||
connection = DriverManager.getConnection(url);
|
||||
|
||||
plugin.getLogger().info("SQLite database connected.");
|
||||
}
|
||||
|
||||
public void initialize() throws SQLException {
|
||||
if (connection == null || connection.isClosed()) {
|
||||
throw new SQLException("Database is not connected.");
|
||||
}
|
||||
|
||||
String sql = """
|
||||
CREATE TABLE IF NOT EXISTS stops (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL COLLATE NOCASE UNIQUE,
|
||||
icon TEXT NOT NULL,
|
||||
world TEXT NOT NULL,
|
||||
x REAL NOT NULL,
|
||||
y REAL NOT NULL,
|
||||
z REAL NOT NULL,
|
||||
yaw REAL NOT NULL,
|
||||
pitch REAL NOT NULL
|
||||
);
|
||||
""";
|
||||
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute(sql);
|
||||
}
|
||||
|
||||
plugin.getLogger().info("SQLite database initialized.");
|
||||
}
|
||||
|
||||
public Connection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (connection == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
connection.close();
|
||||
plugin.getLogger().info("SQLite database connection closed.");
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().severe(
|
||||
"Failed to close SQLite database: "
|
||||
+ e.getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
|
||||
package com.rsscripting.rstaxi.language;
|
||||
|
||||
import com.rsscripting.rstaxi.RSTaxi;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
public final class LanguageManager {
|
||||
|
||||
private final RSTaxi plugin;
|
||||
private YamlConfiguration language;
|
||||
private YamlConfiguration english;
|
||||
|
||||
public LanguageManager(RSTaxi plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
File languageFolder =
|
||||
new File(plugin.getDataFolder(), "language");
|
||||
|
||||
if (!languageFolder.exists() && !languageFolder.mkdirs()) {
|
||||
plugin.getLogger().severe(
|
||||
"Could not create the language folder."
|
||||
);
|
||||
}
|
||||
|
||||
File englishFile =
|
||||
new File(languageFolder, "en_us.yml");
|
||||
|
||||
if (!englishFile.exists()) {
|
||||
plugin.saveResource("language/en_us.yml", false);
|
||||
}
|
||||
|
||||
english = YamlConfiguration.loadConfiguration(englishFile);
|
||||
|
||||
String selected = plugin.getConfig()
|
||||
.getString("language", "en_us")
|
||||
.trim();
|
||||
|
||||
if (!selected.matches("[a-zA-Z0-9_-]+")) {
|
||||
plugin.getLogger().warning(
|
||||
"Invalid language setting. Using en_us."
|
||||
);
|
||||
selected = "en_us";
|
||||
}
|
||||
|
||||
File selectedFile =
|
||||
new File(languageFolder, selected + ".yml");
|
||||
|
||||
if (!selectedFile.isFile()) {
|
||||
plugin.getLogger().warning(
|
||||
"Language file '" + selected
|
||||
+ ".yml' was not found. Using en_us."
|
||||
);
|
||||
language = english;
|
||||
return;
|
||||
}
|
||||
|
||||
language = YamlConfiguration.loadConfiguration(selectedFile);
|
||||
plugin.getLogger().info(
|
||||
"Loaded language: " + selected
|
||||
);
|
||||
}
|
||||
|
||||
public String getMessage(String path) {
|
||||
return getMessage(path, Map.of());
|
||||
}
|
||||
|
||||
public String getMessage(
|
||||
String path,
|
||||
Map<String, String> placeholders
|
||||
) {
|
||||
String message = language == null
|
||||
? null
|
||||
: language.getString(path);
|
||||
|
||||
if (message == null && english != null) {
|
||||
message = english.getString(path);
|
||||
}
|
||||
|
||||
if (message == null) {
|
||||
plugin.getLogger().warning(
|
||||
"Missing language message: " + path
|
||||
);
|
||||
message = "&cMissing message: " + path;
|
||||
}
|
||||
|
||||
String prefix = language == null
|
||||
? ""
|
||||
: language.getString("prefix", "");
|
||||
|
||||
if (!path.equals("prefix") && !prefix.isEmpty()) {
|
||||
message = prefix + message;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry
|
||||
: placeholders.entrySet()) {
|
||||
message = message.replace(
|
||||
"%" + entry.getKey() + "%",
|
||||
entry.getValue()
|
||||
);
|
||||
}
|
||||
|
||||
return ChatColor.translateAlternateColorCodes('&', message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
|
||||
package com.rsscripting.rstaxi.platform;
|
||||
|
||||
import com.rsscripting.rstaxi.RSTaxi;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public final class PlatformValidator {
|
||||
|
||||
private final RSTaxi plugin;
|
||||
|
||||
private static final Map<String, int[]> OFFSETS = Map.of(
|
||||
"north", new int[]{0, -1},
|
||||
"northeast", new int[]{1, -1},
|
||||
"east", new int[]{1, 0},
|
||||
"southeast", new int[]{1, 1},
|
||||
"south", new int[]{0, 1},
|
||||
"southwest", new int[]{-1, 1},
|
||||
"west", new int[]{-1, 0},
|
||||
"northwest", new int[]{-1, -1}
|
||||
);
|
||||
|
||||
public PlatformValidator(RSTaxi plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public boolean isValid(Player player) {
|
||||
if (!plugin.getConfig().getBoolean("platform.enabled", true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Block center = player.getLocation()
|
||||
.subtract(0, 1, 0)
|
||||
.getBlock();
|
||||
|
||||
Material target = getConfiguredMaterial(
|
||||
"platform.target-block"
|
||||
);
|
||||
|
||||
if (center.getType() != target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, int[]> entry : OFFSETS.entrySet()) {
|
||||
String direction = entry.getKey();
|
||||
int[] offset = entry.getValue();
|
||||
|
||||
Material required = getConfiguredMaterial(
|
||||
"platform.layout." + direction
|
||||
);
|
||||
|
||||
Block surrounding = center.getRelative(
|
||||
offset[0], 0, offset[1]
|
||||
);
|
||||
|
||||
if (surrounding.getType() != required) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Material getConfiguredMaterial(String path) {
|
||||
String name = plugin.getConfig().getString(path, "");
|
||||
Material material = Material.matchMaterial(name);
|
||||
|
||||
if (material == null || !material.isBlock()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid platform material at " + path + ": " + name
|
||||
);
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
|
||||
package com.rsscripting.rstaxi.stops;
|
||||
|
||||
import com.rsscripting.rstaxi.RSTaxi;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public final class StopManager {
|
||||
|
||||
private final RSTaxi plugin;
|
||||
|
||||
public StopManager(RSTaxi plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public boolean exists(String name) throws SQLException {
|
||||
String sql = "SELECT 1 FROM stops WHERE name = ?";
|
||||
|
||||
try (PreparedStatement statement = connection()
|
||||
.prepareStatement(sql)) {
|
||||
|
||||
statement.setString(1, name);
|
||||
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
return results.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean add(
|
||||
String name,
|
||||
String icon,
|
||||
Location location
|
||||
) throws SQLException {
|
||||
|
||||
String sql = """
|
||||
INSERT OR IGNORE INTO stops
|
||||
(name, icon, world, x, y, z, yaw, pitch)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""";
|
||||
|
||||
try (PreparedStatement statement = connection()
|
||||
.prepareStatement(sql)) {
|
||||
|
||||
statement.setString(1, name);
|
||||
statement.setString(2, icon);
|
||||
statement.setString(
|
||||
3, location.getWorld().getName()
|
||||
);
|
||||
statement.setDouble(4, location.getX());
|
||||
statement.setDouble(5, location.getY());
|
||||
statement.setDouble(6, location.getZ());
|
||||
statement.setFloat(7, location.getYaw());
|
||||
statement.setFloat(8, location.getPitch());
|
||||
|
||||
return statement.executeUpdate() == 1;
|
||||
}
|
||||
}
|
||||
|
||||
private Connection connection() {
|
||||
return plugin.getDatabaseManager().getConnection();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user