Skip to content

Commit

Permalink
添加 link 指令 #94
Browse files Browse the repository at this point in the history
  • Loading branch information
CaaMoe committed Aug 27, 2023
1 parent 1fe5d33 commit 22076a9
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 11 deletions.
8 changes: 8 additions & 0 deletions api/src/main/java/moe/caa/multilogin/api/util/ValueUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,12 @@ public static byte[] sha256(String str) throws NoSuchAlgorithmException {
public static UUID xuidToUUID(String xuid) {
return new UUID(0, Long.parseLong(xuid));
}

public static String generateLinkCode(){
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 6; i++) {
builder.append((int)(10 * Math.random()));
}
return builder.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ public class BuiltInExceptions implements BuiltInExceptionProvider {
private final DynamicCommandExceptionType PLAYER_NOT_ONLINE;

private final SimpleCommandExceptionType CACHE_NOT_FOUND_SELF;
private final SimpleCommandExceptionType NO_SELF;

private final Dynamic2CommandExceptionType CACHE_NOT_FOUND_OTHER;

public BuiltInExceptions(MultiCore core) {

Expand Down Expand Up @@ -129,6 +132,14 @@ public BuiltInExceptions(MultiCore core) {
)));

CACHE_NOT_FOUND_SELF = new SimpleCommandExceptionType(new LiteralMessage(core.getLanguageHandler().getMessage("command_message_cache_not_found_self")));
NO_SELF = new SimpleCommandExceptionType(new LiteralMessage(core.getLanguageHandler().getMessage("command_message_player_no_self")));


CACHE_NOT_FOUND_OTHER = new Dynamic2CommandExceptionType((uuid, name) -> new LiteralMessage(
core.getLanguageHandler().getMessage("command_message_cache_not_found_other",
new Pair<>("uuid", uuid),
new Pair<>("name", name)
)));
}

@Override
Expand Down Expand Up @@ -274,7 +285,15 @@ public DynamicCommandExceptionType playerNotOnline() {
return PLAYER_NOT_ONLINE;
}

public SimpleCommandExceptionType noSelf() {
return NO_SELF;
}

public SimpleCommandExceptionType cacheNotFoundSelf() {
return CACHE_NOT_FOUND_SELF;
}

public Dynamic2CommandExceptionType cacheNotFoundOther() {
return CACHE_NOT_FOUND_OTHER;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import moe.caa.multilogin.api.auth.GameProfile;
import moe.caa.multilogin.api.command.CommandAPI;
import moe.caa.multilogin.api.logger.LoggerProvider;
import moe.caa.multilogin.api.plugin.IPlayer;
import moe.caa.multilogin.api.plugin.ISender;
import moe.caa.multilogin.api.util.Pair;
import moe.caa.multilogin.core.command.commands.RootCommand;
Expand Down Expand Up @@ -115,15 +116,32 @@ public final void requirePlayer(CommandContext<ISender> context) throws CommandS
}
}

public final void requirePlayerAndNoSelf(CommandContext<ISender> context, IPlayer player) throws CommandSyntaxException {
if (!context.getSource().isPlayer()) {
throw builtInExceptions.requirePlayer().create();
}
if(context.getSource().getAsPlayer().getUniqueId().equals(player.getUniqueId())){
throw builtInExceptions.noSelf().create();
}
}

