mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2025-12-19 14:59:20 +00:00
First part of news
This commit is contained in:
@@ -118,6 +118,12 @@ public interface PlayerLink {
|
|||||||
@NonNull String code
|
@NonNull String code
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of this database implementation. This will return null when Player Linking
|
||||||
|
* is disabled or when <b>only</b> Global Linking is used.
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return if account linking is enabled. The difference between enabled and allowed is that
|
* Return if account linking is enabled. The difference between enabled and allowed is that
|
||||||
* 'enabled' still allows already linked people to join with their linked account while 'allow
|
* 'enabled' still allows already linked people to join with their linked account while 'allow
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ package org.geysermc.floodgate.util;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -40,8 +41,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
|
||||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||||
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
import org.geysermc.floodgate.player.UserAudience;
|
import org.geysermc.floodgate.player.UserAudience;
|
||||||
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
|
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
|
||||||
import org.geysermc.floodgate.util.BungeeUserAudience.BungeeConsoleAudience;
|
import org.geysermc.floodgate.util.BungeeUserAudience.BungeeConsoleAudience;
|
||||||
@@ -135,17 +136,40 @@ public final class BungeeCommandUtil implements CommandUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(Object target, String locale, CommandMessage message, Object... args) {
|
public boolean hasPermission(Object player, String permission) {
|
||||||
|
return cast(player).hasPermission(permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Object> getOnlinePlayersWithPermission(String permission) {
|
||||||
|
List<Object> players = new ArrayList<>();
|
||||||
|
for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
|
||||||
|
if (hasPermission(player, permission)) {
|
||||||
|
players.add(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(Object target, String locale, TranslatableMessage message, Object... args) {
|
||||||
((CommandSender) target).sendMessage(translateAndTransform(locale, message, args));
|
((CommandSender) target).sendMessage(translateAndTransform(locale, message, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void kickPlayer(Object player, String locale, CommandMessage message, Object... args) {
|
public void sendMessage(Object target, String message) {
|
||||||
|
((CommandSender) target).sendMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void kickPlayer(Object player, String locale, TranslatableMessage message, Object... args) {
|
||||||
cast(player).disconnect(translateAndTransform(locale, message, args));
|
cast(player).disconnect(translateAndTransform(locale, message, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseComponent[] translateAndTransform(String locale, CommandMessage message,
|
public BaseComponent[] translateAndTransform(
|
||||||
Object... args) {
|
String locale,
|
||||||
|
TranslatableMessage message,
|
||||||
|
Object... args) {
|
||||||
return TextComponent.fromLegacyText(message.translateMessage(manager, locale, args));
|
return TextComponent.fromLegacyText(message.translateMessage(manager, locale, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
|
||||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||||
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
import org.geysermc.floodgate.player.UserAudience;
|
import org.geysermc.floodgate.player.UserAudience;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -74,13 +74,15 @@ public class BungeeUserAudience implements UserAudience, ForwardingAudience.Sing
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(@NonNull Identity source, @NonNull Component message,
|
public void sendMessage(
|
||||||
@NonNull MessageType type) {
|
@NonNull Identity source,
|
||||||
|
@NonNull Component message,
|
||||||
|
@NonNull MessageType type) {
|
||||||
this.source.sendMessage(GsonComponentSerializer.gson().serialize(message));
|
this.source.sendMessage(GsonComponentSerializer.gson().serialize(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(CommandMessage message, Object... args) {
|
public void sendMessage(TranslatableMessage message, Object... args) {
|
||||||
commandUtil.sendMessage(source(), locale(), message, args);
|
commandUtil.sendMessage(source(), locale(), message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +94,7 @@ public class BungeeUserAudience implements UserAudience, ForwardingAudience.Sing
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnect(CommandMessage message, Object... args) {
|
public void disconnect(TranslatableMessage message, Object... args) {
|
||||||
commandUtil.kickPlayer(source(), locale(), message, args);
|
commandUtil.kickPlayer(source(), locale(), message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import org.geysermc.floodgate.config.loader.ConfigLoader;
|
|||||||
import org.geysermc.floodgate.link.PlayerLinkLoader;
|
import org.geysermc.floodgate.link.PlayerLinkLoader;
|
||||||
import org.geysermc.floodgate.module.ConfigLoadedModule;
|
import org.geysermc.floodgate.module.ConfigLoadedModule;
|
||||||
import org.geysermc.floodgate.module.PostInitializeModule;
|
import org.geysermc.floodgate.module.PostInitializeModule;
|
||||||
|
import org.geysermc.floodgate.news.NewsChecker;
|
||||||
import org.geysermc.floodgate.util.PrefixCheckTask;
|
import org.geysermc.floodgate.util.PrefixCheckTask;
|
||||||
import org.geysermc.floodgate.util.TimeSyncerHolder;
|
import org.geysermc.floodgate.util.TimeSyncerHolder;
|
||||||
|
|
||||||
@@ -123,6 +124,7 @@ public class FloodgatePlatform {
|
|||||||
|
|
||||||
PrefixCheckTask.checkAndExecuteDelayed(config, logger);
|
PrefixCheckTask.checkAndExecuteDelayed(config, logger);
|
||||||
|
|
||||||
|
guice.getInstance(NewsChecker.class).start();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ package org.geysermc.floodgate.addon.debug;
|
|||||||
public enum State {
|
public enum State {
|
||||||
HANDSHAKE, STATUS, LOGIN, PLAY;
|
HANDSHAKE, STATUS, LOGIN, PLAY;
|
||||||
|
|
||||||
public static final State[] VALUES = values();
|
private static final State[] VALUES = values();
|
||||||
|
|
||||||
public static State getById(int id) {
|
public static State getById(int id) {
|
||||||
return id < VALUES.length ? VALUES[id] : null;
|
return id < VALUES.length ? VALUES[id] : null;
|
||||||
|
|||||||
@@ -26,14 +26,14 @@
|
|||||||
package org.geysermc.floodgate.command;
|
package org.geysermc.floodgate.command;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Messages (or part of messages) that are used in two or more commands and thus are 'commonly
|
* Messages (or part of messages) that are used in two or more commands and thus are 'commonly
|
||||||
* used'
|
* used'
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
public enum CommonCommandMessage implements CommandMessage {
|
public enum CommonCommandMessage implements TranslatableMessage {
|
||||||
LINKING_DISABLED("floodgate.commands.linking_disabled"),
|
LINKING_DISABLED("floodgate.commands.linking_disabled"),
|
||||||
NOT_A_PLAYER("floodgate.commands.not_a_player"),
|
NOT_A_PLAYER("floodgate.commands.not_a_player"),
|
||||||
CHECK_CONSOLE("floodgate.commands.check_console"),
|
CHECK_CONSOLE("floodgate.commands.check_console"),
|
||||||
|
|||||||
@@ -42,12 +42,13 @@ import org.geysermc.floodgate.api.link.PlayerLink;
|
|||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.link.GlobalPlayerLinking;
|
import org.geysermc.floodgate.link.GlobalPlayerLinking;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
|
||||||
import org.geysermc.floodgate.platform.command.FloodgateCommand;
|
import org.geysermc.floodgate.platform.command.FloodgateCommand;
|
||||||
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
import org.geysermc.floodgate.player.UserAudience;
|
import org.geysermc.floodgate.player.UserAudience;
|
||||||
import org.geysermc.floodgate.player.UserAudience.PlayerAudience;
|
import org.geysermc.floodgate.player.UserAudience.PlayerAudience;
|
||||||
import org.geysermc.floodgate.player.UserAudienceArgument;
|
import org.geysermc.floodgate.player.UserAudienceArgument;
|
||||||
import org.geysermc.floodgate.util.Constants;
|
import org.geysermc.floodgate.util.Constants;
|
||||||
|
import org.geysermc.floodgate.util.Permissions;
|
||||||
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public final class LinkAccountCommand implements FloodgateCommand {
|
public final class LinkAccountCommand implements FloodgateCommand {
|
||||||
@@ -59,7 +60,7 @@ public final class LinkAccountCommand implements FloodgateCommand {
|
|||||||
return commandManager.commandBuilder("linkaccount",
|
return commandManager.commandBuilder("linkaccount",
|
||||||
ArgumentDescription.of("Link your Java account with your Bedrock account"))
|
ArgumentDescription.of("Link your Java account with your Bedrock account"))
|
||||||
.senderType(PlayerAudience.class)
|
.senderType(PlayerAudience.class)
|
||||||
.permission("floodgate.command.linkaccount")
|
.permission(Permissions.COMMAND_LINK.get())
|
||||||
.argument(UserAudienceArgument.of("player", true))
|
.argument(UserAudienceArgument.of("player", true))
|
||||||
.argument(StringArgument.optional("code"))
|
.argument(StringArgument.optional("code"))
|
||||||
.handler(this::execute)
|
.handler(this::execute)
|
||||||
@@ -165,7 +166,7 @@ public final class LinkAccountCommand implements FloodgateCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public enum Message implements CommandMessage {
|
public enum Message implements TranslatableMessage {
|
||||||
ALREADY_LINKED("floodgate.command.link_account.already_linked"),
|
ALREADY_LINKED("floodgate.command.link_account.already_linked"),
|
||||||
JAVA_USAGE("floodgate.command.link_account.java_usage"),
|
JAVA_USAGE("floodgate.command.link_account.java_usage"),
|
||||||
LINK_REQUEST_CREATED("floodgate.command.link_account.link_request_created"),
|
LINK_REQUEST_CREATED("floodgate.command.link_account.link_request_created"),
|
||||||
|
|||||||
@@ -38,11 +38,12 @@ import org.geysermc.floodgate.api.FloodgateApi;
|
|||||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.link.GlobalPlayerLinking;
|
import org.geysermc.floodgate.link.GlobalPlayerLinking;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
|
||||||
import org.geysermc.floodgate.platform.command.FloodgateCommand;
|
import org.geysermc.floodgate.platform.command.FloodgateCommand;
|
||||||
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
import org.geysermc.floodgate.player.UserAudience;
|
import org.geysermc.floodgate.player.UserAudience;
|
||||||
import org.geysermc.floodgate.player.UserAudience.PlayerAudience;
|
import org.geysermc.floodgate.player.UserAudience.PlayerAudience;
|
||||||
import org.geysermc.floodgate.util.Constants;
|
import org.geysermc.floodgate.util.Constants;
|
||||||
|
import org.geysermc.floodgate.util.Permissions;
|
||||||
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public final class UnlinkAccountCommand implements FloodgateCommand {
|
public final class UnlinkAccountCommand implements FloodgateCommand {
|
||||||
@@ -53,7 +54,7 @@ public final class UnlinkAccountCommand implements FloodgateCommand {
|
|||||||
return commandManager.commandBuilder("unlinkaccount",
|
return commandManager.commandBuilder("unlinkaccount",
|
||||||
ArgumentDescription.of("Unlink your Java account from your Bedrock account"))
|
ArgumentDescription.of("Unlink your Java account from your Bedrock account"))
|
||||||
.senderType(PlayerAudience.class)
|
.senderType(PlayerAudience.class)
|
||||||
.permission("floodgate.command.unlinkaccount")
|
.permission(Permissions.COMMAND_UNLINK.get())
|
||||||
.handler(this::execute)
|
.handler(this::execute)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,7 @@ public final class UnlinkAccountCommand implements FloodgateCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public enum Message implements CommandMessage {
|
public enum Message implements TranslatableMessage {
|
||||||
NOT_LINKED("floodgate.command.unlink_account.not_linked"),
|
NOT_LINKED("floodgate.command.unlink_account.not_linked"),
|
||||||
UNLINK_SUCCESS("floodgate.command.unlink_account.unlink_success"),
|
UNLINK_SUCCESS("floodgate.command.unlink_account.unlink_success"),
|
||||||
UNLINK_ERROR("floodgate.command.unlink_account.error " + CHECK_CONSOLE);
|
UNLINK_ERROR("floodgate.command.unlink_account.error " + CHECK_CONSOLE);
|
||||||
|
|||||||
@@ -37,13 +37,14 @@ import lombok.Getter;
|
|||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
|
||||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||||
import org.geysermc.floodgate.platform.command.FloodgateCommand;
|
import org.geysermc.floodgate.platform.command.FloodgateCommand;
|
||||||
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
import org.geysermc.floodgate.player.UserAudience;
|
import org.geysermc.floodgate.player.UserAudience;
|
||||||
import org.geysermc.floodgate.player.UserAudienceArgument;
|
import org.geysermc.floodgate.player.UserAudienceArgument;
|
||||||
import org.geysermc.floodgate.util.Constants;
|
import org.geysermc.floodgate.util.Constants;
|
||||||
import org.geysermc.floodgate.util.HttpUtils;
|
import org.geysermc.floodgate.util.HttpUtils;
|
||||||
|
import org.geysermc.floodgate.util.Permissions;
|
||||||
|
|
||||||
public class WhitelistCommand implements FloodgateCommand {
|
public class WhitelistCommand implements FloodgateCommand {
|
||||||
@Inject private FloodgateConfig config;
|
@Inject private FloodgateConfig config;
|
||||||
@@ -53,7 +54,7 @@ public class WhitelistCommand implements FloodgateCommand {
|
|||||||
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
||||||
Command.Builder<UserAudience> builder = commandManager.commandBuilder("fwhitelist",
|
Command.Builder<UserAudience> builder = commandManager.commandBuilder("fwhitelist",
|
||||||
ArgumentDescription.of("Easy way to whitelist Bedrock players"))
|
ArgumentDescription.of("Easy way to whitelist Bedrock players"))
|
||||||
.permission("floodgate.command.fwhitelist");
|
.permission(Permissions.COMMAND_WHITELIST.get());
|
||||||
|
|
||||||
commandManager.command(builder
|
commandManager.command(builder
|
||||||
.literal("add", "a")
|
.literal("add", "a")
|
||||||
@@ -153,7 +154,7 @@ public class WhitelistCommand implements FloodgateCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public enum Message implements CommandMessage {
|
public enum Message implements TranslatableMessage {
|
||||||
INVALID_USERNAME("floodgate.command.fwhitelist.invalid_username"),
|
INVALID_USERNAME("floodgate.command.fwhitelist.invalid_username"),
|
||||||
API_UNAVAILABLE("floodgate.command.fwhitelist.api_unavailable " + CHECK_CONSOLE),
|
API_UNAVAILABLE("floodgate.command.fwhitelist.api_unavailable " + CHECK_CONSOLE),
|
||||||
USER_NOT_FOUND("floodgate.command.fwhitelist.user_not_found"),
|
USER_NOT_FOUND("floodgate.command.fwhitelist.user_not_found"),
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
package org.geysermc.floodgate.link;
|
package org.geysermc.floodgate.link;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Key;
|
||||||
|
import com.google.inject.name.Names;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@@ -91,6 +93,11 @@ public abstract class CommonPlayerLink implements PlayerLink {
|
|||||||
return injectorHolder.get().getInstance(DatabaseConfigLoader.class).loadAs(configClass);
|
return injectorHolder.get().getInstance(DatabaseConfigLoader.class).loadAs(configClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return injectorHolder.get().getInstance(Key.get(String.class, Names.named("databaseName")));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
executorService.shutdown();
|
executorService.shutdown();
|
||||||
|
|||||||
@@ -90,6 +90,11 @@ final class DisabledPlayerLink implements PlayerLink {
|
|||||||
return failedFuture();
|
return failedFuture();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
import org.geysermc.floodgate.api.link.LinkRequestResult;
|
import org.geysermc.floodgate.api.link.LinkRequestResult;
|
||||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||||
import org.geysermc.floodgate.util.HttpUtils;
|
import org.geysermc.floodgate.util.HttpUtils;
|
||||||
import org.geysermc.floodgate.util.HttpUtils.HttpResponse;
|
import org.geysermc.floodgate.util.HttpUtils.DefaultHttpResponse;
|
||||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||||
import org.geysermc.floodgate.util.Utils;
|
import org.geysermc.floodgate.util.Utils;
|
||||||
|
|
||||||
@@ -55,6 +55,15 @@ public class GlobalPlayerLinking extends CommonPlayerLink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
if (databaseImpl != null) {
|
||||||
|
return databaseImpl.getName();
|
||||||
|
}
|
||||||
|
// Global Linking is integrated
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
super.stop();
|
super.stop();
|
||||||
@@ -82,7 +91,7 @@ public class GlobalPlayerLinking extends CommonPlayerLink {
|
|||||||
private CompletableFuture<LinkedPlayer> getLinkedPlayer0(@NonNull UUID bedrockId) {
|
private CompletableFuture<LinkedPlayer> getLinkedPlayer0(@NonNull UUID bedrockId) {
|
||||||
return CompletableFuture.supplyAsync(
|
return CompletableFuture.supplyAsync(
|
||||||
() -> {
|
() -> {
|
||||||
HttpResponse response =
|
DefaultHttpResponse response =
|
||||||
HttpUtils.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits());
|
HttpUtils.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits());
|
||||||
|
|
||||||
// both on code != 200 and fails with 200 'success' will be false
|
// both on code != 200 and fails with 200 'success' will be false
|
||||||
@@ -128,7 +137,7 @@ public class GlobalPlayerLinking extends CommonPlayerLink {
|
|||||||
private CompletableFuture<Boolean> isLinkedPlayer0(@NonNull UUID bedrockId) {
|
private CompletableFuture<Boolean> isLinkedPlayer0(@NonNull UUID bedrockId) {
|
||||||
return CompletableFuture.supplyAsync(
|
return CompletableFuture.supplyAsync(
|
||||||
() -> {
|
() -> {
|
||||||
HttpResponse response =
|
DefaultHttpResponse response =
|
||||||
HttpUtils.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits());
|
HttpUtils.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits());
|
||||||
|
|
||||||
// both on http != 200 and fails with 200 success will be false
|
// both on http != 200 and fails with 200 success will be false
|
||||||
|
|||||||
@@ -34,9 +34,11 @@ import java.nio.file.Path;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.geysermc.floodgate.addon.data.HandshakeHandlersImpl;
|
import org.geysermc.floodgate.addon.data.HandshakeHandlersImpl;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
|
import org.geysermc.floodgate.api.InstanceHolder;
|
||||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||||
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
||||||
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
||||||
|
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.api.packet.PacketHandlers;
|
import org.geysermc.floodgate.api.packet.PacketHandlers;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
@@ -52,7 +54,9 @@ import org.geysermc.floodgate.crypto.Base64Topping;
|
|||||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||||
import org.geysermc.floodgate.crypto.KeyProducer;
|
import org.geysermc.floodgate.crypto.KeyProducer;
|
||||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||||
|
import org.geysermc.floodgate.news.NewsChecker;
|
||||||
import org.geysermc.floodgate.packet.PacketHandlersImpl;
|
import org.geysermc.floodgate.packet.PacketHandlersImpl;
|
||||||
|
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
||||||
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
||||||
import org.geysermc.floodgate.skin.SkinApplier;
|
import org.geysermc.floodgate.skin.SkinApplier;
|
||||||
@@ -169,6 +173,15 @@ public class CommonModule extends AbstractModule {
|
|||||||
return new SkinUploadManager(api, skinApplier, logger);
|
return new SkinUploadManager(api, skinApplier, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public NewsChecker newsChecker(CommandUtil commandUtil, FloodgateLogger logger) {
|
||||||
|
// will be loaded after enabling, so we can use the link instance in InstanceHolder
|
||||||
|
PlayerLink link = InstanceHolder.getPlayerLink();
|
||||||
|
logger.info(link.getName());
|
||||||
|
return new NewsChecker(link, commandUtil, logger, null, -1);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named("kickMessageAttribute")
|
@Named("kickMessageAttribute")
|
||||||
|
|||||||
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Floodgate
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.floodgate.news;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||||
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
|
import org.geysermc.floodgate.news.data.BuildSpecificData;
|
||||||
|
import org.geysermc.floodgate.news.data.CheckAfterData;
|
||||||
|
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||||
|
import org.geysermc.floodgate.util.Constants;
|
||||||
|
import org.geysermc.floodgate.util.HttpUtils;
|
||||||
|
import org.geysermc.floodgate.util.HttpUtils.HttpResponse;
|
||||||
|
import org.geysermc.floodgate.util.Permissions;
|
||||||
|
|
||||||
|
public class NewsChecker {
|
||||||
|
private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
|
||||||
|
private final PlayerLink link;
|
||||||
|
private final CommandUtil commandUtil;
|
||||||
|
private final FloodgateLogger logger;
|
||||||
|
|
||||||
|
private final Map<Integer, NewsItem> activeNewsItems = new HashMap<>();
|
||||||
|
private final String branch;
|
||||||
|
private final int build;
|
||||||
|
|
||||||
|
private boolean firstCheck;
|
||||||
|
|
||||||
|
public NewsChecker(
|
||||||
|
PlayerLink link,
|
||||||
|
CommandUtil commandUtil,
|
||||||
|
FloodgateLogger logger,
|
||||||
|
String branch,
|
||||||
|
int build) {
|
||||||
|
this.link = link;
|
||||||
|
this.commandUtil = commandUtil;
|
||||||
|
this.logger = logger;
|
||||||
|
this.branch = branch;
|
||||||
|
this.build = build;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
executorService.scheduleWithFixedDelay(this::checkNews, 0, 30, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void schedule(long delayMs) {
|
||||||
|
executorService.schedule(this::checkNews, delayMs, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkNews() {
|
||||||
|
HttpResponse<JsonArray> response =
|
||||||
|
HttpUtils.getSilent(Constants.NEWS_OVERVIEW_URL, JsonArray.class);
|
||||||
|
JsonArray array = response.getResponse();
|
||||||
|
|
||||||
|
// silent mode doesn't throw exceptions, so array will be null on failure
|
||||||
|
if (array == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (JsonElement newsItemElement : array) {
|
||||||
|
NewsItem newsItem = NewsItem.readItem(newsItemElement.getAsJsonObject());
|
||||||
|
if (newsItem != null) {
|
||||||
|
addNews(newsItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
firstCheck = false;
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (logger.isDebug()) {
|
||||||
|
logger.error("Error while reading news item", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleNews(Object player, NewsItemAction action) {
|
||||||
|
for (NewsItem news : getActiveNews(action)) {
|
||||||
|
handleNewsItem(player, news, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNewsItem(Object player, NewsItem news, NewsItemAction action) {
|
||||||
|
switch (action) {
|
||||||
|
case ON_SERVER_STARTED:
|
||||||
|
if (!firstCheck) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case BROADCAST_TO_CONSOLE:
|
||||||
|
logger.info(news.getMessage());
|
||||||
|
break;
|
||||||
|
case ON_OPERATOR_JOIN:
|
||||||
|
if (player == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandUtil.hasPermission(player, Permissions.NEWS_RECEIVE.get())) {
|
||||||
|
String message = Constants.COLOR_CHAR + "a " + news.getMessage();
|
||||||
|
commandUtil.sendMessage(player, message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BROADCAST_TO_OPERATORS:
|
||||||
|
Collection<Object> onlinePlayers = commandUtil.getOnlinePlayersWithPermission(
|
||||||
|
Permissions.NEWS_RECEIVE.get()
|
||||||
|
);
|
||||||
|
|
||||||
|
for (Object onlinePlayer : onlinePlayers) {
|
||||||
|
String message = Constants.COLOR_CHAR + "a " + news.getMessage();
|
||||||
|
commandUtil.sendMessage(onlinePlayer, message);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<NewsItem> getActiveNews() {
|
||||||
|
return activeNewsItems.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<NewsItem> getActiveNews(NewsItemAction action) {
|
||||||
|
List<NewsItem> news = new ArrayList<>();
|
||||||
|
for (NewsItem item : getActiveNews()) {
|
||||||
|
if (item.getActions().contains(action)) {
|
||||||
|
news.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return news;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNews(NewsItem item) {
|
||||||
|
if (activeNewsItems.containsKey(item.getId())) {
|
||||||
|
if (!item.isActive()) {
|
||||||
|
activeNewsItems.remove(item.getId());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!item.isActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!item.isGlobal() && !Constants.NEWS_PROJECT_NAME.equals(item.getProject())) {
|
||||||
|
// only non-integrated database types have a name
|
||||||
|
if (link.getName() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String fullDatabaseName = Constants.NEWS_PROJECT_NAME + link.getName();
|
||||||
|
if (!fullDatabaseName.equals(item.getProject())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (item.getType()) {
|
||||||
|
case BUILD_SPECIFIC:
|
||||||
|
if (!item.getDataAs(BuildSpecificData.class).isAffected(branch, build)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CHECK_AFTER:
|
||||||
|
long checkAfter = item.getDataAs(CheckAfterData.class).getCheckAfter();
|
||||||
|
long delayMs = System.currentTimeMillis() - checkAfter;
|
||||||
|
schedule(delayMs > 0 ? delayMs : 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
activeNewsItems.put(item.getId(), item);
|
||||||
|
activateNews(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void activateNews(NewsItem item) {
|
||||||
|
for (NewsItemAction action : item.getActions()) {
|
||||||
|
handleNewsItem(null, item, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
executorService.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,25 +50,51 @@ public interface CommandUtil {
|
|||||||
@NonNull Collection<String> getOnlineUsernames(final @NonNull PlayerType limitTo);
|
@NonNull Collection<String> getOnlineUsernames(final @NonNull PlayerType limitTo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a message to the specified target, no matter what platform Floodgate is running on.
|
* Checks if the given player has the given permission.
|
||||||
*
|
*
|
||||||
* @param target the target to send the message to
|
* @param player the player to check
|
||||||
* @param message the command message
|
* @param permission the permission to check
|
||||||
* @param locale the locale of the player
|
* @return true or false depending on if the player has the permission
|
||||||
* @param args the arguments
|
|
||||||
*/
|
*/
|
||||||
void sendMessage(Object target, String locale, CommandMessage message, Object... args);
|
boolean hasPermission(Object player, String permission);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link CommandUtil#sendMessage(Object, String, CommandMessage, Object...)} except it
|
* Get all online players with the given permission.
|
||||||
* kicks the player.
|
|
||||||
*
|
*
|
||||||
* @param player the player to send the message to
|
* @param permission the permission to check
|
||||||
|
* @return a list of online players that have the given permission
|
||||||
|
*/
|
||||||
|
Collection<Object> getOnlinePlayersWithPermission(String permission);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to the specified target, no matter what platform Floodgate is running on.
|
||||||
|
*
|
||||||
|
* @param target the player that should receive the message
|
||||||
* @param message the command message
|
* @param message the command message
|
||||||
* @param locale the locale of the player
|
* @param locale the locale of the player
|
||||||
* @param args the arguments
|
* @param args the arguments
|
||||||
*/
|
*/
|
||||||
void kickPlayer(Object player, String locale, CommandMessage message, Object... args);
|
void sendMessage(Object target, String locale, TranslatableMessage message, Object... args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a raw message to the specified target, no matter what platform Floodgate is running
|
||||||
|
* on.
|
||||||
|
*
|
||||||
|
* @param target the player that should receive the message
|
||||||
|
* @param message the message
|
||||||
|
*/
|
||||||
|
void sendMessage(Object target, String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link CommandUtil#sendMessage(Object, String, TranslatableMessage, Object...)}
|
||||||
|
* except it kicks the player using the given message as the kick reason.
|
||||||
|
*
|
||||||
|
* @param player the player that should be kicked
|
||||||
|
* @param message the command message
|
||||||
|
* @param locale the locale of the player
|
||||||
|
* @param args the arguments
|
||||||
|
*/
|
||||||
|
void kickPlayer(Object player, String locale, TranslatableMessage message, Object... args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whitelist the given Bedrock player.
|
* Whitelist the given Bedrock player.
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ package org.geysermc.floodgate.platform.command;
|
|||||||
import org.geysermc.floodgate.util.LanguageManager;
|
import org.geysermc.floodgate.util.LanguageManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CommandMessage is the interface of a message that can be send to a command source after executing
|
* TranslatableMessage is the interface for a message that can be translated.
|
||||||
* a command. Messages are generally implemented using enums.
|
* Messages are generally implemented using enums.
|
||||||
*/
|
*/
|
||||||
public interface CommandMessage {
|
public interface TranslatableMessage {
|
||||||
/**
|
/**
|
||||||
* Returns the message attached to the enum identifier
|
* Returns the message attached to the enum identifier
|
||||||
*/
|
*/
|
||||||
@@ -26,8 +26,8 @@
|
|||||||
package org.geysermc.floodgate.platform.util;
|
package org.geysermc.floodgate.platform.util;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
|
||||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||||
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
|
|
||||||
public interface PlatformUtils {
|
public interface PlatformUtils {
|
||||||
/**
|
/**
|
||||||
@@ -38,10 +38,10 @@ public interface PlatformUtils {
|
|||||||
* @param locale the locale of the player
|
* @param locale the locale of the player
|
||||||
* @param args the arguments
|
* @param args the arguments
|
||||||
*/
|
*/
|
||||||
void sendMessage(Object player, String locale, CommandMessage message, Object... args);
|
void sendMessage(Object player, String locale, TranslatableMessage message, Object... args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link CommandUtil#sendMessage(Object, String, CommandMessage, Object...)} except it
|
* Same as {@link CommandUtil#sendMessage(Object, String, TranslatableMessage, Object...)} except it
|
||||||
* kicks the player.
|
* kicks the player.
|
||||||
*
|
*
|
||||||
* @param player the player to send the message to
|
* @param player the player to send the message to
|
||||||
@@ -49,7 +49,7 @@ public interface PlatformUtils {
|
|||||||
* @param locale the locale of the player
|
* @param locale the locale of the player
|
||||||
* @param args the arguments
|
* @param args the arguments
|
||||||
*/
|
*/
|
||||||
void kickPlayer(Object player, String locale, CommandMessage message, Object... args);
|
void kickPlayer(Object player, String locale, TranslatableMessage message, Object... args);
|
||||||
|
|
||||||
Collection<String> getOnlineUsernames(PlayerType limitTo);
|
Collection<String> getOnlineUsernames(PlayerType limitTo);
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import net.kyori.adventure.identity.Identified;
|
|||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
|
|
||||||
public interface UserAudience extends Identified, Identity, Audience {
|
public interface UserAudience extends Identified, Identity, Audience {
|
||||||
@Override
|
@Override
|
||||||
@@ -51,11 +51,11 @@ public interface UserAudience extends Identified, Identity, Audience {
|
|||||||
final @NonNull Component message,
|
final @NonNull Component message,
|
||||||
final @NonNull MessageType type);
|
final @NonNull MessageType type);
|
||||||
|
|
||||||
void sendMessage(CommandMessage message, Object... args);
|
void sendMessage(TranslatableMessage message, Object... args);
|
||||||
|
|
||||||
void disconnect(@NonNull final Component reason);
|
void disconnect(@NonNull final Component reason);
|
||||||
|
|
||||||
void disconnect(CommandMessage message, Object... args);
|
void disconnect(TranslatableMessage message, Object... args);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default @NonNull Identity identity() {
|
default @NonNull Identity identity() {
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
package org.geysermc.floodgate.util;
|
package org.geysermc.floodgate.util;
|
||||||
|
|
||||||
public final class Constants {
|
public final class Constants {
|
||||||
|
public static final char COLOR_CHAR = '§';
|
||||||
|
|
||||||
public static final boolean DEBUG_MODE = true;
|
public static final boolean DEBUG_MODE = true;
|
||||||
public static final boolean PRINT_ALL_PACKETS = false;
|
public static final boolean PRINT_ALL_PACKETS = false;
|
||||||
|
|
||||||
@@ -36,9 +38,12 @@ public final class Constants {
|
|||||||
public static final String WEBSOCKET_URL = "ws" + API_BASE_URL + "/ws";
|
public static final String WEBSOCKET_URL = "ws" + API_BASE_URL + "/ws";
|
||||||
public static final String GET_XUID_URL = "http" + API_BASE_URL + "/v1/xbox/xuid/";
|
public static final String GET_XUID_URL = "http" + API_BASE_URL + "/v1/xbox/xuid/";
|
||||||
public static final String GET_GAMERTAG_URL = "http" + API_BASE_URL + "/v1/xbox/gamertag/";
|
public static final String GET_GAMERTAG_URL = "http" + API_BASE_URL + "/v1/xbox/gamertag/";
|
||||||
|
public static final String NEWS_OVERVIEW_URL = "http" + API_BASE_URL + "/v1/news";
|
||||||
|
|
||||||
public static final String LINK_INFO_URL = "https://link.geysermc.org/";
|
public static final String LINK_INFO_URL = "https://link.geysermc.org/";
|
||||||
|
|
||||||
|
public static final String NEWS_PROJECT_NAME = "floodgate";
|
||||||
|
|
||||||
|
|
||||||
public static final String NTP_SERVER = "time.cloudflare.com";
|
public static final String NTP_SERVER = "time.cloudflare.com";
|
||||||
public static final String TIMESTAMP_DENIED_MESSAGE =
|
public static final String TIMESTAMP_DENIED_MESSAGE =
|
||||||
|
|||||||
@@ -48,13 +48,21 @@ public class HttpUtils {
|
|||||||
private static final String BOUNDARY = "******";
|
private static final String BOUNDARY = "******";
|
||||||
private static final String END = "\r\n";
|
private static final String END = "\r\n";
|
||||||
|
|
||||||
public static CompletableFuture<HttpResponse> asyncGet(String urlString) {
|
public static CompletableFuture<DefaultHttpResponse> asyncGet(String urlString) {
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
return get(urlString);
|
return get(urlString);
|
||||||
}, EXECUTOR_SERVICE);
|
}, EXECUTOR_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HttpResponse get(String urlString) {
|
public static DefaultHttpResponse get(String urlString) {
|
||||||
|
return readDefaultResponse(request(urlString));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> HttpResponse<T> getSilent(String urlString, Class<T> clazz) {
|
||||||
|
return readResponseSilent(request(urlString), clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpURLConnection request(String urlString) {
|
||||||
HttpURLConnection connection;
|
HttpURLConnection connection;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -68,34 +76,37 @@ public class HttpUtils {
|
|||||||
connection.setRequestMethod("GET");
|
connection.setRequestMethod("GET");
|
||||||
connection.setUseCaches(false);
|
connection.setUseCaches(false);
|
||||||
connection.setRequestProperty("User-Agent", USER_AGENT);
|
connection.setRequestProperty("User-Agent", USER_AGENT);
|
||||||
connection.setRequestProperty("ContentType", "application/json");
|
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
throw new RuntimeException("Failed to create request", exception);
|
throw new RuntimeException("Failed to create request", exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
return readResponse(connection);
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HttpResponse readResponse(HttpURLConnection connection) {
|
private static <T> HttpResponse<T> readResponseSilent(HttpURLConnection connection, Class<T> clazz) {
|
||||||
InputStream stream = null;
|
InputStreamReader streamReader = createReader(connection);
|
||||||
try {
|
|
||||||
stream = connection.getInputStream();
|
|
||||||
} catch (Exception exception) {
|
|
||||||
try {
|
|
||||||
stream = connection.getErrorStream();
|
|
||||||
} catch (Exception exception1) {
|
|
||||||
throw new RuntimeException("Both the input and the error stream failed?!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InputStreamReader streamReader = new InputStreamReader(stream);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int responseCode = connection.getResponseCode();
|
int responseCode = connection.getResponseCode();
|
||||||
|
T response = GSON.fromJson(streamReader, clazz);
|
||||||
|
return new HttpResponse<>(responseCode, response);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
return new HttpResponse<>(-1, null);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
streamReader.close();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DefaultHttpResponse readDefaultResponse(HttpURLConnection connection) {
|
||||||
|
InputStreamReader streamReader = createReader(connection);
|
||||||
|
|
||||||
|
try {
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
JsonObject response = GSON.fromJson(streamReader, JsonObject.class);
|
JsonObject response = GSON.fromJson(streamReader, JsonObject.class);
|
||||||
|
return new DefaultHttpResponse(responseCode, response);
|
||||||
return new HttpResponse(responseCode, response);
|
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
throw new RuntimeException("Failed to read response", exception);
|
throw new RuntimeException("Failed to read response", exception);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -106,10 +117,30 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static InputStreamReader createReader(HttpURLConnection connection) {
|
||||||
|
InputStream stream = null;
|
||||||
|
try {
|
||||||
|
stream = connection.getInputStream();
|
||||||
|
} catch (Exception exception) {
|
||||||
|
try {
|
||||||
|
stream = connection.getErrorStream();
|
||||||
|
} catch (Exception exception1) {
|
||||||
|
throw new RuntimeException("Both the input and the error stream failed?!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new InputStreamReader(stream);
|
||||||
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
public static final class HttpResponse {
|
public static class HttpResponse<T> {
|
||||||
private final int httpCode;
|
private final int httpCode;
|
||||||
private final JsonObject response;
|
private final T response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class DefaultHttpResponse extends HttpResponse<JsonObject> {
|
||||||
|
private DefaultHttpResponse(int httpCode, JsonObject response) {
|
||||||
|
super(httpCode, response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Floodgate
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.floodgate.util;
|
||||||
|
|
||||||
|
public enum Permissions {
|
||||||
|
COMMAND_LINK("floodgate.command.linkaccount"),
|
||||||
|
COMMAND_UNLINK("floodgate.command.unlinkaccount"),
|
||||||
|
COMMAND_WHITELIST("floodgate.command.fwhitelist"),
|
||||||
|
|
||||||
|
NEWS_RECEIVE("floodgate.news.receive");
|
||||||
|
|
||||||
|
private final String permission;
|
||||||
|
|
||||||
|
Permissions(String permission) {
|
||||||
|
this.permission = permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get() {
|
||||||
|
return permission;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,7 +46,7 @@ public final class PrefixCheckTask {
|
|||||||
"**********************************\n" +
|
"**********************************\n" +
|
||||||
"* You specified an empty prefix in your Floodgate config for Bedrock players!\n" +
|
"* You specified an empty prefix in your Floodgate config for Bedrock players!\n" +
|
||||||
"* Should a Java player join and a Bedrock player join with the same username, unwanted results and conflicts will happen!\n" +
|
"* Should a Java player join and a Bedrock player join with the same username, unwanted results and conflicts will happen!\n" +
|
||||||
"* We strongly recommend using . as the prefix, but other alternatives that will not conflict include: *, - and +\n" +
|
"* We strongly recommend using . as the prefix, but other alternatives that will not conflict include: +, - and *\n" +
|
||||||
"**********************************");
|
"**********************************");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -54,9 +54,9 @@ public final class PrefixCheckTask {
|
|||||||
logger.warn(
|
logger.warn(
|
||||||
"\n" +
|
"\n" +
|
||||||
"**********************************\n" +
|
"**********************************\n" +
|
||||||
"The prefix you entered in your Floodgate config ({}) could lead to username conflicts!\n" +
|
"* The prefix you entered in your Floodgate config ({}) could lead to username conflicts!\n" +
|
||||||
"Should a Java player join with the username {}Notch, and a Bedrock player join as Notch (who will be given the name {}Notch), unwanted results will happen!\n" +
|
"* Should a Java player join with the username {}Notch, and a Bedrock player join as Notch (who will be given the name {}Notch), unwanted results will happen!\n" +
|
||||||
"We strongly recommend using . as the prefix, but other alternatives that will not conflict include: *, - and +\n" +
|
"* We strongly recommend using . as the prefix, but other alternatives that will not conflict include: +, - and *\n" +
|
||||||
"**********************************",
|
"**********************************",
|
||||||
config.getUsernamePrefix(), config.getUsernamePrefix(),
|
config.getUsernamePrefix(), config.getUsernamePrefix(),
|
||||||
config.getUsernamePrefix(), config.getUsernamePrefix());
|
config.getUsernamePrefix(), config.getUsernamePrefix());
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ package org.geysermc.floodgate.util;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -40,8 +41,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
|
||||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||||
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
import org.geysermc.floodgate.player.UserAudience;
|
import org.geysermc.floodgate.player.UserAudience;
|
||||||
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
|
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
|
||||||
import org.geysermc.floodgate.util.SpigotUserAudience.SpigotConsoleAudience;
|
import org.geysermc.floodgate.util.SpigotUserAudience.SpigotConsoleAudience;
|
||||||
@@ -136,12 +137,33 @@ public final class SpigotCommandUtil implements CommandUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(Object target, String locale, CommandMessage message, Object... args) {
|
public boolean hasPermission(Object player, String permission) {
|
||||||
((CommandSender) target).sendMessage(translateAndTransform(locale, message, args));
|
return cast(player).hasPermission(permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void kickPlayer(Object player, String locale, CommandMessage message, Object... args) {
|
public Collection<Object> getOnlinePlayersWithPermission(String permission) {
|
||||||
|
List<Object> players = new ArrayList<>();
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (hasPermission(player, permission)) {
|
||||||
|
players.add(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(Object target, String locale, TranslatableMessage message, Object... args) {
|
||||||
|
sendMessage(target, translateAndTransform(locale, message, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(Object target, String message) {
|
||||||
|
((CommandSender) target).sendMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void kickPlayer(Object player, String locale, TranslatableMessage message, Object... args) {
|
||||||
// Have to run this in the main thread so we don't get a `Asynchronous player kick!` error
|
// Have to run this in the main thread so we don't get a `Asynchronous player kick!` error
|
||||||
Bukkit.getScheduler().runTask(plugin,
|
Bukkit.getScheduler().runTask(plugin,
|
||||||
() -> cast(player).kickPlayer(translateAndTransform(locale, message, args)));
|
() -> cast(player).kickPlayer(translateAndTransform(locale, message, args)));
|
||||||
@@ -157,7 +179,7 @@ public final class SpigotCommandUtil implements CommandUtil {
|
|||||||
return WhitelistUtils.removePlayer(xuid, username);
|
return WhitelistUtils.removePlayer(xuid, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String translateAndTransform(String locale, CommandMessage message, Object... args) {
|
public String translateAndTransform(String locale, TranslatableMessage message, Object... args) {
|
||||||
// unlike others, Bukkit doesn't have to transform a message into another class.
|
// unlike others, Bukkit doesn't have to transform a message into another class.
|
||||||
return message.translateMessage(manager, locale, args);
|
return message.translateMessage(manager, locale, args);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
|||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
|
||||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||||
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
import org.geysermc.floodgate.player.UserAudience;
|
import org.geysermc.floodgate.player.UserAudience;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -82,7 +82,7 @@ public class SpigotUserAudience implements UserAudience, ForwardingAudience.Sing
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(CommandMessage message, Object... args) {
|
public void sendMessage(TranslatableMessage message, Object... args) {
|
||||||
commandUtil.sendMessage(source(), locale(), message, args);
|
commandUtil.sendMessage(source(), locale(), message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ public class SpigotUserAudience implements UserAudience, ForwardingAudience.Sing
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnect(CommandMessage message, Object... args) {
|
public void disconnect(TranslatableMessage message, Object... args) {
|
||||||
commandUtil.kickPlayer(source(), locale(), message, args);
|
commandUtil.kickPlayer(source(), locale(), message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ import net.kyori.adventure.audience.MessageType;
|
|||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
|
||||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||||
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public abstract class VelocityUserAudience implements UserAudience, ForwardingAudience.Single {
|
public abstract class VelocityUserAudience implements UserAudience, ForwardingAudience.Single {
|
||||||
@@ -78,7 +78,7 @@ public abstract class VelocityUserAudience implements UserAudience, ForwardingAu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(CommandMessage message, Object... args) {
|
public void sendMessage(TranslatableMessage message, Object... args) {
|
||||||
commandUtil.sendMessage(source(), locale(), message, args);
|
commandUtil.sendMessage(source(), locale(), message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ public abstract class VelocityUserAudience implements UserAudience, ForwardingAu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnect(CommandMessage message, Object... args) {
|
public void disconnect(TranslatableMessage message, Object... args) {
|
||||||
commandUtil.kickPlayer(source(), locale(), message, args);
|
commandUtil.kickPlayer(source(), locale(), message, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
@@ -39,8 +40,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
|
||||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||||
|
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||||
import org.geysermc.floodgate.player.UserAudience;
|
import org.geysermc.floodgate.player.UserAudience;
|
||||||
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
|
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
|
||||||
import org.geysermc.floodgate.player.VelocityUserAudience.VelocityConsoleAudience;
|
import org.geysermc.floodgate.player.VelocityUserAudience.VelocityConsoleAudience;
|
||||||
@@ -134,17 +135,40 @@ public final class VelocityCommandUtil implements CommandUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(Object target, String locale, CommandMessage message, Object... args) {
|
public boolean hasPermission(Object player, String permission) {
|
||||||
|
return cast(player).hasPermission(permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Object> getOnlinePlayersWithPermission(String permission) {
|
||||||
|
List<Object> players = new ArrayList<>();
|
||||||
|
for (Player player : server.getAllPlayers()) {
|
||||||
|
if (hasPermission(player, permission)) {
|
||||||
|
players.add(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(Object target, String locale, TranslatableMessage message, Object... args) {
|
||||||
((CommandSource) target).sendMessage(translateAndTransform(locale, message, args));
|
((CommandSource) target).sendMessage(translateAndTransform(locale, message, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void kickPlayer(Object player, String locale, CommandMessage message, Object... args) {
|
public void sendMessage(Object target, String message) {
|
||||||
|
((CommandSource) target).sendMessage(Component.text(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void kickPlayer(Object player, String locale, TranslatableMessage message, Object... args) {
|
||||||
cast(player).disconnect(translateAndTransform(locale, message, args));
|
cast(player).disconnect(translateAndTransform(locale, message, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component translateAndTransform(String locale, CommandMessage message,
|
public Component translateAndTransform(
|
||||||
Object... args) {
|
String locale,
|
||||||
|
TranslatableMessage message,
|
||||||
|
Object... args) {
|
||||||
return Component.text(message.translateMessage(manager, locale, args));
|
return Component.text(message.translateMessage(manager, locale, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user