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
|
||||
);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* '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.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -40,8 +41,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
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.TranslatableMessage;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
|
||||
import org.geysermc.floodgate.util.BungeeUserAudience.BungeeConsoleAudience;
|
||||
@@ -135,16 +136,39 @@ public final class BungeeCommandUtil implements CommandUtil {
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
|
||||
public BaseComponent[] translateAndTransform(String locale, CommandMessage message,
|
||||
public BaseComponent[] translateAndTransform(
|
||||
String locale,
|
||||
TranslatableMessage message,
|
||||
Object... 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.connection.ProxiedPlayer;
|
||||
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.TranslatableMessage;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@@ -74,13 +74,15 @@ public class BungeeUserAudience implements UserAudience, ForwardingAudience.Sing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(@NonNull Identity source, @NonNull Component message,
|
||||
public void sendMessage(
|
||||
@NonNull Identity source,
|
||||
@NonNull Component message,
|
||||
@NonNull MessageType type) {
|
||||
this.source.sendMessage(GsonComponentSerializer.gson().serialize(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(CommandMessage message, Object... args) {
|
||||
public void sendMessage(TranslatableMessage message, Object... args) {
|
||||
commandUtil.sendMessage(source(), locale(), message, args);
|
||||
}
|
||||
|
||||
@@ -92,7 +94,7 @@ public class BungeeUserAudience implements UserAudience, ForwardingAudience.Sing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(CommandMessage message, Object... args) {
|
||||
public void disconnect(TranslatableMessage message, Object... 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.module.ConfigLoadedModule;
|
||||
import org.geysermc.floodgate.module.PostInitializeModule;
|
||||
import org.geysermc.floodgate.news.NewsChecker;
|
||||
import org.geysermc.floodgate.util.PrefixCheckTask;
|
||||
import org.geysermc.floodgate.util.TimeSyncerHolder;
|
||||
|
||||
@@ -123,6 +124,7 @@ public class FloodgatePlatform {
|
||||
|
||||
PrefixCheckTask.checkAndExecuteDelayed(config, logger);
|
||||
|
||||
guice.getInstance(NewsChecker.class).start();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ package org.geysermc.floodgate.addon.debug;
|
||||
public enum State {
|
||||
HANDSHAKE, STATUS, LOGIN, PLAY;
|
||||
|
||||
public static final State[] VALUES = values();
|
||||
private static final State[] VALUES = values();
|
||||
|
||||
public static State getById(int id) {
|
||||
return id < VALUES.length ? VALUES[id] : null;
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
package org.geysermc.floodgate.command;
|
||||
|
||||
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
|
||||
* used'
|
||||
*/
|
||||
@Getter
|
||||
public enum CommonCommandMessage implements CommandMessage {
|
||||
public enum CommonCommandMessage implements TranslatableMessage {
|
||||
LINKING_DISABLED("floodgate.commands.linking_disabled"),
|
||||
NOT_A_PLAYER("floodgate.commands.not_a_player"),
|
||||
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.config.FloodgateConfig;
|
||||
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.TranslatableMessage;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
import org.geysermc.floodgate.player.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.player.UserAudienceArgument;
|
||||
import org.geysermc.floodgate.util.Constants;
|
||||
import org.geysermc.floodgate.util.Permissions;
|
||||
|
||||
@NoArgsConstructor
|
||||
public final class LinkAccountCommand implements FloodgateCommand {
|
||||
@@ -59,7 +60,7 @@ public final class LinkAccountCommand implements FloodgateCommand {
|
||||
return commandManager.commandBuilder("linkaccount",
|
||||
ArgumentDescription.of("Link your Java account with your Bedrock account"))
|
||||
.senderType(PlayerAudience.class)
|
||||
.permission("floodgate.command.linkaccount")
|
||||
.permission(Permissions.COMMAND_LINK.get())
|
||||
.argument(UserAudienceArgument.of("player", true))
|
||||
.argument(StringArgument.optional("code"))
|
||||
.handler(this::execute)
|
||||
@@ -165,7 +166,7 @@ public final class LinkAccountCommand implements FloodgateCommand {
|
||||
}
|
||||
|
||||
@Getter
|
||||
public enum Message implements CommandMessage {
|
||||
public enum Message implements TranslatableMessage {
|
||||
ALREADY_LINKED("floodgate.command.link_account.already_linked"),
|
||||
JAVA_USAGE("floodgate.command.link_account.java_usage"),
|
||||
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.config.FloodgateConfig;
|
||||
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.TranslatableMessage;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
import org.geysermc.floodgate.player.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.util.Constants;
|
||||
import org.geysermc.floodgate.util.Permissions;
|
||||
|
||||
@NoArgsConstructor
|
||||
public final class UnlinkAccountCommand implements FloodgateCommand {
|
||||
@@ -53,7 +54,7 @@ public final class UnlinkAccountCommand implements FloodgateCommand {
|
||||
return commandManager.commandBuilder("unlinkaccount",
|
||||
ArgumentDescription.of("Unlink your Java account from your Bedrock account"))
|
||||
.senderType(PlayerAudience.class)
|
||||
.permission("floodgate.command.unlinkaccount")
|
||||
.permission(Permissions.COMMAND_UNLINK.get())
|
||||
.handler(this::execute)
|
||||
.build();
|
||||
}
|
||||
@@ -113,7 +114,7 @@ public final class UnlinkAccountCommand implements FloodgateCommand {
|
||||
}
|
||||
|
||||
@Getter
|
||||
public enum Message implements CommandMessage {
|
||||
public enum Message implements TranslatableMessage {
|
||||
NOT_LINKED("floodgate.command.unlink_account.not_linked"),
|
||||
UNLINK_SUCCESS("floodgate.command.unlink_account.unlink_success"),
|
||||
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.config.FloodgateConfig;
|
||||
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.FloodgateCommand;
|
||||
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
import org.geysermc.floodgate.player.UserAudienceArgument;
|
||||
import org.geysermc.floodgate.util.Constants;
|
||||
import org.geysermc.floodgate.util.HttpUtils;
|
||||
import org.geysermc.floodgate.util.Permissions;
|
||||
|
||||
public class WhitelistCommand implements FloodgateCommand {
|
||||
@Inject private FloodgateConfig config;
|
||||
@@ -53,7 +54,7 @@ public class WhitelistCommand implements FloodgateCommand {
|
||||
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
||||
Command.Builder<UserAudience> builder = commandManager.commandBuilder("fwhitelist",
|
||||
ArgumentDescription.of("Easy way to whitelist Bedrock players"))
|
||||
.permission("floodgate.command.fwhitelist");
|
||||
.permission(Permissions.COMMAND_WHITELIST.get());
|
||||
|
||||
commandManager.command(builder
|
||||
.literal("add", "a")
|
||||
@@ -153,7 +154,7 @@ public class WhitelistCommand implements FloodgateCommand {
|
||||
}
|
||||
|
||||
@Getter
|
||||
public enum Message implements CommandMessage {
|
||||
public enum Message implements TranslatableMessage {
|
||||
INVALID_USERNAME("floodgate.command.fwhitelist.invalid_username"),
|
||||
API_UNAVAILABLE("floodgate.command.fwhitelist.api_unavailable " + CHECK_CONSOLE),
|
||||
USER_NOT_FOUND("floodgate.command.fwhitelist.user_not_found"),
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
package org.geysermc.floodgate.link;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.name.Names;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -91,6 +93,11 @@ public abstract class CommonPlayerLink implements PlayerLink {
|
||||
return injectorHolder.get().getInstance(DatabaseConfigLoader.class).loadAs(configClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return injectorHolder.get().getInstance(Key.get(String.class, Names.named("databaseName")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
executorService.shutdown();
|
||||
|
||||
@@ -90,6 +90,11 @@ final class DisabledPlayerLink implements PlayerLink {
|
||||
return failedFuture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
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.PlayerLink;
|
||||
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.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
|
||||
public void stop() {
|
||||
super.stop();
|
||||
@@ -82,7 +91,7 @@ public class GlobalPlayerLinking extends CommonPlayerLink {
|
||||
private CompletableFuture<LinkedPlayer> getLinkedPlayer0(@NonNull UUID bedrockId) {
|
||||
return CompletableFuture.supplyAsync(
|
||||
() -> {
|
||||
HttpResponse response =
|
||||
DefaultHttpResponse response =
|
||||
HttpUtils.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits());
|
||||
|
||||
// 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) {
|
||||
return CompletableFuture.supplyAsync(
|
||||
() -> {
|
||||
HttpResponse response =
|
||||
DefaultHttpResponse response =
|
||||
HttpUtils.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits());
|
||||
|
||||
// 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 org.geysermc.floodgate.addon.data.HandshakeHandlersImpl;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.InstanceHolder;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
||||
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.packet.PacketHandlers;
|
||||
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.KeyProducer;
|
||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||
import org.geysermc.floodgate.news.NewsChecker;
|
||||
import org.geysermc.floodgate.packet.PacketHandlersImpl;
|
||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
||||
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
@@ -169,6 +173,15 @@ public class CommonModule extends AbstractModule {
|
||||
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
|
||||
@Singleton
|
||||
@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);
|
||||
|
||||
/**
|
||||
* 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 message the command message
|
||||
* @param locale the locale of the player
|
||||
* @param args the arguments
|
||||
* @param player the player to check
|
||||
* @param permission the permission to check
|
||||
* @return true or false depending on if the player has the permission
|
||||
*/
|
||||
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
|
||||
* kicks the player.
|
||||
* Get all online players with the given permission.
|
||||
*
|
||||
* @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 locale the locale of the player
|
||||
* @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.
|
||||
|
||||
@@ -28,10 +28,10 @@ package org.geysermc.floodgate.platform.command;
|
||||
import org.geysermc.floodgate.util.LanguageManager;
|
||||
|
||||
/**
|
||||
* CommandMessage is the interface of a message that can be send to a command source after executing
|
||||
* a command. Messages are generally implemented using enums.
|
||||
* TranslatableMessage is the interface for a message that can be translated.
|
||||
* Messages are generally implemented using enums.
|
||||
*/
|
||||
public interface CommandMessage {
|
||||
public interface TranslatableMessage {
|
||||
/**
|
||||
* Returns the message attached to the enum identifier
|
||||
*/
|
||||
@@ -26,8 +26,8 @@
|
||||
package org.geysermc.floodgate.platform.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.geysermc.floodgate.platform.command.CommandMessage;
|
||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.platform.command.TranslatableMessage;
|
||||
|
||||
public interface PlatformUtils {
|
||||
/**
|
||||
@@ -38,10 +38,10 @@ public interface PlatformUtils {
|
||||
* @param locale the locale of the player
|
||||
* @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.
|
||||
*
|
||||
* @param player the player to send the message to
|
||||
@@ -49,7 +49,7 @@ public interface PlatformUtils {
|
||||
* @param locale the locale of the player
|
||||
* @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);
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import net.kyori.adventure.identity.Identified;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import net.kyori.adventure.text.Component;
|
||||
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 {
|
||||
@Override
|
||||
@@ -51,11 +51,11 @@ public interface UserAudience extends Identified, Identity, Audience {
|
||||
final @NonNull Component message,
|
||||
final @NonNull MessageType type);
|
||||
|
||||
void sendMessage(CommandMessage message, Object... args);
|
||||
void sendMessage(TranslatableMessage message, Object... args);
|
||||
|
||||
void disconnect(@NonNull final Component reason);
|
||||
|
||||
void disconnect(CommandMessage message, Object... args);
|
||||
void disconnect(TranslatableMessage message, Object... args);
|
||||
|
||||
@Override
|
||||
default @NonNull Identity identity() {
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
package org.geysermc.floodgate.util;
|
||||
|
||||
public final class Constants {
|
||||
public static final char COLOR_CHAR = '§';
|
||||
|
||||
public static final boolean DEBUG_MODE = true;
|
||||
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 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 NEWS_OVERVIEW_URL = "http" + API_BASE_URL + "/v1/news";
|
||||
|
||||
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 TIMESTAMP_DENIED_MESSAGE =
|
||||
|
||||
@@ -48,13 +48,21 @@ public class HttpUtils {
|
||||
private static final String BOUNDARY = "******";
|
||||
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 get(urlString);
|
||||
}, 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;
|
||||
|
||||
try {
|
||||
@@ -68,34 +76,37 @@ public class HttpUtils {
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setUseCaches(false);
|
||||
connection.setRequestProperty("User-Agent", USER_AGENT);
|
||||
connection.setRequestProperty("ContentType", "application/json");
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException("Failed to create request", exception);
|
||||
}
|
||||
|
||||
return readResponse(connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
private static HttpResponse readResponse(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?!");
|
||||
}
|
||||
}
|
||||
|
||||
InputStreamReader streamReader = new InputStreamReader(stream);
|
||||
private static <T> HttpResponse<T> readResponseSilent(HttpURLConnection connection, Class<T> clazz) {
|
||||
InputStreamReader streamReader = createReader(connection);
|
||||
|
||||
try {
|
||||
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);
|
||||
|
||||
return new HttpResponse(responseCode, response);
|
||||
return new DefaultHttpResponse(responseCode, response);
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException("Failed to read response", exception);
|
||||
} 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
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static final class HttpResponse {
|
||||
public static class HttpResponse<T> {
|
||||
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" +
|
||||
"* 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" +
|
||||
"* 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;
|
||||
}
|
||||
@@ -54,9 +54,9 @@ public final class PrefixCheckTask {
|
||||
logger.warn(
|
||||
"\n" +
|
||||
"**********************************\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" +
|
||||
"We strongly recommend using . as the prefix, but other alternatives that will not conflict include: *, - and +\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" +
|
||||
"* 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());
|
||||
|
||||
@@ -28,6 +28,7 @@ package org.geysermc.floodgate.util;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -40,8 +41,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
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.TranslatableMessage;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
|
||||
import org.geysermc.floodgate.util.SpigotUserAudience.SpigotConsoleAudience;
|
||||
@@ -136,12 +137,33 @@ public final class SpigotCommandUtil implements CommandUtil {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Object target, String locale, CommandMessage message, Object... args) {
|
||||
((CommandSender) target).sendMessage(translateAndTransform(locale, message, args));
|
||||
public boolean hasPermission(Object player, String permission) {
|
||||
return cast(player).hasPermission(permission);
|
||||
}
|
||||
|
||||
@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
|
||||
Bukkit.getScheduler().runTask(plugin,
|
||||
() -> cast(player).kickPlayer(translateAndTransform(locale, message, args)));
|
||||
@@ -157,7 +179,7 @@ public final class SpigotCommandUtil implements CommandUtil {
|
||||
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.
|
||||
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.entity.Player;
|
||||
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.TranslatableMessage;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@@ -82,7 +82,7 @@ public class SpigotUserAudience implements UserAudience, ForwardingAudience.Sing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(CommandMessage message, Object... args) {
|
||||
public void sendMessage(TranslatableMessage message, Object... args) {
|
||||
commandUtil.sendMessage(source(), locale(), message, args);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ public class SpigotUserAudience implements UserAudience, ForwardingAudience.Sing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(CommandMessage message, Object... args) {
|
||||
public void disconnect(TranslatableMessage message, Object... 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.text.Component;
|
||||
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.TranslatableMessage;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class VelocityUserAudience implements UserAudience, ForwardingAudience.Single {
|
||||
@@ -78,7 +78,7 @@ public abstract class VelocityUserAudience implements UserAudience, ForwardingAu
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(CommandMessage message, Object... args) {
|
||||
public void sendMessage(TranslatableMessage message, Object... args) {
|
||||
commandUtil.sendMessage(source(), locale(), message, args);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ public abstract class VelocityUserAudience implements UserAudience, ForwardingAu
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(CommandMessage message, Object... args) {
|
||||
public void disconnect(TranslatableMessage message, Object... args) {
|
||||
commandUtil.kickPlayer(source(), locale(), message, args);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
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.geysermc.floodgate.api.FloodgateApi;
|
||||
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.TranslatableMessage;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
import org.geysermc.floodgate.player.UserAudienceArgument.PlayerType;
|
||||
import org.geysermc.floodgate.player.VelocityUserAudience.VelocityConsoleAudience;
|
||||
@@ -134,16 +135,39 @@ public final class VelocityCommandUtil implements CommandUtil {
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
|
||||
public Component translateAndTransform(String locale, CommandMessage message,
|
||||
public Component translateAndTransform(
|
||||
String locale,
|
||||
TranslatableMessage message,
|
||||
Object... args) {
|
||||
return Component.text(message.translateMessage(manager, locale, args));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user