/**
* 检查是通过猫踢螺钉登录的玩家
*/
public final Pair<GameProfile, Integer> requireDataCacheArgument(CommandContext<ISender> context) throws CommandSyntaxException {
public final Pair<GameProfile, Integer> requireDataCacheArgumentSelf(CommandContext<ISender> context) throws CommandSyntaxException {
requirePlayer(context);
Pair<GameProfile, Integer> profile = core.getPlayerHandler().getPlayerOnlineProfile(context.getSource().getAsPlayer().getUniqueId());
if (profile == null) {
throw builtInExceptions.cacheNotFoundSelf().create();
}
return profile;
}

public final Pair<GameProfile, Integer> requireDataCacheArgumentOther(IPlayer player) throws CommandSyntaxException {
Pair<GameProfile, Integer> profile = core.getPlayerHandler().getPlayerOnlineProfile(player.getUniqueId());
if (profile == null) {
throw builtInExceptions.cacheNotFoundOther().create(player.getUniqueId(), player.getName());
}
return profile;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public final class Permissions {
public static final String COMMAND_MULTI_LOGIN_FIND_ONLINE = "command.multilogin.find.online";
public static final String COMMAND_MULTI_LOGIN_FIND_PROFILE = "command.multilogin.find.profile";
public static final String COMMAND_MULTI_LOGIN_DATA_CONVERT = "command.multilogin.data.convert";
public static final String COMMAND_MULTI_LOGIN_PROFILE_UPDATENAME = "command.multilogin.profile.updatename";

public static final String COMMAND_MULTI_LOGIN_LINK_TO = "command.multilogin.link.to";
public static final String COMMAND_MULTI_LOGIN_LINK_ACCEPT = "command.multilogin.link.accept";
public static final String COMMAND_MULTI_LOGIN_LINK_CODE = "command.multilogin.link.code";
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,22 @@
import com.mojang.brigadier.Message;
import com.mojang.brigadier.exceptions.CommandExceptionType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class UniversalCommandExceptionType implements CommandExceptionType {
private static final UniversalCommandExceptionType instance = new UniversalCommandExceptionType();

public static CommandSyntaxException create(Message message){
return new CommandSyntaxException(instance, message);
}

public static CommandSyntaxException create(String message){
return create(new LiteralMessage(message));
}

public static CommandSyntaxException create(Message message, ImmutableStringReader reader) {
return new CommandSyntaxException(instance, message, reader.getString(), reader.getCursor());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ public MInfoCommand(CommandHandler handler) {
}

public LiteralArgumentBuilder<ISender> register(LiteralArgumentBuilder<ISender> literalArgumentBuilder) {
return literalArgumentBuilder.then(handler.argument("player", OnlinePlayerArgumentType.player())
return literalArgumentBuilder.then(handler.argument("player", OnlinePlayerArgumentType.players())
.requires(iSender -> iSender.hasPermission(Permissions.COMMAND_MULTI_LOGIN_CURRENT_OTHER))
.executes(this::executeInfo))
.requires(iSender -> iSender.hasPermission(Permissions.COMMAND_MULTI_LOGIN_CURRENT_ONESELF))
.executes(this::executeInfoOneself);
}

private int executeInfo(CommandContext<ISender> context) {
Set<IPlayer> players = OnlinePlayerArgumentType.getPlayer(context, "player");
Set<IPlayer> players = OnlinePlayerArgumentType.getPlayers(context, "player");
processInfoCommand(context, players);
return 0;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package moe.caa.multilogin.core.command.commands;

import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import lombok.SneakyThrows;
import moe.caa.multilogin.api.auth.GameProfile;
import moe.caa.multilogin.api.plugin.IPlayer;
import moe.caa.multilogin.api.plugin.ISender;
import moe.caa.multilogin.api.util.Pair;
import moe.caa.multilogin.api.util.ValueUtil;
import moe.caa.multilogin.core.command.CommandHandler;
import moe.caa.multilogin.core.command.Permissions;
import moe.caa.multilogin.core.command.argument.OnlinePlayerArgumentType;
import moe.caa.multilogin.core.command.argument.StringArgumentType;
import moe.caa.multilogin.core.configuration.service.BaseServiceConfig;

import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public class MLinkCommand {
private final CommandHandler handler;
private final Map<GameProfile, Entry> gameProfileEntryMap = new ConcurrentHashMap<>();

public MLinkCommand(CommandHandler handler) {
this.handler = handler;
}

public LiteralArgumentBuilder<ISender> register(LiteralArgumentBuilder<ISender> literal) {
return literal
.then(handler.literal("to")
.requires(sender -> sender.hasPermission(Permissions.COMMAND_MULTI_LOGIN_LINK_TO))
.then(handler.argument("player", OnlinePlayerArgumentType.players())
.executes(this::executeLinkTo)))
.then(handler.literal("accept")
.requires(iSender -> iSender.hasPermission(Permissions.COMMAND_MULTI_LOGIN_LINK_ACCEPT))
.then(handler.argument("name", StringArgumentType.string())
.executes(this::executeLinkAccept)))
.then(handler.literal("code")
.requires(iSender -> iSender.hasPermission(Permissions.COMMAND_MULTI_LOGIN_LINK_CODE))
.then(handler.argument("player", OnlinePlayerArgumentType.players())
.then(handler.argument("code", StringArgumentType.string())
.executes(this::executeLinkCode))));
}

@SneakyThrows
private int executeLinkCode(CommandContext<ISender> context) {
GameProfile self = handler.requireDataCacheArgumentSelf(context).getValue1();
IPlayer target = OnlinePlayerArgumentType.getPlayer(context, "player");
String code = StringArgumentType.getString(context, "code");

gameProfileEntryMap.values().removeIf(e -> e.timeMills < System.currentTimeMillis() - 30000);
Entry entry = gameProfileEntryMap.get(self);
if(entry == null || !entry.receiverUserInGameUUID.equals(target.getUniqueId()) || entry.code == null){
context.getSource().sendMessagePL(CommandHandler.getCore().getLanguageHandler().getMessage("command_message_code_invalid"));
return 0;
}
if(!entry.code.equals(code)){
context.getSource().sendMessagePL(CommandHandler.getCore().getLanguageHandler().getMessage("command_message_code_invalid_code"));
return 0;
}
gameProfileEntryMap.remove(self);

CommandHandler.getCore().getSqlManager().getUserDataTable().setInGameUUID(entry.requesterOnlineProfile.getValue1().getId(),
entry.requesterOnlineProfile.getValue2(), entry.receiverUserInGameUUID);

context.getSource().sendMessagePL(
CommandHandler.getCore().getLanguageHandler().getMessage("command_message_code_succeed",
new Pair<>("redirect_name", target.getName()),
new Pair<>("redirect_uuid", target.getUniqueId())
));

context.getSource().getAsPlayer().kickPlayer(CommandHandler.getCore().getLanguageHandler().getMessage("command_message_code_kickmessage",
new Pair<>("redirect_name", target.getName()),
new Pair<>("redirect_uuid", target.getUniqueId())
));
return 0;
}

private int executeLinkAccept(CommandContext<ISender> context) throws CommandSyntaxException {
handler.requireDataCacheArgumentSelf(context);
String string = StringArgumentType.getString(context, "name");

gameProfileEntryMap.values().removeIf(e -> e.timeMills < System.currentTimeMillis() - 30000);
Optional<Map.Entry<GameProfile, Entry>> entry = gameProfileEntryMap.entrySet().stream()
.filter(e -> e.getKey().getName().equalsIgnoreCase(string))
.filter(e -> e.getValue().receiverUserInGameUUID.equals(context.getSource().getAsPlayer().getUniqueId()))
.filter(e -> e.getValue().code == null).findFirst();

if (entry.isEmpty()) {
context.getSource().sendMessagePL(CommandHandler.getCore().getLanguageHandler().getMessage("command_message_accept_invalid"));
return 0;
}
Map.Entry<GameProfile, Entry> profileEntryEntry = entry.get();

String targetServiceName;
BaseServiceConfig bsc = CommandHandler.getCore().getPluginConfig().getServiceIdMap().get(profileEntryEntry.getValue().requesterOnlineProfile.getValue2());
if (bsc == null) {
targetServiceName = CommandHandler.getCore().getLanguageHandler().getMessage("command_message_info_unidentified_name");
} else {
targetServiceName = bsc.getName();
}

handler.getSecondaryConfirmationHandler().submit(context.getSource(), () -> {
profileEntryEntry.getValue().code = ValueUtil.generateLinkCode();
context.getSource().sendMessagePL(CommandHandler.getCore().getLanguageHandler().getMessage("command_message_accept",
new Pair<>("code", profileEntryEntry.getValue().code),
new Pair<>("profile_name", context.getSource().getAsPlayer().getName())
));
}, CommandHandler.getCore().getLanguageHandler().getMessage("command_message_accept_desc",
new Pair<>("target_service_name", targetServiceName),
new Pair<>("target_service_id", profileEntryEntry.getValue().requesterOnlineProfile.getValue2()),
new Pair<>("target_online_name", profileEntryEntry.getKey().getName()),
new Pair<>("target_online_uuid", profileEntryEntry.getKey().getId()),
new Pair<>("profile_name", context.getSource().getAsPlayer().getName()),
new Pair<>("profile_uuid", context.getSource().getAsPlayer().getUniqueId())
), CommandHandler.getCore().getLanguageHandler().getMessage("command_message_accept_cq",
new Pair<>("target_service_name", targetServiceName),
new Pair<>("target_service_id", profileEntryEntry.getValue().requesterOnlineProfile.getValue2()),
new Pair<>("target_online_name", profileEntryEntry.getKey().getName()),
new Pair<>("target_online_uuid", profileEntryEntry.getKey().getId()),
new Pair<>("profile_name", context.getSource().getAsPlayer().getName()),
new Pair<>("profile_uuid", context.getSource().getAsPlayer().getUniqueId())
));

return 0;
}

private int executeLinkTo(CommandContext<ISender> context) throws CommandSyntaxException {
Pair<GameProfile, Integer> self = handler.requireDataCacheArgumentSelf(context);
IPlayer target = OnlinePlayerArgumentType.getPlayer(context, "player");

handler.requirePlayerAndNoSelf(context, target);
handler.requireDataCacheArgumentOther(target);

handler.getSecondaryConfirmationHandler().submit(context.getSource(), () -> {
gameProfileEntryMap.put(self.getValue1(), new Entry(self, target.getUniqueId()));
context.getSource().sendMessagePL(CommandHandler.getCore().getLanguageHandler().getMessage("command_message_link",
new Pair<>("self_online_name", self.getValue1().getName())
));
}, CommandHandler.getCore().getLanguageHandler().getMessage("command_message_link_to_desc",
new Pair<>("redirect_name", target.getName()),
new Pair<>("redirect_uuid", target.getUniqueId())
), CommandHandler.getCore().getLanguageHandler().getMessage("command_message_link_to_cq",
new Pair<>("redirect_name", target.getName()),
new Pair<>("redirect_uuid", target.getUniqueId())
));
return 0;
}

public static class Entry {
// 请求发起时间
private final long timeMills = System.currentTimeMillis();
// 请求发起玩家的在线档案
private final Pair<GameProfile, Integer> requesterOnlineProfile;
// 请求发起玩家请求的档案uuid
private final UUID receiverUserInGameUUID;
// 连接码
private String code;

public Entry(Pair<GameProfile, Integer> requesterOnlineProfile, UUID receiverUserInGameUUID) {
this.requesterOnlineProfile = requesterOnlineProfile;
this.receiverUserInGameUUID = receiverUserInGameUUID;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ private int executeSetOther(CommandContext<ISender> context) {
@SneakyThrows
private int executeSetOneself(CommandContext<ISender> context) {
ProfileArgumentType.ProfileArgument profile = ProfileArgumentType.getProfile(context, "profile");
Pair<GameProfile, Integer> pair = handler.requireDataCacheArgument(context);
Pair<GameProfile, Integer> pair = handler.requireDataCacheArgumentSelf(context);

processSet(context, pair.getValue1().getId(), pair.getValue1().getName(), pair.getValue2(), profile);
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private int executeRenameOther(CommandContext<ISender> context) {
@SneakyThrows
private int executeRename(CommandContext<ISender> context) {
String newname = StringArgumentType.getString(context, "newname");
handler.requireDataCacheArgument(context);
handler.requireDataCacheArgumentSelf(context);

processRename(context, newname, new ProfileArgumentType.ProfileArgument(context.getSource().getAsPlayer().getUniqueId(), context.getSource().getAsPlayer().getName()));
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public LiteralArgumentBuilder<ISender> register(LiteralArgumentBuilder<ISender>
.then(new MRenameCommand(handler).register(handler.literal("rename")))
.then(new MFindCommand(handler).register(handler.literal("find")))
.then(new MInfoCommand(handler).register(handler.literal("info")))
.then(new MLinkCommand(handler).register(handler.literal("link")))
.then(new MDataConvert(handler).register(handler.literal("dataconvert")));
}

Expand Down
Loading

0 comments on commit 22076a9

Please sign in to comment.