Skip to content

Commit 4b82d46

Browse files
authored
Merge pull request #3 from indra87g/feature/server-selector
feat: Add /servers command for server selection
2 parents a3d9f98 + b616354 commit 4b82d46

6 files changed

Lines changed: 238 additions & 9 deletions

File tree

pom.xml

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,14 @@
3535
<id>nukkitx</id>
3636
<url>https://repo.opencollab.dev/main/</url>
3737
</repository>
38-
<repository>
39-
<id>jitpack.io</id>
40-
<url>https://jitpack.io</url>
41-
</repository>
38+
</repositories>
4239
<dependencies>
4340
<dependency>
4441
<groupId>cn.nukkit</groupId>
4542
<artifactId>nukkit</artifactId>
4643
<version>1.0-SNAPSHOT</version>
4744
<scope>provided</scope>
4845
</dependency>
49-
<dependency>
50-
<groupId>com.github.MEFRREEX</groupId>
51-
<artifactId>FormConstructor</artifactId>
52-
<version>2.0.0</version>
53-
</dependency>
5446
<dependency>
5547
<groupId>me.onebone</groupId>
5648
<artifactId>EconomyAPI</artifactId>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,55 @@
11
package com.indra87g;
22

3+
import cn.nukkit.Player;
34
import cn.nukkit.plugin.PluginBase;
5+
import cn.nukkit.scheduler.PluginTask;
6+
import cn.nukkit.utils.Config;
7+
import com.indra87g.commands.ServersCommand;
48
import com.indra87g.commands.SetBlockCommand;
59

