ProjectAres/Commons/bukkit/src/main/java/tc/oc/commons/bukkit/commands/ServerCommands.java

171 lines
6.4 KiB
Java

package tc.oc.commons.bukkit.commands;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import tc.oc.api.docs.Server;
import tc.oc.api.docs.virtual.ServerDoc;
import tc.oc.api.servers.ServerStore;
import tc.oc.commons.bukkit.chat.Audiences;
import tc.oc.commons.bukkit.chat.Paginator;
import tc.oc.commons.bukkit.chat.WarningComponent;
import tc.oc.commons.bukkit.format.ServerFormatter;
import tc.oc.commons.bukkit.teleport.Teleporter;
import tc.oc.commons.core.chat.Audience;
import tc.oc.commons.core.chat.Component;
import tc.oc.commons.core.commands.Commands;
import tc.oc.commons.core.commands.TranslatableCommandException;
import tc.oc.commons.core.formatting.StringUtils;
public class ServerCommands implements Commands {
private final Server localServer;
private final ServerStore serverStore;
private final ServerFormatter formatter = ServerFormatter.light;
private final Teleporter teleporter;
private final Audiences audiences;
private static final Comparator<Server> FULLNESS = Comparator.comparing(Server::num_online).reversed();
@Inject ServerCommands(Server localServer, ServerStore serverStore, Teleporter teleporter, Audiences audiences) {
this.localServer = localServer;
this.serverStore = serverStore;
this.teleporter = teleporter;
this.audiences = audiences;
}
private BaseComponent format(Server server) {
final Component c = new Component(formatter.nameWithDatacenter(server))
.extra(" ")
.extra(formatter.playerCounts(server, true));
if(server.role() == ServerDoc.Role.PGM && server.current_match() != null) {
c.extra(" ")
.extra(formatter.matchTime(server.current_match()))
.extra(" ")
.extra(new Component(server.current_match().map().name(), ChatColor.AQUA));
}
return c;
}
@Command(
aliases = { "servers", "srvs" },
desc = "Show a listing of all servers on the network",
usage = "[page]",
min = 0,
max = 1
)
public void servers(final CommandContext args, final CommandSender sender) throws CommandException {
final List<Server> servers = new ArrayList<>(serverStore.subset(teleporter::isVisible));
Collections.sort(servers, FULLNESS);
new Paginator<Server>() {
@Override
protected BaseComponent title() {
return new TranslatableComponent("command.servers.title");
}
@Override
protected BaseComponent entry(Server server, int index) {
return format(server);
}
}.display(sender, servers, args.getInteger(0, 1));
}
@Command(
aliases = { "server", "srv" },
desc = "Show the name of this server or connect to a different server",
usage = "[-d datacenter] [name]",
flags = "bd:"
)
public List<String> server(CommandContext args, final CommandSender sender) throws CommandException {
if(args.getSuggestionContext() != null) {
return StringUtils.complete(args.getJoinedStrings(0),
serverStore.all()
.filter(teleporter::isConnectable)
.map(Server::name));
}
// Show current server
if(args.argsLength() == 0) {
teleporter.showCurrentServer(sender);
return null;
}
final Player player = CommandUtils.senderToPlayer(sender);
// Search by bungee_name
if(args.hasFlag('b')) {
final Server byBungee = serverStore.tryBungeeName(args.getJoinedStrings(0));
if(byBungee == null) {
throw new TranslatableCommandException("command.serverNotFound");
}
teleporter.remoteTeleport(player, byBungee);
return null;
}
// Search by name/datacenter
// If they don't have the X-DC perm, parse the first arg as part of the
// server name, so normal players can do "/server ghost squadron"
final String datacenter, name;
if(args.argsLength() > 1 && !args.hasFlag('d') && player.hasPermission(Teleporter.CROSS_DATACENTER_PERMISSION)) {
datacenter = args.getString(0).toUpperCase();
name = args.getJoinedStrings(1);
} else {
datacenter = args.getFlag('d', localServer.datacenter());
name = args.getJoinedStrings(0);
}
// Special aliases for the lobby
if(name.equals("lobby") || name.equals("hub")) {
teleporter.remoteTeleport(player, datacenter, null, null);
return null;
}
final Set<Server> connectable = serverStore.subset(teleporter::isConnectable);
final List<Server> partial = new ArrayList<>();
for(Server server : connectable) {
if(server.name().equalsIgnoreCase(name)) {
teleporter.remoteTeleport(player, server);
return null;
}
if(StringUtils.startsWithIgnoreCase(server.name(), name)) {
partial.add(server);
}
}
final Audience audience = audiences.get(sender);
audience.sendMessage(new WarningComponent("command.serverNotFound"));
// If there were no more than 3 partial matches, show them
if(partial.size() <= 3) {
Collections.sort(partial, FULLNESS);
for(Server server : partial) {
audience.sendMessage(format(server));
}
}
return null;
}
@Command(
aliases = {"hub", "lobby"},
desc = "Teleport to the lobby",
min = 0,
max = 1
)
public void hub(final CommandContext args, CommandSender sender) throws CommandException {
teleporter.sendToLobby(CommandUtils.senderToPlayer(sender), args.getString(0, null));
}
}