0.1.0 - Added

- Clickable /cab list
- Clickable /cab search xxxx
This commit is contained in:
BigPappa committed 2026-10-12 19:27:02 -05:00
1 parent a7fba84cd3
commit 2e8b4b19c8
15 files changed
+217 -48

No files matched your search

@@ -5,6 +5,9 @@ import com.rsscripting.rstaxi.RSTaxi;
import com.rsscripting.rstaxi.platform.PlatformValidator; import com.rsscripting.rstaxi.platform.PlatformValidator;
import com.rsscripting.rstaxi.stops.StopManager; import com.rsscripting.rstaxi.stops.StopManager;
import com.rsscripting.rstaxi.integrations.BlueMapManager; import com.rsscripting.rstaxi.integrations.BlueMapManager;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Map; import java.util.Map;
import org.bukkit.command.Command; import org.bukkit.command.Command;
@@ -55,7 +58,7 @@ public final class CabCommand implements CommandExecutor {
return handleRemove(sender, args); return handleRemove(sender, args);
} }
case "list" -> { case "list" -> {
return handleList(sender); return openList(sender);
} }
case "search" -> { case "search" -> {
return searchCommand.execute(sender, args); return searchCommand.execute(sender, args);
@@ -66,7 +69,6 @@ public final class CabCommand implements CommandExecutor {
} }
} }
private boolean handleTravel( private boolean handleTravel(
CommandSender sender, CommandSender sender,
String[] args String[] args
@@ -88,7 +90,7 @@ public final class CabCommand implements CommandExecutor {
} }
if (args.length == 0) { if (args.length == 0) {
sender.sendMessage( player.sendMessage(
plugin.getLanguageManager() plugin.getLanguageManager()
.getMessage("general.invalid-usage") .getMessage("general.invalid-usage")
); );
@@ -96,10 +98,22 @@ public final class CabCommand implements CommandExecutor {
} }
String name = String.join(" ", args).trim(); String name = String.join(" ", args).trim();
boolean allowCrossWorld = plugin.getConfig()
.getBoolean("allow-cross-world", true);
try { try {
StopManager.StopLocation stop = StopManager.StopLocation stop;
stopManager.getStopLocation(name);
if (allowCrossWorld && name.contains(":")) {
int separator = name.indexOf(':');
String worldName = name.substring(0, separator).trim();
String stopName = name.substring(separator + 1).trim();
stop = stopManager.getStopLocation(stopName, worldName);
name = stopName;
} else {
stop = stopManager.getStopLocation(name);
}
if (stop == null) { if (stop == null) {
player.sendMessage( player.sendMessage(
@@ -111,6 +125,15 @@ public final class CabCommand implements CommandExecutor {
return true; return true;
} }
if (!allowCrossWorld
&& !player.getWorld().getName().equals(stop.world())) {
player.sendMessage(
plugin.getLanguageManager()
.getMessage("general.stop-in-another-world")
);
return true;
}
World world = Bukkit.getWorld(stop.world()); World world = Bukkit.getWorld(stop.world());
if (world == null) { if (world == null) {
@@ -141,7 +164,12 @@ public final class CabCommand implements CommandExecutor {
player.sendMessage( player.sendMessage(
plugin.getLanguageManager().getMessage( plugin.getLanguageManager().getMessage(
"teleport.success", "teleport.success",
Map.of("stop", stop.name()) Map.of(
"stop",
allowCrossWorld
? stop.world() + ":" + stop.name()
: stop.name()
)
) )
); );
@@ -341,9 +369,7 @@ public final class CabCommand implements CommandExecutor {
return true; return true;
} }
public boolean openList(CommandSender sender) {
private boolean handleList(CommandSender sender) {
if (!sender.hasPermission("rs-cab.use")) { if (!sender.hasPermission("rs-cab.use")) {
sender.sendMessage( sender.sendMessage(
plugin.getLanguageManager() plugin.getLanguageManager()
@@ -352,35 +378,55 @@ public final class CabCommand implements CommandExecutor {
return true; return true;
} }
if (!(sender instanceof Player player)) {
sender.sendMessage(
plugin.getLanguageManager()
.getMessage("general.player-only")
);
return true;
}
try { try {
var stops = stopManager.getAllStops(); var stops = stopManager.getAllStops();
boolean allowCrossWorld = plugin.getConfig()
.getBoolean("allow-cross-world", true);
if (!allowCrossWorld) {
String currentWorld = player.getWorld().getName();
stops = stops.stream()
.filter(stop -> stop.world().equals(currentWorld))
.toList();
}
if (stops.isEmpty()) { if (stops.isEmpty()) {
sender.sendMessage( player.sendMessage(
plugin.getLanguageManager() plugin.getLanguageManager()
.getMessage("general.no-stops") .getMessage("general.no-stops")
); );
return true; return true;
} }
sender.sendMessage( player.sendMessage(
plugin.getLanguageManager() plugin.getLanguageManager()
.getMessage("list.header") .getMessage("list.header")
); );
for (StopManager.StopEntry stop : stops) { for (StopManager.StopEntry stop : stops) {
sender.sendMessage( String displayName = allowCrossWorld
plugin.getLanguageManager() ? stop.world() + ":" + stop.name()
.getMessage( : stop.name();
"list.entry",
Map.of(
"icon", stop.icon(),
"stop", stop.name()
)
)
);
}
String command = "/cab " + stop.name();
Component clickableStop = Component.text(displayName)
.color(NamedTextColor.WHITE)
.clickEvent(ClickEvent.runCommand(command))
.hoverEvent(net.kyori.adventure.text.event.HoverEvent
.showText(Component.text("Click to teleport")));
player.sendMessage(clickableStop);
}
} catch (SQLException e) { } catch (SQLException e) {
plugin.getLogger().log( plugin.getLogger().log(
@@ -389,17 +435,15 @@ public final class CabCommand implements CommandExecutor {
e e
); );
sender.sendMessage( player.sendMessage(
plugin.getLanguageManager() plugin.getLanguageManager()
.getMessage("list.error") .getMessage("list.error")
); );
} }
return true; return true;
} }
private boolean checkPermission( private boolean checkPermission(
CommandSender sender, CommandSender sender,
String permission String permission
@@ -4,9 +4,12 @@ package com.rsscripting.rstaxi.commands;
import com.rsscripting.rstaxi.RSTaxi; import com.rsscripting.rstaxi.RSTaxi;
import com.rsscripting.rstaxi.stops.StopManager; import com.rsscripting.rstaxi.stops.StopManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Map;
import java.util.Locale; import java.util.Locale;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player;
public final class CabSearchCommand { public final class CabSearchCommand {
@@ -49,6 +52,17 @@ public final class CabSearchCommand {
? stopManager.searchByIcon(value) ? stopManager.searchByIcon(value)
: stopManager.searchByName(value); : stopManager.searchByName(value);
boolean allowCrossWorld = plugin.getConfig()
.getBoolean("allow-cross-world", true);
if (!allowCrossWorld && sender instanceof Player player) {
String currentWorld = player.getWorld().getName();
stops = stops.stream()
.filter(stop -> stop.world().equals(currentWorld))
.toList();
}
if (stops.isEmpty()) { if (stops.isEmpty()) {
sender.sendMessage( sender.sendMessage(
plugin.getLanguageManager() plugin.getLanguageManager()
@@ -63,15 +77,23 @@ public final class CabSearchCommand {
); );
for (StopManager.StopEntry stop : stops) { for (StopManager.StopEntry stop : stops) {
sender.sendMessage( String displayName = allowCrossWorld
plugin.getLanguageManager().getMessage( ? stop.world() + ":" + stop.name()
"list.entry", : stop.name();
Map.of(
"icon", stop.icon(), if (sender instanceof Player) {
"stop", stop.name() Component clickableStop = Component.text(displayName)
) .color(NamedTextColor.WHITE)
) .clickEvent(ClickEvent.runCommand("/cab " + stop.name()))
.hoverEvent(
net.kyori.adventure.text.event.HoverEvent
.showText(Component.text("Click to teleport"))
); );
sender.sendMessage(clickableStop);
} else {
sender.sendMessage(displayName);
}
} }
} catch (SQLException e) { } catch (SQLException e) {
plugin.getLogger().log( plugin.getLogger().log(
@@ -40,11 +40,26 @@ public final class CabTabCompleter implements TabCompleter {
} }
String input = args[0].toLowerCase(Locale.ROOT); String input = args[0].toLowerCase(Locale.ROOT);
boolean allowCrossWorld = plugin.getConfig()
.getBoolean("allow-cross-world", true);
String currentWorld = sender instanceof org.bukkit.entity.Player player
? player.getWorld().getName()
: null;
for (StopManager.StopEntry stop : getSortedStops()) { for (StopManager.StopEntry stop : getSortedStops()) {
if (stop.name().toLowerCase(Locale.ROOT) if (!allowCrossWorld
.startsWith(input)) { && currentWorld != null
suggestions.add(stop.name()); && !stop.world().equals(currentWorld)) {
continue;
}
String suggestion = allowCrossWorld
? stop.world() + ":" + stop.name()
: stop.name();
if (suggestion.toLowerCase(Locale.ROOT).startsWith(input)) {
suggestions.add(suggestion);
} }
} }
@@ -7,6 +7,10 @@ import org.bukkit.block.Block;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockBreakEvent;
import com.rsscripting.rstaxi.commands.CabCommand;
import org.bukkit.entity.Player;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import java.util.Map; import java.util.Map;
@@ -29,6 +33,38 @@ public final class PlatformProtectionListener implements Listener {
this.plugin = plugin; this.plugin = plugin;
} }
@EventHandler
public void onPlatformInteract(PlayerInteractEvent event) {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) {
return;
}
Player player = event.getPlayer();
if (!player.isSneaking()) {
return;
}
if (!plugin.getConfig().getBoolean("platform.enabled", true)
|| !plugin.getConfig().getBoolean(
"platform.sneak-rightclick-platform", false)) {
return;
}
Block clicked = event.getClickedBlock();
if (clicked == null
|| clicked.getType() != getMaterial("platform.target-block")
|| !hasRequiredSurroundings(clicked)) {
return;
}
event.setCancelled(true);
CabCommand cabCommand = new CabCommand(plugin);
cabCommand.openList(player);
}
@EventHandler @EventHandler
public void onBlockBreak(BlockBreakEvent event) { public void onBlockBreak(BlockBreakEvent event) {
@@ -19,8 +19,11 @@ public final class StopManager {
this.plugin = plugin; this.plugin = plugin;
} }
public record StopEntry(String name, String icon) { public record StopEntry(
} String name,
String icon,
String world
) {}
public record StopLocation( public record StopLocation(
String name, String name,
@@ -34,6 +37,40 @@ public final class StopManager {
) { ) {
} }
public StopLocation getStopLocation(String name, String world)
throws SQLException {
String sql = """
SELECT name, icon, world, x, y, z, yaw, pitch
FROM stops
WHERE name = ? AND world = ?
""";
try (PreparedStatement statement = connection()
.prepareStatement(sql)) {
statement.setString(1, name);
statement.setString(2, world);
try (ResultSet results = statement.executeQuery()) {
if (!results.next()) {
return null;
}
return new StopLocation(
results.getString("name"),
results.getString("icon"),
results.getString("world"),
results.getDouble("x"),
results.getDouble("y"),
results.getDouble("z"),
results.getFloat("yaw"),
results.getFloat("pitch")
);
}
}
}
public boolean exists(String name) throws SQLException { public boolean exists(String name) throws SQLException {
String sql = "SELECT 1 FROM stops WHERE name = ?"; String sql = "SELECT 1 FROM stops WHERE name = ?";
@@ -126,7 +163,7 @@ public final class StopManager {
public List<StopEntry> getAllStops() throws SQLException { public List<StopEntry> getAllStops() throws SQLException {
String sql = """ String sql = """
SELECT name, icon SELECT name, icon, world
FROM stops FROM stops
ORDER BY name COLLATE NOCASE ORDER BY name COLLATE NOCASE
"""; """;
@@ -140,7 +177,8 @@ public final class StopManager {
while (results.next()) { while (results.next()) {
stops.add(new StopEntry( stops.add(new StopEntry(
results.getString("name"), results.getString("name"),
results.getString("icon") results.getString("icon"),
results.getString("world")
)); ));
} }
} }
@@ -153,9 +191,9 @@ public final class StopManager {
throws SQLException { throws SQLException {
String sql = """ String sql = """
SELECT name, icon SELECT name, icon, world
FROM stops FROM stops
WHERE name LIKE ? ESCAPE '\\' WHERE LOWER(name) LIKE LOWER(?)
ORDER BY name COLLATE NOCASE ORDER BY name COLLATE NOCASE
"""; """;
@@ -175,7 +213,8 @@ public final class StopManager {
while (results.next()) { while (results.next()) {
stops.add(new StopEntry( stops.add(new StopEntry(
results.getString("name"), results.getString("name"),
results.getString("icon") results.getString("icon"),
results.getString("world")
)); ));
} }
} }
@@ -188,9 +227,9 @@ public final class StopManager {
throws SQLException { throws SQLException {
String sql = """ String sql = """
SELECT name, icon SELECT name, icon, world
FROM stops FROM stops
WHERE icon = ? WHERE LOWER(icon) = LOWER(?)
ORDER BY name COLLATE NOCASE ORDER BY name COLLATE NOCASE
"""; """;
@@ -205,7 +244,8 @@ public final class StopManager {
while (results.next()) { while (results.next()) {
stops.add(new StopEntry( stops.add(new StopEntry(
results.getString("name"), results.getString("name"),
results.getString("icon") results.getString("icon"),
results.getString("world")
)); ));
} }
} }
+11
View File
@@ -7,6 +7,11 @@
# Example: en_us, de_de, fr_fr # Example: en_us, de_de, fr_fr
language: "en_us" language: "en_us"
# Allow players to travel between different worlds.
# true: Players can travel to stops in any world.
# false: Players can only travel to stops in their current world.
allow-cross-world: true
# Platform Settings. # Platform Settings.
platform: platform:
# Determines wether platforms are required before adding a destination # Determines wether platforms are required before adding a destination
@@ -22,6 +27,12 @@ platform:
# false: platforms can be broken. # false: platforms can be broken.
protect-platforms: true protect-platforms: true
# Allow players to sneak + right-click the center block
# of a valid 3x3 taxi platform to open a clickable list of
# taxi stops.
# Requires platform.enabled to be true.
sneak-rightclick-platform: false
#Layout requirement for add a destination if enabled is set to true. #Layout requirement for add a destination if enabled is set to true.
layout: layout:
north: "OAK_PLANKS" north: "OAK_PLANKS"
+2 -1
View File
@@ -8,6 +8,7 @@ general:
invalid-usage: "&cInvalid command usage." invalid-usage: "&cInvalid command usage."
unknown-stop: "&cThe stop &e%stop% &cdoes not exist." unknown-stop: "&cThe stop &e%stop% &cdoes not exist."
no-stops: "&eNo taxi stops have been created yet." no-stops: "&eNo taxi stops have been created yet."
stop-in-another-world: "&cStop is in another world, you need to enter that world first."
database: database:
connection-success: "&aDatabase connected successfully." connection-success: "&aDatabase connected successfully."
@@ -32,7 +33,7 @@ confirmation:
list: list:
header: "&6Available Taxi Destinations:" header: "&6Available Taxi Destinations:"
entry: "&e%icon% &f%stop%" entry: "&f%stop%"
error: "&cUnable to retrieve taxi destinations. Check the server logs." error: "&cUnable to retrieve taxi destinations. Check the server logs."
platform: platform:
Binary file not shown.