mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2026-01-06 15:42:03 +00:00
Merge remote-tracking branch 'origin/development' into feature/geyser-merge
# Conflicts: # build-logic/src/main/kotlin/Versions.kt # bungee/src/main/java/org/geysermc/floodgate/listener/BungeeListener.java # bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeeSkinApplier.java # core/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java # core/src/main/java/org/geysermc/floodgate/api/SimpleFloodgateApi.java # core/src/main/java/org/geysermc/floodgate/api/legacy/PropertyGlue.java # core/src/main/java/org/geysermc/floodgate/module/CommonModule.java # core/src/main/java/org/geysermc/floodgate/pluginmessage/channel/SkinChannel.java # core/src/main/java/org/geysermc/floodgate/skin/SkinApplier.java # core/src/main/java/org/geysermc/floodgate/skin/SkinUploadManager.java # core/src/main/java/org/geysermc/floodgate/skin/SkinUploadSocket.java # core/src/main/java/org/geysermc/floodgate/util/Utils.java # spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java # velocity/src/main/java/org/geysermc/floodgate/util/VelocitySkinApplier.java
This commit is contained in:
@@ -37,6 +37,7 @@ import org.geysermc.api.Geyser;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.InstanceHolder;
|
||||
import org.geysermc.floodgate.api.event.FloodgateEventBus;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
||||
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||
@@ -44,8 +45,8 @@ import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.packet.PacketHandlers;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.event.EventBus;
|
||||
import org.geysermc.floodgate.event.PostEnableEvent;
|
||||
import org.geysermc.floodgate.event.ShutdownEvent;
|
||||
import org.geysermc.floodgate.event.lifecycle.PostEnableEvent;
|
||||
import org.geysermc.floodgate.event.lifecycle.ShutdownEvent;
|
||||
import org.geysermc.floodgate.module.PostEnableModules;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
@@ -71,6 +72,7 @@ public abstract class FloodgatePlatform {
|
||||
InstanceHolder.set(
|
||||
guice.getInstance(FloodgateApi.class),
|
||||
guice.getInstance(PlayerLink.class),
|
||||
guice.getInstance(FloodgateEventBus.class),
|
||||
injector,
|
||||
guice.getInstance(PacketHandlers.class),
|
||||
guice.getInstance(HandshakeHandlers.class),
|
||||
|
||||
@@ -29,10 +29,8 @@ import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@@ -51,7 +49,7 @@ import org.geysermc.floodgate.util.HttpClient;
|
||||
|
||||
@Singleton
|
||||
public class SimpleFloodgateApi implements GeyserApiBase {
|
||||
private final Map<UUID, Connection> players = new HashMap<>();
|
||||
private final Map<UUID, Connection> players = new ConcurrentHashMap<>();
|
||||
private final Cache<UUID, Connection> pendingRemove =
|
||||
CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(20, TimeUnit.SECONDS)
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.geysermc.floodgate.player.UserAudience;
|
||||
public final class MainCommand extends SubCommands implements FloodgateCommand {
|
||||
public MainCommand() {
|
||||
defineSubCommand(FirewallCheckSubcommand.class);
|
||||
defineSubCommand(VersionSubcommand.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 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.command.main;
|
||||
|
||||
import static org.geysermc.floodgate.util.Constants.COLOR_CHAR;
|
||||
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.inject.Inject;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.command.WhitelistCommand.Message;
|
||||
import org.geysermc.floodgate.command.util.Permission;
|
||||
import org.geysermc.floodgate.platform.command.FloodgateSubCommand;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
import org.geysermc.floodgate.util.Constants;
|
||||
import org.geysermc.floodgate.util.HttpClient;
|
||||
|
||||
public class VersionSubcommand extends FloodgateSubCommand {
|
||||
@Inject
|
||||
private HttpClient httpClient;
|
||||
|
||||
@Inject
|
||||
private FloodgateLogger logger;
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "version";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Displays version information about Floodgate";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Permission permission() {
|
||||
return Permission.COMMAND_MAIN_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandContext<UserAudience> context) {
|
||||
UserAudience sender = context.getSender();
|
||||
sender.sendMessage(String.format(
|
||||
COLOR_CHAR + "7You're currently on " + COLOR_CHAR + "b%s" +
|
||||
COLOR_CHAR + "7 (branch: " + COLOR_CHAR + "b%s" + COLOR_CHAR + "7)\n" +
|
||||
COLOR_CHAR + "eFetching latest build info...",
|
||||
Constants.VERSION, Constants.GIT_BRANCH
|
||||
));
|
||||
|
||||
String baseUrl = String.format(
|
||||
"https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/%s/lastSuccessfulBuild/",
|
||||
Constants.GIT_BRANCH
|
||||
);
|
||||
|
||||
httpClient.asyncGet(
|
||||
baseUrl + "buildNumber",
|
||||
JsonElement.class
|
||||
).whenComplete((result, error) -> {
|
||||
if (error != null) {
|
||||
sender.sendMessage(COLOR_CHAR + "cCould not retrieve latest version info!");
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
JsonElement response = result.getResponse();
|
||||
|
||||
logger.info(String.valueOf(response));
|
||||
logger.info("{}", result.getHttpCode());
|
||||
|
||||
if (result.getHttpCode() == 404) {
|
||||
sender.sendMessage(
|
||||
COLOR_CHAR + "cGot a 404 (not found) while requesting the latest version." +
|
||||
" Are you using a custom Floodgate version?"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.isCodeOk()) {
|
||||
//todo make it more generic instead of using a Whitelist command strings
|
||||
logger.error(
|
||||
"Got an error from requesting the latest Floodgate version: {}",
|
||||
response.toString()
|
||||
);
|
||||
sender.sendMessage(Message.UNEXPECTED_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
int buildNumber = response.getAsInt();
|
||||
|
||||
if (buildNumber > Constants.BUILD_NUMBER) {
|
||||
sender.sendMessage(String.format(
|
||||
COLOR_CHAR + "7There is a newer version of Floodgate available!\n" +
|
||||
COLOR_CHAR + "7You are " + COLOR_CHAR + "e%s " + COLOR_CHAR + "7builds behind.\n" +
|
||||
COLOR_CHAR + "7Download the latest Floodgate version here: " + COLOR_CHAR + "b%s",
|
||||
buildNumber - Constants.BUILD_NUMBER, baseUrl
|
||||
));
|
||||
return;
|
||||
}
|
||||
if (buildNumber == Constants.BUILD_NUMBER) {
|
||||
sender.sendMessage(COLOR_CHAR + "aYou're running the latest version of Floodgate!");
|
||||
return;
|
||||
}
|
||||
sender.sendMessage(COLOR_CHAR + "cCannot check version for custom Floodgate versions!");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import static org.geysermc.floodgate.command.util.PermissionDefault.TRUE;
|
||||
public enum Permission {
|
||||
COMMAND_MAIN("floodgate.command.floodgate", TRUE),
|
||||
COMMAND_MAIN_FIREWALL(COMMAND_MAIN, "firewall", OP),
|
||||
COMMAND_MAIN_VERSION(COMMAND_MAIN, "version", OP),
|
||||
COMMAND_LINK("floodgate.command.linkaccount", TRUE),
|
||||
COMMAND_UNLINK("floodgate.command.unlinkaccount", TRUE),
|
||||
COMMAND_WHITELIST("floodgate.command.fwhitelist", OP),
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.floodgate.event;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@@ -32,9 +33,13 @@ import org.geysermc.event.PostOrder;
|
||||
import org.geysermc.event.bus.impl.EventBusImpl;
|
||||
import org.geysermc.event.subscribe.Subscribe;
|
||||
import org.geysermc.event.subscribe.Subscriber;
|
||||
import org.geysermc.floodgate.api.event.FloodgateEventBus;
|
||||
import org.geysermc.floodgate.api.event.FloodgateSubscriber;
|
||||
|
||||
@Singleton
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class EventBus extends EventBusImpl<Object, EventSubscriber<?>> {
|
||||
public final class EventBus extends EventBusImpl<Object, FloodgateSubscriber<?>>
|
||||
implements FloodgateEventBus {
|
||||
@Override
|
||||
protected <H, T, B extends Subscriber<T>> B makeSubscription(
|
||||
@NonNull Class<T> eventClass,
|
||||
|
||||
@@ -30,8 +30,9 @@ import java.util.function.Consumer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.event.PostOrder;
|
||||
import org.geysermc.event.subscribe.impl.SubscriberImpl;
|
||||
import org.geysermc.floodgate.api.event.FloodgateSubscriber;
|
||||
|
||||
public final class EventSubscriber<E> extends SubscriberImpl<E> {
|
||||
public final class EventSubscriber<E> extends SubscriberImpl<E> implements FloodgateSubscriber<E> {
|
||||
EventSubscriber(
|
||||
@NonNull Class<E> eventClass,
|
||||
@NonNull Consumer<E> handler,
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
* @link https://github.com/GeyserMC/Floodgate
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.event;
|
||||
package org.geysermc.floodgate.event.lifecycle;
|
||||
|
||||
public class PostEnableEvent {
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
* @link https://github.com/GeyserMC/Floodgate
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.event;
|
||||
package org.geysermc.floodgate.event.lifecycle;
|
||||
|
||||
public class ShutdownEvent {
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 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.event.skin;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.event.util.AbstractCancellable;
|
||||
import org.geysermc.floodgate.api.event.skin.SkinApplyEvent;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
|
||||
public class SkinApplyEventImpl extends AbstractCancellable implements SkinApplyEvent {
|
||||
private final FloodgatePlayer player;
|
||||
private final SkinData currentSkin;
|
||||
private SkinData newSkin;
|
||||
|
||||
public SkinApplyEventImpl(
|
||||
@NonNull FloodgatePlayer player,
|
||||
@Nullable SkinData currentSkin,
|
||||
@NonNull SkinData newSkin
|
||||
) {
|
||||
this.player = Objects.requireNonNull(player);
|
||||
this.currentSkin = currentSkin;
|
||||
this.newSkin = Objects.requireNonNull(newSkin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull FloodgatePlayer player() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public @Nullable SkinData currentSkin() {
|
||||
return currentSkin;
|
||||
}
|
||||
|
||||
public @NonNull SkinData newSkin() {
|
||||
return newSkin;
|
||||
}
|
||||
|
||||
public SkinApplyEventImpl newSkin(@NonNull SkinData skinData) {
|
||||
this.newSkin = Objects.requireNonNull(skinData);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -26,18 +26,17 @@
|
||||
package org.geysermc.floodgate.inject;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import java.util.WeakHashMap;
|
||||
import org.geysermc.floodgate.api.inject.InjectorAddon;
|
||||
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
||||
|
||||
public abstract class CommonPlatformInjector implements PlatformInjector {
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private final Set<Channel> injectedClients = new HashSet<>();
|
||||
private final Set<Channel> injectedClients =
|
||||
Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap<>()));
|
||||
|
||||
private final Map<Class<?>, InjectorAddon> addons = new HashMap<>();
|
||||
|
||||
@@ -49,6 +48,10 @@ public abstract class CommonPlatformInjector implements PlatformInjector {
|
||||
return injectedClients.remove(channel);
|
||||
}
|
||||
|
||||
public Set<Channel> injectedClients() {
|
||||
return injectedClients;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAddon(InjectorAddon addon) {
|
||||
return addons.putIfAbsent(addon.getClass(), addon) == null;
|
||||
|
||||
@@ -43,7 +43,7 @@ import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.database.config.DatabaseConfig;
|
||||
import org.geysermc.floodgate.database.config.DatabaseConfigLoader;
|
||||
import org.geysermc.floodgate.event.ShutdownEvent;
|
||||
import org.geysermc.floodgate.event.lifecycle.ShutdownEvent;
|
||||
import org.geysermc.floodgate.util.InjectorHolder;
|
||||
|
||||
@Listener
|
||||
|
||||
@@ -51,7 +51,7 @@ import org.geysermc.floodgate.api.link.PlayerLink;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig.PlayerLinkConfig;
|
||||
import org.geysermc.floodgate.event.ShutdownEvent;
|
||||
import org.geysermc.floodgate.event.lifecycle.ShutdownEvent;
|
||||
import org.geysermc.floodgate.util.Constants;
|
||||
import org.geysermc.floodgate.util.InjectorHolder;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
|
||||
@@ -38,6 +38,7 @@ import io.netty.util.AttributeKey;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
@@ -45,6 +46,7 @@ import org.geysermc.event.PostOrder;
|
||||
import org.geysermc.floodgate.addon.data.HandshakeHandlersImpl;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.event.FloodgateEventBus;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
||||
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
||||
import org.geysermc.floodgate.api.legacy.LegacyApiWrapper;
|
||||
@@ -59,14 +61,13 @@ import org.geysermc.floodgate.crypto.Base64Topping;
|
||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||
import org.geysermc.floodgate.crypto.KeyProducer;
|
||||
import org.geysermc.floodgate.event.EventBus;
|
||||
import org.geysermc.floodgate.event.ShutdownEvent;
|
||||
import org.geysermc.floodgate.event.lifecycle.ShutdownEvent;
|
||||
import org.geysermc.floodgate.event.util.ListenerAnnotationMatcher;
|
||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||
import org.geysermc.floodgate.link.PlayerLinkHolder;
|
||||
import org.geysermc.floodgate.packet.PacketHandlersImpl;
|
||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
||||
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinUploadManager;
|
||||
import org.geysermc.floodgate.util.Constants;
|
||||
import org.geysermc.floodgate.util.WebEndpoints;
|
||||
@@ -79,6 +80,7 @@ public class CommonModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(EventBus.class).toInstance(eventBus);
|
||||
bind(FloodgateEventBus.class).to(EventBus.class);
|
||||
// register every class that has the Listener annotation
|
||||
bindListener(new ListenerAnnotationMatcher(), new TypeListener() {
|
||||
@Override
|
||||
@@ -88,8 +90,19 @@ public class CommonModule extends AbstractModule {
|
||||
});
|
||||
|
||||
ExecutorService commonPool = Executors.newCachedThreadPool();
|
||||
eventBus.subscribe(ShutdownEvent.class, ignored -> commonPool.shutdown(), PostOrder.LAST);
|
||||
bind(ExecutorService.class).annotatedWith(Names.named("commonPool")).toInstance(commonPool);
|
||||
ScheduledExecutorService commonScheduledPool = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
eventBus.subscribe(ShutdownEvent.class, ignored -> {
|
||||
commonPool.shutdown();
|
||||
commonScheduledPool.shutdown();
|
||||
}, PostOrder.LAST);
|
||||
|
||||
bind(ExecutorService.class)
|
||||
.annotatedWith(Names.named("commonPool"))
|
||||
.toInstance(commonPool);
|
||||
bind(ScheduledExecutorService.class)
|
||||
.annotatedWith(Names.named("commonScheduledPool"))
|
||||
.toInstance(commonScheduledPool);
|
||||
|
||||
bind(GeyserApiBase.class).to(SimpleFloodgateApi.class);
|
||||
bind(PlatformInjector.class).to(CommonPlatformInjector.class);
|
||||
@@ -160,15 +173,6 @@ public class CommonModule extends AbstractModule {
|
||||
return new PluginMessageManager();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public SkinUploadManager skinUploadManager(
|
||||
GeyserApiBase api,
|
||||
SkinApplier skinApplier,
|
||||
FloodgateLogger logger) {
|
||||
return new SkinUploadManager(api, skinApplier, logger);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("gitBranch")
|
||||
|
||||
@@ -34,14 +34,10 @@ 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.event.Listener;
|
||||
import org.geysermc.event.subscribe.Subscribe;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.command.util.Permission;
|
||||
import org.geysermc.floodgate.event.ShutdownEvent;
|
||||
import org.geysermc.floodgate.news.data.AnnouncementData;
|
||||
import org.geysermc.floodgate.news.data.BuildSpecificData;
|
||||
import org.geysermc.floodgate.news.data.CheckAfterData;
|
||||
@@ -52,10 +48,11 @@ import org.geysermc.floodgate.util.HttpClient;
|
||||
import org.geysermc.floodgate.util.HttpClient.HttpResponse;
|
||||
|
||||
@AutoBind
|
||||
@Listener
|
||||
public class NewsChecker {
|
||||
private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
|
||||
private final Map<Integer, NewsItem> activeNewsItems = new HashMap<>();
|
||||
@Inject
|
||||
@Named("commonScheduledPool")
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
@Inject
|
||||
private CommandUtil commandUtil;
|
||||
@@ -199,15 +196,6 @@ public class NewsChecker {
|
||||
activateNews(item);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onShutdown(ShutdownEvent ignored) {
|
||||
shutdown();
|
||||
}
|
||||
|
||||
private void activateNews(NewsItem item) {
|
||||
for (NewsItemAction action : item.getActions()) {
|
||||
handleNewsItem(null, item, action);
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
package org.geysermc.floodgate.pluginmessage.channel;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.inject.Inject;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
@@ -36,6 +35,7 @@ import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.pluginmessage.PluginMessageChannel;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinData;
|
||||
import org.geysermc.floodgate.skin.SkinDataImpl;
|
||||
|
||||
public class SkinChannel implements PluginMessageChannel {
|
||||
@Inject private GeyserApiBase api;
|
||||
@@ -88,18 +88,10 @@ public class SkinChannel implements PluginMessageChannel {
|
||||
return Result.kick("Got invalid skin data");
|
||||
}
|
||||
|
||||
if (connection.isLinked() || skinApplier.hasSkin(connection)) {
|
||||
return Result.handled();
|
||||
}
|
||||
|
||||
String value = split[0];
|
||||
String signature = split[1];
|
||||
|
||||
JsonObject result = new JsonObject();
|
||||
result.addProperty("value", value);
|
||||
result.addProperty("signature", signature);
|
||||
|
||||
SkinData skinData = new SkinData(value, signature);
|
||||
SkinData skinData = new SkinDataImpl(value, signature);
|
||||
|
||||
skinApplier.applySkin(connection, skinData);
|
||||
|
||||
|
||||
@@ -25,23 +25,16 @@
|
||||
|
||||
package org.geysermc.floodgate.skin;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.event.skin.SkinApplyEvent.SkinData;
|
||||
|
||||
public interface SkinApplier {
|
||||
/**
|
||||
* Apply a skin to a {@link FloodgatePlayer player}
|
||||
* @param connection player to apply skin to
|
||||
* Apply a skin to a {@link Connection player}
|
||||
*
|
||||
* @param connection player to apply skin to
|
||||
* @param skinData data for skin to apply to player
|
||||
*/
|
||||
void applySkin(Connection connection, SkinData skinData);
|
||||
|
||||
/**
|
||||
* Check if a {@link FloodgatePlayer player} currently
|
||||
* has a skin applied.
|
||||
*
|
||||
* @param connection player to check skin of
|
||||
* @return if player has a skin
|
||||
*/
|
||||
boolean hasSkin(Connection connection);
|
||||
void applySkin(@NonNull Connection connection, @NonNull SkinData skinData);
|
||||
}
|
||||
|
||||
@@ -26,22 +26,33 @@
|
||||
package org.geysermc.floodgate.skin;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import java.util.Objects;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.floodgate.api.event.skin.SkinApplyEvent.SkinData;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class SkinData {
|
||||
public class SkinDataImpl implements SkinData {
|
||||
private final String value;
|
||||
private final String signature;
|
||||
|
||||
public SkinDataImpl(@NonNull String value, @NonNull String signature) {
|
||||
this.value = Objects.requireNonNull(value);
|
||||
this.signature = Objects.requireNonNull(signature);
|
||||
}
|
||||
|
||||
public static SkinData from(JsonObject data) {
|
||||
if (data.has("signature") && !data.get("signature").isJsonNull()) {
|
||||
return new SkinData(
|
||||
data.get("value").getAsString(),
|
||||
data.get("signature").getAsString()
|
||||
);
|
||||
}
|
||||
return new SkinData(data.get("value").getAsString(), null);
|
||||
return new SkinDataImpl(
|
||||
data.get("value").getAsString(),
|
||||
data.get("signature").getAsString()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String signature() {
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
@@ -25,22 +25,26 @@
|
||||
|
||||
package org.geysermc.floodgate.skin;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.event.Listener;
|
||||
import org.geysermc.event.subscribe.Subscribe;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.event.lifecycle.ShutdownEvent;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Listener
|
||||
@Singleton
|
||||
public final class SkinUploadManager {
|
||||
private final Int2ObjectMap<SkinUploadSocket> connections =
|
||||
Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
|
||||
|
||||
private final GeyserApiBase api;
|
||||
private final SkinApplier applier;
|
||||
private final FloodgateLogger logger;
|
||||
@Inject private GeyserBaseApi api;
|
||||
@Inject private SkinApplier applier;
|
||||
@Inject private FloodgateLogger logger;
|
||||
|
||||
public void addConnectionIfNeeded(int id, String verifyCode) {
|
||||
connections.computeIfAbsent(id, (ignored) -> {
|
||||
@@ -54,4 +58,16 @@ public final class SkinUploadManager {
|
||||
public void removeConnection(int id, SkinUploadSocket socket) {
|
||||
connections.remove(id, socket);
|
||||
}
|
||||
|
||||
public void closeAllSockets() {
|
||||
for (SkinUploadSocket socket : connections.values()) {
|
||||
socket.close();
|
||||
}
|
||||
connections.clear();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onShutdown(ShutdownEvent ignored) {
|
||||
closeAllSockets();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import javax.net.ssl.SSLException;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.event.skin.SkinApplyEvent.SkinData;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
import org.geysermc.floodgate.util.WebsocketEventType;
|
||||
@@ -60,8 +61,8 @@ final class SkinUploadSocket extends WebSocketClient {
|
||||
SkinUploadManager uploadManager,
|
||||
GeyserApiBase api,
|
||||
SkinApplier applier,
|
||||
FloodgateLogger logger) {
|
||||
|
||||
FloodgateLogger logger
|
||||
) {
|
||||
super(getWebsocketUri(id, verifyCode));
|
||||
this.id = id;
|
||||
this.verifyCode = verifyCode;
|
||||
@@ -82,7 +83,7 @@ final class SkinUploadSocket extends WebSocketClient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(ServerHandshake handshakedata) {
|
||||
public void onOpen(ServerHandshake ignored) {
|
||||
setConnectionLostTimeout(11);
|
||||
}
|
||||
|
||||
@@ -113,10 +114,9 @@ final class SkinUploadSocket extends WebSocketClient {
|
||||
player.javaUsername());
|
||||
return;
|
||||
}
|
||||
if (!player.isLinked() && !applier.hasSkin(player)) {
|
||||
SkinData skinData = SkinData.from(message.getAsJsonObject("data"));
|
||||
applier.applySkin(player, skinData);
|
||||
}
|
||||
|
||||
SkinData skinData = SkinDataImpl.from(message.getAsJsonObject("data"));
|
||||
applier.applySkin(player, skinData);
|
||||
}
|
||||
break;
|
||||
case LOG_MESSAGE:
|
||||
|
||||
@@ -57,6 +57,10 @@ public class HttpClient {
|
||||
return CompletableFuture.supplyAsync(() -> get(urlString), executorService);
|
||||
}
|
||||
|
||||
public <T> CompletableFuture<HttpResponse<T>> asyncGet(String urlString, Class<T> response) {
|
||||
return CompletableFuture.supplyAsync(() -> get(urlString, response), executorService);
|
||||
}
|
||||
|
||||
public DefaultHttpResponse get(String urlString) {
|
||||
return readDefaultResponse(request(urlString));
|
||||
}
|
||||
@@ -99,12 +103,14 @@ public class HttpClient {
|
||||
return new HttpResponse<>(-1, null);
|
||||
}
|
||||
|
||||
int responseCode = -1;
|
||||
try {
|
||||
int responseCode = connection.getResponseCode();
|
||||
responseCode = connection.getResponseCode();
|
||||
T response = gson.fromJson(streamReader, clazz);
|
||||
return new HttpResponse<>(responseCode, response);
|
||||
} catch (Exception ignored) {
|
||||
return new HttpResponse<>(-1, null);
|
||||
// e.g. when the response isn't JSON
|
||||
return new HttpResponse<>(responseCode, null);
|
||||
} finally {
|
||||
try {
|
||||
streamReader.close();
|
||||
@@ -149,11 +155,7 @@ public class HttpClient {
|
||||
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?!");
|
||||
}
|
||||
stream = connection.getErrorStream();
|
||||
}
|
||||
|
||||
// it's null for example when it couldn't connect to the server
|
||||
|
||||
@@ -26,13 +26,16 @@
|
||||
package org.geysermc.floodgate.util;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.geysermc.event.Listener;
|
||||
import org.geysermc.event.subscribe.Subscribe;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.event.PostEnableEvent;
|
||||
import org.geysermc.floodgate.event.lifecycle.PostEnableEvent;
|
||||
|
||||
@AutoBind
|
||||
@Listener
|
||||
@@ -41,6 +44,9 @@ public final class PostEnableMessages {
|
||||
|
||||
@Inject private FloodgateConfig config;
|
||||
@Inject private FloodgateLogger logger;
|
||||
@Inject
|
||||
@Named("commonScheduledPool")
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
public void add(String[] message, Object... args) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
@@ -93,14 +99,11 @@ public final class PostEnableMessages {
|
||||
|
||||
@Subscribe
|
||||
public void onPostEnable(PostEnableEvent ignored) {
|
||||
new Thread(() -> {
|
||||
// normally proxies don't have a lot of plugins, so proxies don't need to sleep as long
|
||||
try {
|
||||
Thread.sleep(config.isProxy() ? 2000 : 5000);
|
||||
} catch (InterruptedException ignored1) {
|
||||
}
|
||||
|
||||
messages.forEach(logger::warn);
|
||||
}).start();
|
||||
// normally proxies don't have a lot of plugins, so proxies don't need to sleep as long
|
||||
executorService.schedule(
|
||||
() -> messages.forEach(logger::warn),
|
||||
config.isProxy() ? 2 : 5,
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -77,7 +78,7 @@ public class Utils {
|
||||
if (is == null) {
|
||||
return null;
|
||||
}
|
||||
properties.load(is);
|
||||
properties.load(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError("Failed to read properties file", e);
|
||||
}
|
||||
|
||||
@@ -26,12 +26,12 @@
|
||||
package org.geysermc.floodgate.util;
|
||||
|
||||
public final class Constants {
|
||||
public static final String VERSION = "${floodgateVersion}";
|
||||
public static final int BUILD_NUMBER = Integer.parseInt("${buildNumber}");
|
||||
public static final String GIT_BRANCH = "${branch}";
|
||||
public static final String VERSION = "@floodgateVersion@";
|
||||
public static final int BUILD_NUMBER = Integer.parseInt("@buildNumber@");
|
||||
public static final String GIT_BRANCH = "@branch@";
|
||||
public static final int METRICS_ID = 14649;
|
||||
|
||||
public static final char COLOR_CHAR = '§';
|
||||
public static final char COLOR_CHAR = '\u00A7';
|
||||
|
||||
public static final boolean DEBUG_MODE = false;
|
||||
public static final boolean PRINT_ALL_PACKETS = false;
|
||||
@@ -55,7 +55,7 @@ public final class Constants {
|
||||
|
||||
public static final String NTP_SERVER = "time.cloudflare.com";
|
||||
public static final String INTERNAL_ERROR_MESSAGE =
|
||||
"An internal error happened while handling Floodgate data." +
|
||||
"An internal error happened while handling Floodgate data." +
|
||||
" Try logging in again or contact a server administrator if the issue persists.";
|
||||
public static final String UNSUPPORTED_DATA_VERSION =
|
||||
"Received an unsupported Floodgate data version." +
|
||||
Reference in New Issue
Block a user