138 lines
6.0 KiB
Java
138 lines
6.0 KiB
Java
package tc.oc.commons.bukkit.commands;
|
|
|
|
import java.util.EnumSet;
|
|
import java.util.logging.Logger;
|
|
import javax.inject.Inject;
|
|
|
|
import com.google.common.util.concurrent.ListenableFuture;
|
|
import com.sk89q.minecraft.util.commands.Command;
|
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
|
import com.sk89q.minecraft.util.commands.CommandException;
|
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
|
import org.bukkit.ChatColor;
|
|
import org.bukkit.command.CommandSender;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.event.EventHandler;
|
|
import org.bukkit.event.EventPriority;
|
|
import org.bukkit.event.Listener;
|
|
import org.bukkit.event.player.PlayerQuitEvent;
|
|
import tc.oc.api.docs.Server;
|
|
import tc.oc.api.docs.virtual.ServerDoc;
|
|
import tc.oc.api.minecraft.MinecraftService;
|
|
import tc.oc.minecraft.scheduler.SyncExecutor;
|
|
import tc.oc.commons.bukkit.event.WhitelistStateChangeEvent;
|
|
import tc.oc.commons.bukkit.whitelist.Whitelist;
|
|
import tc.oc.commons.core.commands.CommandFutureCallback;
|
|
import tc.oc.commons.core.commands.Commands;
|
|
import tc.oc.commons.core.logging.Loggers;
|
|
|
|
public class ServerVisibilityCommands implements Listener, Commands {
|
|
|
|
private static final String VISIBILITY_PERMISSION = "server.visibility";
|
|
private static final EnumSet<ServerDoc.Visibility> OPTIONS = EnumSet.of(ServerDoc.Visibility.PUBLIC, ServerDoc.Visibility.UNLISTED);
|
|
|
|
private final Logger logger;
|
|
private final MinecraftService minecraftService;
|
|
private final SyncExecutor syncExecutor;
|
|
private final Whitelist whitelist;
|
|
|
|
@Inject ServerVisibilityCommands(Loggers loggers, MinecraftService minecraftService, SyncExecutor syncExecutor, Whitelist whitelist) {
|
|
this.whitelist = whitelist;
|
|
this.logger = loggers.get(getClass());
|
|
this.minecraftService = minecraftService;
|
|
this.syncExecutor = syncExecutor;
|
|
}
|
|
|
|
private static String coloredVisibility(ServerDoc.Visibility visibility) {
|
|
switch(visibility) {
|
|
case PRIVATE: return ChatColor.BLUE + "private";
|
|
case UNLISTED: return ChatColor.YELLOW + "unlisted";
|
|
case PUBLIC: return ChatColor.GREEN + "public";
|
|
default: return ChatColor.RED + "unknown";
|
|
}
|
|
}
|
|
|
|
private static void reportVisibility(CommandSender sender, ServerDoc.Visibility visibility) {
|
|
sender.sendMessage("Server visibility: " + coloredVisibility(visibility));
|
|
}
|
|
|
|
// Too bad Gson refuses to serialize anonymous classes
|
|
private static class Info implements ServerDoc.Visible {
|
|
private final ServerDoc.Visibility visibility;
|
|
public Info(ServerDoc.Visibility visibility) {this.visibility = visibility; }
|
|
@Override public ServerDoc.Visibility visibility() { return visibility; }
|
|
}
|
|
|
|
private ListenableFuture<Server> setVisibility(final ServerDoc.Visibility visibility) {
|
|
return minecraftService.updateLocalServer(new Info(visibility));
|
|
}
|
|
|
|
@Command(
|
|
aliases = { "visibility" },
|
|
desc = "Show or change the visibility type of this server",
|
|
usage = "[public|unlisted]",
|
|
min = 0,
|
|
max = 1
|
|
)
|
|
@CommandPermissions(VISIBILITY_PERMISSION)
|
|
public void visibility(final CommandContext args, final CommandSender sender) throws CommandException {
|
|
final Server local = minecraftService.getLocalServer();
|
|
if(args.argsLength() < 1) {
|
|
reportVisibility(sender, local.visibility());
|
|
} else {
|
|
final ServerDoc.Visibility visibility;
|
|
try {
|
|
visibility = ServerDoc.Visibility.valueOf(args.getString(0).toUpperCase());
|
|
if(!OPTIONS.contains(visibility)) throw new IllegalArgumentException();
|
|
} catch(IllegalArgumentException e) {
|
|
throw new CommandException("Invalid visibility type '" + args.getString(0) + "'");
|
|
}
|
|
|
|
if(visibility == ServerDoc.Visibility.PUBLIC && whitelist.isEnabled()) {
|
|
throw new CommandException("Cannot set visibility to 'public' while whitelist is enabled");
|
|
}
|
|
|
|
syncExecutor.callback(
|
|
setVisibility(visibility),
|
|
CommandFutureCallback.onSuccess(sender, args, response -> {
|
|
logger.info("Server visibility set to " + response.visibility() + " by " + sender.getName());
|
|
reportVisibility(sender, response.visibility());
|
|
})
|
|
);
|
|
}
|
|
}
|
|
|
|
@EventHandler(priority = EventPriority.MONITOR)
|
|
public void hideAbandonedServer(PlayerQuitEvent event) {
|
|
final Server local = minecraftService.getLocalServer();
|
|
|
|
if(local.startup_visibility() != ServerDoc.Visibility.PUBLIC && // If server was initially not public and
|
|
local.visibility() == ServerDoc.Visibility.PUBLIC && // server was made public and
|
|
event.getPlayer().hasPermission(VISIBILITY_PERMISSION)) { // someone with perms to do that is leaving...
|
|
|
|
// ...check if there is still someone online with that permission
|
|
for(Player player : event.getPlayer().getServer().getOnlinePlayers()) {
|
|
// If someone else with perms is online, we're cool
|
|
if(player != event.getPlayer() && player.hasPermission(VISIBILITY_PERMISSION)) return;
|
|
}
|
|
|
|
// If nobody with perms is online, make the server non-public again
|
|
logger.info("Reverting server visibility to " + local.startup_visibility() + " because nobody with permissions is online");
|
|
setVisibility(local.startup_visibility());
|
|
}
|
|
}
|
|
|
|
@EventHandler
|
|
public void hideWhitelistedServer(WhitelistStateChangeEvent event) {
|
|
final Server local = minecraftService.getLocalServer();
|
|
|
|
if(local.startup_visibility() != ServerDoc.Visibility.PUBLIC &&
|
|
local.visibility() == ServerDoc.Visibility.PUBLIC &&
|
|
event.isEnabled()) {
|
|
|
|
logger.info("Reverting server visibility to " + local.startup_visibility() + " because whitelist is enabled");
|
|
setVisibility(local.startup_visibility());
|
|
}
|
|
}
|
|
}
|