Add fixed-destination gates and /sg networks command
Sign line 4 now accepts fixed:GateName to lock a gate to one destination without cycling, and /sg networks lists every known network.
This commit is contained in:
@@ -26,7 +26,8 @@ Build everything with `./gradlew build`. Jars land in each module's `build/libs/
|
||||
- Line 1: `[Stargate]`
|
||||
- Line 2: network name (blank = default network)
|
||||
- Line 3: gate name (blank = auto-generated)
|
||||
- Line 4: `hidden` to keep it out of the cycle list, otherwise blank
|
||||
- Line 4: `hidden` to keep it out of the cycle list, `fixed:GateName` to lock this
|
||||
gate to always dial `GateName` (no right-click cycling), or blank
|
||||
|
||||
The plugin flood-fills the frame from the block behind the sign, confirms it's a
|
||||
fully enclosed ring, and registers the gate. If nothing happens, the ring isn't
|
||||
|
||||
+10
-3
@@ -13,8 +13,8 @@ import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class StargateCommand implements CommandExecutor, TabCompleter {
|
||||
@@ -30,11 +30,18 @@ public class StargateCommand implements CommandExecutor, TabCompleter {
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage(Component.text("Usage: /sg <list|destroy|reload>", NamedTextColor.YELLOW));
|
||||
sender.sendMessage(Component.text("Usage: /sg <list|networks|destroy|reload>", NamedTextColor.YELLOW));
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "networks" -> {
|
||||
TreeSet<String> networks = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
|
||||
for (RuntimeGate rg : gateManager.all()) {
|
||||
networks.add(rg.getGate().getNetwork());
|
||||
}
|
||||
sender.sendMessage(Component.text("Networks (" + networks.size() + "): " + String.join(", ", networks), NamedTextColor.AQUA));
|
||||
}
|
||||
case "reload" -> {
|
||||
if (!sender.hasPermission("stargate.admin")) {
|
||||
sender.sendMessage(Component.text("No permission.", NamedTextColor.RED));
|
||||
@@ -82,7 +89,7 @@ public class StargateCommand implements CommandExecutor, TabCompleter {
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
if (args.length == 1) {
|
||||
return List.of("list", "destroy", "reload").stream()
|
||||
return List.of("list", "networks", "destroy", "reload").stream()
|
||||
.filter(s -> s.startsWith(args[0].toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -109,6 +109,10 @@ public class GateManager {
|
||||
}
|
||||
|
||||
public RuntimeGate createGate(Block signBlock, String network, String name, UUID owner, EnumSet<Gate.Flag> flags) {
|
||||
return createGate(signBlock, network, name, owner, flags, null);
|
||||
}
|
||||
|
||||
public RuntimeGate createGate(Block signBlock, String network, String name, UUID owner, EnumSet<Gate.Flag> flags, String fixedDestination) {
|
||||
Block attached = attachedFrameBlock(signBlock);
|
||||
if (attached == null) return null;
|
||||
GateStructure structure = scanner.scan(attached);
|
||||
@@ -118,7 +122,7 @@ public class GateManager {
|
||||
Gate gate = new Gate(UUID.randomUUID(), name, network, plugin.getServerId(),
|
||||
exit.getWorld().getName(), exit.getBlockX(), exit.getBlockY(), exit.getBlockZ(), exit.getYaw(),
|
||||
signBlock.getX(), signBlock.getY(), signBlock.getZ(), signBlock.getWorld().getName(),
|
||||
signBlockFacing(signBlock), owner, flags, null);
|
||||
signBlockFacing(signBlock), owner, flags, fixedDestination);
|
||||
|
||||
RuntimeGate rg = new RuntimeGate(gate, structure);
|
||||
gatesById.put(gate.getId(), rg);
|
||||
|
||||
+9
-2
@@ -46,12 +46,19 @@ public class SignCreateListener implements Listener {
|
||||
if (name == null || name.isBlank()) name = "Gate-" + Integer.toHexString((int) (Math.random() * 0xFFFF));
|
||||
|
||||
EnumSet<Gate.Flag> flags = EnumSet.of(Gate.Flag.PUBLIC);
|
||||
String fixedDestination = null;
|
||||
String flagLine = stripped(event.line(3));
|
||||
if (flagLine != null) {
|
||||
if (flagLine.equalsIgnoreCase("hidden")) { flags.clear(); flags.add(Gate.Flag.HIDDEN); }
|
||||
if (flagLine.equalsIgnoreCase("hidden")) {
|
||||
flags.clear();
|
||||
flags.add(Gate.Flag.HIDDEN);
|
||||
} else if (flagLine.toLowerCase().startsWith("fixed:")) {
|
||||
fixedDestination = flagLine.substring("fixed:".length()).trim();
|
||||
flags.add(Gate.Flag.FIXED);
|
||||
}
|
||||
}
|
||||
|
||||
RuntimeGate rg = gateManager.createGate(event.getBlock(), network, name, player.getUniqueId(), flags);
|
||||
RuntimeGate rg = gateManager.createGate(event.getBlock(), network, name, player.getUniqueId(), flags, fixedDestination);
|
||||
if (rg == null) {
|
||||
player.sendMessage(Component.text("No valid gate structure found. Build the frame first, then place the sign.", NamedTextColor.RED));
|
||||
resetLine(event);
|
||||
|
||||
@@ -35,6 +35,10 @@ public final class SignRenderer {
|
||||
}
|
||||
|
||||
private static Component destinationLine(RuntimeGate rg, GateManager gateManager) {
|
||||
if (rg.getGate().isFixed()) {
|
||||
String dest = rg.getGate().getFixedDestination();
|
||||
return Component.text("=> " + (dest == null || dest.isBlank() ? "?" : dest), NamedTextColor.DARK_PURPLE);
|
||||
}
|
||||
List<RuntimeGate> destinations = gateManager.destinationsFor(rg);
|
||||
if (destinations.isEmpty()) {
|
||||
return Component.text("no destinations", NamedTextColor.DARK_GRAY);
|
||||
|
||||
@@ -10,7 +10,7 @@ commands:
|
||||
stargate:
|
||||
description: Manage Stargate networks and gates.
|
||||
aliases: [sg]
|
||||
usage: /sg <create|destroy|network|reload|list> ...
|
||||
usage: /sg <list|networks|destroy|reload> ...
|
||||
|
||||
permissions:
|
||||
stargate.use:
|
||||
|
||||
Reference in New Issue
Block a user