10+
import java.io.File;
11+
import java.util.HashMap;
12+
import java.util.List;
13+
import java.util.Map;
14+
import java.util.UUID;
15+
616
public class Main extends PluginBase {
717

18+
private List<Map> servers;
19+
private final Map<UUID, PluginTask<?>> countdowns = new HashMap<>();
20+
private final Map<UUID, Player> teleportingPlayers = new HashMap<>();
21+
private final Map<UUID, cn.nukkit.level.Location> playerLocations = new HashMap<>();
22+
823
@Override
924
public void onEnable() {
25+
this.saveDefaultConfig();
26+
this.saveResource("servers.yml");
27+
28+
Config serversConfig = new Config(new File(this.getDataFolder(), "servers.yml"), Config.YAML);
29+
this.servers = serversConfig.getMapList("servers");
30+
1031
getLogger().info("WaffleCoreNK has been enabled.");
32+
33+
ServersCommand serversCommand = new ServersCommand(this);
34+
this.getServer().getPluginManager().registerEvents(new com.indra87g.listeners.PlayerMoveListener(this), this);
35+
this.getServer().getPluginManager().registerEvents(serversCommand, this);
1136
this.getServer().getCommandMap().register("setblock", new SetBlockCommand());
37+
this.getServer().getCommandMap().register("servers", serversCommand);
38+
}
39+
40+
public List<Map> getServers() {
41+
return servers;
42+
}
43+
44+
public Map<UUID, PluginTask<?>> getCountdowns() {
45+
return countdowns;
46+
}
47+
48+
public Map<UUID, Player> getTeleportingPlayers() {
49+
return teleportingPlayers;
50+
}
51+
52+
public Map<UUID, cn.nukkit.level.Location> getPlayerLocations() {
53+
return playerLocations;
1254
}
1355
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package com.indra87g.commands;
2+
3+
import cn.nukkit.Player;
4+
import cn.nukkit.command.Command;
5+
import cn.nukkit.command.CommandSender;
6+
import cn.nukkit.event.EventHandler;
7+
import cn.nukkit.event.Listener;
8+
import cn.nukkit.event.player.PlayerFormRespondedEvent;
9+
import cn.nukkit.form.element.ElementButton;
10+
import cn.nukkit.network.protocol.TransferPacket;
11+
import cn.nukkit.scheduler.PluginTask;
12+
import cn.nukkit.form.window.FormWindowSimple;
13+
import com.indra87g.Main;
14+
15+
import java.util.HashMap;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.UUID;
19+
20+
public class ServersCommand extends Command implements Listener {
21+
22+
private final Main plugin;
23+
private final Map<UUID, Integer> formIDs = new HashMap<>();
24+
25+
public ServersCommand(Main plugin) {
26+
super("servers", "Display a list of servers to connect to.", "/servers");
27+
this.plugin = plugin;
28+
}
29+
30+
@Override
31+
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
32+
if (!(sender instanceof Player)) {
33+
sender.sendMessage("This command can only be used by a player.");
34+
return false;
35+
}
36+
37+
Player player = (Player) sender;
38+
39+
List<Map> servers = plugin.getServers();
40+
if (servers == null || servers.isEmpty()) {
41+
player.sendMessage("There are no servers available at the moment. Please try again later.");
42+
return true;
43+
}
44+
45+
FormWindowSimple form = new FormWindowSimple("Server Selector", "Choose a server to connect to.");
46+
for (Map serverData : servers) {
47+
form.addButton(new ElementButton(String.valueOf(serverData.get("name"))));
48+
}
49+
50+
int formId = player.showFormWindow(form);
51+
formIDs.put(player.getUniqueId(), formId);
52+
53+
return true;
54+
}
55+
56+
@EventHandler
57+
public void onFormResponse(PlayerFormRespondedEvent event) {
58+
Player player = event.getPlayer();
59+
UUID playerUUID = player.getUniqueId();
60+
61+
if (formIDs.containsKey(playerUUID) && formIDs.get(playerUUID) == event.getFormID()) {
62+
formIDs.remove(playerUUID); // Prevent re-handling
63+
64+
if (event.getResponse() == null) {
65+
return; // Form was closed
66+
}
67+
68+
if (event.getWindow() instanceof FormWindowSimple) {
69+
FormWindowSimple form = (FormWindowSimple) event.getWindow();
70+
int buttonIndex = form.getResponse().getClickedButtonId();
71+
72+
List<Map> servers = plugin.getServers();
73+
if (servers == null || buttonIndex >= servers.size()) {
74+
return; // Should not happen
75+
}
76+
77+
Map serverData = servers.get(buttonIndex);
78+
String address = String.valueOf(serverData.get("address"));
79+
int port = ((Number) serverData.get("port")).intValue();
80+
81+
if (plugin.getTeleportingPlayers().containsKey(playerUUID)) {
82+
player.sendMessage("You are already being transferred to a server.");
83+
return;
84+
}
85+
86+
plugin.getPlayerLocations().put(playerUUID, player.getLocation());
87+
plugin.getTeleportingPlayers().put(playerUUID, player);
88+
CountdownTask task = new CountdownTask(plugin, player, address, port);
89+
plugin.getServer().getScheduler().scheduleRepeatingTask(plugin, task, 20);
90+
plugin.getCountdowns().put(playerUUID, task);
91+
}
92+
}
93+
}
94+
95+
private static class CountdownTask extends PluginTask<Main> {
96+
97+
private final Player player;
98+
private final String address;
99+
private final int port;
100+
private int countdown = 3;
101+
102+
public CountdownTask(Main owner, Player player, String address, int port) {
103+
super(owner);
104+
this.player = player;
105+
this.address = address;
106+
this.port = port;
107+
}
108+
109+
@Override
110+
public void onRun(int currentTick) {
111+
if (!player.isOnline() || !this.getOwner().getTeleportingPlayers().containsKey(player.getUniqueId())) {
112+
this.cancel();
113+
this.getOwner().getTeleportingPlayers().remove(player.getUniqueId());
114+
this.getOwner().getCountdowns().remove(player.getUniqueId());
115+
this.getOwner().getPlayerLocations().remove(player.getUniqueId());
116+
return;
117+
}
118+
119+
if (countdown > 0) {
120+
player.sendTitle("§eTeleporting in " + countdown + "...", "", 0, 25, 5);
121+
countdown--;
122+
} else {
123+
player.sendTitle("§aTransferring...", "", 0, 20, 0);
124+
TransferPacket pk = new TransferPacket();
125+
pk.address = address;
126+
pk.port = port;
127+
player.dataPacket(pk);
128+
this.getOwner().getTeleportingPlayers().remove(player.getUniqueId());
129+
this.getOwner().getCountdowns().remove(player.getUniqueId());
130+
this.getOwner().getPlayerLocations().remove(player.getUniqueId());
131+
this.cancel();
132+
}
133+
}
134+
}
135+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.indra87g.listeners;
2+
3+
import cn.nukkit.Player;
4+
import cn.nukkit.event.EventHandler;
5+
import cn.nukkit.event.Listener;
6+
import cn.nukkit.event.player.PlayerMoveEvent;
7+
import cn.nukkit.level.Location;
8+
import cn.nukkit.scheduler.PluginTask;
9+
import com.indra87g.Main;
10+
11+
import java.util.UUID;
12+
13+
public class PlayerMoveListener implements Listener {
14+
15+
private final Main plugin;
16+
17+
public PlayerMoveListener(Main plugin) {
18+
this.plugin = plugin;
19+
}
20+
21+
@EventHandler
22+
public void onPlayerMove(PlayerMoveEvent event) {
23+
Player player = event.getPlayer();
24+
UUID playerUUID = player.getUniqueId();
25+
26+
if (plugin.getTeleportingPlayers().containsKey(playerUUID)) {
27+
Location from = plugin.getPlayerLocations().get(playerUUID);
28+
Location to = event.getTo();
29+
30+
if (from.getFloorX() != to.getFloorX() || from.getFloorZ() != to.getFloorZ()) {
31+
plugin.getTeleportingPlayers().remove(playerUUID);
32+
plugin.getPlayerLocations().remove(playerUUID);
33+
34+
PluginTask<?> task = plugin.getCountdowns().remove(playerUUID);
35+
if (task != null) {
36+
task.cancel();
37+
}
38+
39+
player.sendTitle("§cTeleportation cancelled.", "You moved.", 0, 20, 5);
40+
}
41+
}
42+
}
43+
}

src/main/resources/plugin.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@ commands:
99
description: "Sets a block at a specific location"
1010
usage: "/setblock <x> <y> <z> <block_id>"
1111
permission: waffle.setblock
12+
servers:
13+
description: "Shows a list of servers"
14+
usage: "/servers"
15+
permission: waffle.servers
1216
permissions:
1317
waffle.setblock:
1418
description: "Allows the user to use the /setblock command"
1519
default: op
20+
waffle.servers:
21+
description: "Allows the user to use the /servers command"
22+
default: true

src/main/resources/servers.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
servers:
2+
- name: "Lobby"
3+
address: "lobby.example.com"
4+
port: 19132
5+
- name: "Survival"
6+
address: "survival.example.com"
7+
port: 19133
8+
- name: "Creative"
9+
address: "creative.example.com"
10+
port: 19134

0 commit comments

Comments
 (0)