240 lines
9.6 KiB
Java
240 lines
9.6 KiB
Java
package tc.oc.commons.bukkit.commands;
|
|
|
|
import javax.annotation.Nullable;
|
|
import javax.inject.Inject;
|
|
import javax.inject.Singleton;
|
|
|
|
import com.google.common.util.concurrent.FutureCallback;
|
|
import com.google.common.util.concurrent.Futures;
|
|
import com.google.common.util.concurrent.ListenableFuture;
|
|
import com.google.common.util.concurrent.SettableFuture;
|
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
|
import com.sk89q.minecraft.util.commands.CommandException;
|
|
import org.bukkit.command.CommandSender;
|
|
import org.bukkit.entity.Player;
|
|
import tc.oc.api.bukkit.users.BukkitUserStore;
|
|
import tc.oc.api.bukkit.users.OnlinePlayers;
|
|
import tc.oc.api.docs.User;
|
|
import tc.oc.api.exceptions.NotFound;
|
|
import tc.oc.api.minecraft.MinecraftService;
|
|
import tc.oc.api.users.UserSearchRequest;
|
|
import tc.oc.api.users.UserSearchResponse;
|
|
import tc.oc.api.users.UserService;
|
|
import tc.oc.commons.bukkit.nick.IdentityProvider;
|
|
import tc.oc.minecraft.scheduler.MainThreadExecutor;
|
|
import tc.oc.commons.bukkit.users.PlayerSearchResponse;
|
|
import tc.oc.commons.core.commands.TranslatableCommandException;
|
|
import tc.oc.commons.core.util.Orderable;
|
|
|
|
@Singleton
|
|
public class UserFinder {
|
|
|
|
public enum Default implements Orderable<Default> { NULL, THROW, SENDER }
|
|
public enum Scope implements Orderable<Scope> { LOCAL, ONLINE, ALL }
|
|
|
|
private final MinecraftService minecraftService;
|
|
private final UserService userService;
|
|
private final BukkitUserStore userStore;
|
|
private final IdentityProvider identityProvider;
|
|
private final MainThreadExecutor mainThreadExecutor;
|
|
private final OnlinePlayers onlinePlayers;
|
|
|
|
@Inject UserFinder(MinecraftService minecraftService, UserService userService, BukkitUserStore userStore, IdentityProvider identityProvider, MainThreadExecutor mainThreadExecutor, OnlinePlayers onlinePlayers) {
|
|
this.minecraftService = minecraftService;
|
|
this.userService = userService;
|
|
this.userStore = userStore;
|
|
this.identityProvider = identityProvider;
|
|
this.mainThreadExecutor = mainThreadExecutor;
|
|
this.onlinePlayers = onlinePlayers;
|
|
}
|
|
|
|
public Player senderToPlayer(CommandSender sender) throws CommandException {
|
|
if(sender instanceof Player) {
|
|
return (Player) sender;
|
|
} else {
|
|
throw new TranslatableCommandException("command.onlyPlayers");
|
|
}
|
|
}
|
|
|
|
public @Nullable User getLocalUser(CommandSender sender) {
|
|
if(sender instanceof Player) {
|
|
return userStore.getUser((Player) sender);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public @Nullable Player getLocalPlayer(CommandSender sender, String username) {
|
|
return sender.getServer().getPlayerExact(username, sender);
|
|
}
|
|
|
|
public UserSearchResponse localUserResponse(CommandSender viewer, Player player) {
|
|
return new UserSearchResponse(
|
|
userStore.getUser(player),
|
|
true,
|
|
identityProvider.currentIdentity(player).isDisguised(viewer),
|
|
userStore.getSession(player),
|
|
minecraftService.getLocalServer()
|
|
);
|
|
}
|
|
|
|
public PlayerSearchResponse localPlayerResponse(CommandSender viewer, Player player) {
|
|
return new PlayerSearchResponse(
|
|
localUserResponse(viewer, player),
|
|
player
|
|
);
|
|
}
|
|
|
|
public ListenableFuture<UserSearchResponse> findUser(final CommandSender sender, @Nullable String name, Scope scope, Default def) {
|
|
try {
|
|
if(name != null) {
|
|
final Player player = getLocalPlayer(sender, name);
|
|
if(player != null) {
|
|
return Futures.immediateFuture(localUserResponse(sender, player));
|
|
}
|
|
|
|
if(scope.noGreaterThan(Scope.LOCAL)) {
|
|
throw new TranslatableCommandException("command.playerNotFound");
|
|
}
|
|
|
|
final SettableFuture<UserSearchResponse> result = SettableFuture.create();
|
|
Futures.addCallback(
|
|
userService.search(new UserSearchRequest(name, getLocalUser(sender))),
|
|
new FutureCallback<UserSearchResponse>() {
|
|
@Override
|
|
public void onSuccess(@Nullable UserSearchResponse response) {
|
|
if(!response.online && scope.noGreaterThan(Scope.ONLINE)) {
|
|
result.setException(new TranslatableCommandException("command.playerNotFound"));
|
|
} else {
|
|
result.set(response);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(Throwable e) {
|
|
if(e instanceof NotFound) {
|
|
result.setException(new TranslatableCommandException("command.playerNotFound"));
|
|
} else {
|
|
result.setException(e);
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
return result;
|
|
} else {
|
|
switch(def) {
|
|
case NULL:
|
|
return Futures.immediateFuture(null);
|
|
|
|
case SENDER:
|
|
return Futures.immediateFuture(localUserResponse(sender, senderToPlayer(sender)));
|
|
|
|
default:
|
|
throw new TranslatableCommandException("command.specifyPlayer");
|
|
}
|
|
}
|
|
} catch(CommandException e) {
|
|
return Futures.immediateFailedFuture(e);
|
|
}
|
|
}
|
|
|
|
public ListenableFuture<PlayerSearchResponse> findPlayer(CommandSender sender, @Nullable String name, Scope scope, Default def) {
|
|
try {
|
|
if (name == null || name.isEmpty()) {
|
|
switch(def) {
|
|
case NULL:
|
|
return Futures.immediateFuture(null);
|
|
|
|
case SENDER:
|
|
return Futures.immediateFuture(localPlayerResponse(sender, senderToPlayer(sender)));
|
|
|
|
default:
|
|
throw new TranslatableCommandException("command.specifyPlayer");
|
|
}
|
|
}
|
|
|
|
final Player player = getLocalPlayer(sender, name);
|
|
if(player != null) {
|
|
return Futures.immediateFuture(localPlayerResponse(sender, player));
|
|
}
|
|
|
|
if(scope.noGreaterThan(Scope.LOCAL)) {
|
|
throw new TranslatableCommandException("command.playerNotFound");
|
|
}
|
|
|
|
final SettableFuture<PlayerSearchResponse> playerResult = SettableFuture.create();
|
|
mainThreadExecutor.callback(
|
|
findUser(sender, name, scope, def),
|
|
new FutureCallback<UserSearchResponse>() {
|
|
@Override
|
|
public void onSuccess(@Nullable UserSearchResponse userResult) {
|
|
playerResult.set(new PlayerSearchResponse(userResult, onlinePlayers.find(userResult.user)));
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(Throwable t) {
|
|
playerResult.setException(t);
|
|
}
|
|
}
|
|
);
|
|
|
|
return playerResult;
|
|
} catch(CommandException e) {
|
|
return Futures.immediateFailedFuture(e);
|
|
}
|
|
}
|
|
|
|
|
|
// findUser overloads
|
|
|
|
public ListenableFuture<UserSearchResponse> findUser(final CommandSender sender, CommandContext args, int index, Scope scope, Default def) {
|
|
return findUser(sender, args.getString(index, null), scope, def);
|
|
}
|
|
|
|
public ListenableFuture<UserSearchResponse> findUser(final CommandSender sender, CommandContext args, int index, Default def) {
|
|
return findUser(sender, args, index, Scope.ALL, def);
|
|
}
|
|
|
|
public ListenableFuture<UserSearchResponse> findUser(final CommandSender sender, CommandContext args, int index, Scope scope) {
|
|
return findUser(sender, args.getString(index, null), scope, Default.THROW);
|
|
}
|
|
|
|
public ListenableFuture<UserSearchResponse> findUser(final CommandSender sender, CommandContext args, int index) {
|
|
return findUser(sender, args, index, Scope.ALL, Default.THROW);
|
|
}
|
|
|
|
|
|
// findPlayer overloads
|
|
|
|
public ListenableFuture<PlayerSearchResponse> findPlayer(CommandSender sender, CommandContext args, int index, Scope scope, Default def) {
|
|
return findPlayer(sender, args.getString(index, null), scope, def);
|
|
}
|
|
|
|
public ListenableFuture<PlayerSearchResponse> findPlayer(CommandSender sender, CommandContext args, int index, Scope scope) {
|
|
return findPlayer(sender, args, index, scope, Default.THROW);
|
|
}
|
|
|
|
public ListenableFuture<PlayerSearchResponse> findPlayer(CommandSender sender, CommandContext args, int index, Default def) {
|
|
return findPlayer(sender, args, index, Scope.ALL, def);
|
|
}
|
|
|
|
public ListenableFuture<PlayerSearchResponse> findPlayer(CommandSender sender, CommandContext args, int index) {
|
|
return findPlayer(sender, args, index, Scope.ALL, Default.THROW);
|
|
}
|
|
|
|
|
|
// Special cases
|
|
|
|
public ListenableFuture<PlayerSearchResponse> findLocalPlayer(CommandSender sender, CommandContext args, int index, Default def) {
|
|
return findPlayer(sender, args, index, Scope.LOCAL, def);
|
|
}
|
|
|
|
public ListenableFuture<PlayerSearchResponse> findLocalPlayer(CommandSender sender, CommandContext args, int index) {
|
|
return findLocalPlayer(sender, args, index, Default.THROW);
|
|
}
|
|
|
|
public ListenableFuture<PlayerSearchResponse> findLocalPlayerOrSender(CommandSender sender, CommandContext args, int index) {
|
|
return findLocalPlayer(sender, args, index, Default.SENDER);
|
|
}
|
|
}
|