mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2025-12-19 14:59:20 +00:00
Added Player properties, started working on Bungee skins, fixed errors
This commit is contained in:
@@ -97,6 +97,11 @@ public interface FloodgatePlayer {
|
||||
*/
|
||||
InputMode getInputMode();
|
||||
|
||||
/**
|
||||
* Returns if the Floodgate player is connected through a proxy
|
||||
*/
|
||||
boolean isFromProxy();
|
||||
|
||||
/**
|
||||
* Returns the LinkedPlayer object if the player is linked to a Java account.
|
||||
*/
|
||||
@@ -115,6 +120,18 @@ public interface FloodgatePlayer {
|
||||
return sendForm(formBuilder.build());
|
||||
}
|
||||
|
||||
<T> T getProperty(PropertyKey key);
|
||||
|
||||
<T> T getProperty(String key);
|
||||
|
||||
<T> T removeProperty(PropertyKey key);
|
||||
|
||||
<T> T removeProperty(String key);
|
||||
|
||||
<T> T addProperty(PropertyKey key, Object value);
|
||||
|
||||
<T> T addProperty(String key, Object value);
|
||||
|
||||
/**
|
||||
* Casts the FloodgatePlayer instance to a class that extends FloodgatePlayer.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 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.api.player;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class PropertyKey {
|
||||
/**
|
||||
* Socket Address returns the InetSocketAddress of the Bedrock player
|
||||
*/
|
||||
public static final PropertyKey SOCKET_ADDRESS =
|
||||
new PropertyKey("socket_address", false, false);
|
||||
|
||||
/**
|
||||
* Skin Uploaded returns a JsonObject containing the value and signature of the Skin
|
||||
*/
|
||||
public static final PropertyKey SKIN_UPLOADED =
|
||||
new PropertyKey("skin_uploaded", false, false);
|
||||
|
||||
private final String key;
|
||||
private final boolean changeable;
|
||||
private final boolean removeable;
|
||||
|
||||
public PropertyKey(String key, boolean changeable, boolean removeable) {
|
||||
this.key = key;
|
||||
this.changeable = changeable;
|
||||
this.removeable = removeable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof PropertyKey) {
|
||||
return key.equals(((PropertyKey) obj).key);
|
||||
}
|
||||
|
||||
if (obj instanceof String) {
|
||||
return key.equals(obj);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public AllowedResult isAddAllowed(Object obj) {
|
||||
if (obj instanceof PropertyKey) {
|
||||
PropertyKey propertyKey = (PropertyKey) obj;
|
||||
|
||||
if (key.equals(propertyKey.key)) {
|
||||
if ((propertyKey.changeable == changeable || propertyKey.changeable) &&
|
||||
(propertyKey.removeable == removeable || propertyKey.removeable)) {
|
||||
return AllowedResult.CORRECT;
|
||||
}
|
||||
return AllowedResult.INVALID_TAGS;
|
||||
}
|
||||
return AllowedResult.NOT_EQUALS;
|
||||
}
|
||||
|
||||
if (obj instanceof String) {
|
||||
if (changeable) {
|
||||
return AllowedResult.CORRECT;
|
||||
}
|
||||
return AllowedResult.INVALID_TAGS;
|
||||
}
|
||||
return AllowedResult.NOT_EQUALS;
|
||||
}
|
||||
|
||||
public enum AllowedResult {
|
||||
NOT_EQUALS,
|
||||
INVALID_TAGS,
|
||||
CORRECT
|
||||
}
|
||||
}
|
||||
@@ -39,9 +39,9 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-protocol</artifactId>
|
||||
<version>${bungee.version}</version>
|
||||
<groupId>com.github.SpigotMC.BungeeCord</groupId>
|
||||
<artifactId>bungeecord-proxy</artifactId>
|
||||
<version>master-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -88,5 +88,9 @@
|
||||
<id>bungeecord-repo</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jitpack</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</project>
|
||||
@@ -33,7 +33,7 @@ import org.geysermc.floodgate.module.BungeeAddonModule;
|
||||
import org.geysermc.floodgate.module.BungeeListenerModule;
|
||||
import org.geysermc.floodgate.module.BungeePlatformModule;
|
||||
import org.geysermc.floodgate.module.CommandModule;
|
||||
import org.geysermc.floodgate.module.CommonModule;
|
||||
import org.geysermc.floodgate.module.ProxyCommonModule;
|
||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||
|
||||
public final class BungeePlugin extends Plugin {
|
||||
@@ -45,7 +45,7 @@ public final class BungeePlugin extends Plugin {
|
||||
|
||||
long ctm = System.currentTimeMillis();
|
||||
Injector injector = Guice.createInjector(
|
||||
new CommonModule(getDataFolder().toPath()),
|
||||
new ProxyCommonModule(getDataFolder().toPath()),
|
||||
new BungeePlatformModule(this)
|
||||
);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.geysermc.floodgate.HandshakeHandler.HandshakeResult;
|
||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||
@@ -97,7 +98,12 @@ public final class BungeeDataHandler {
|
||||
event.getConnection(), EXTRA_HANDSHAKE_DATA
|
||||
);
|
||||
|
||||
HandshakeResult result = handler.handle(extraData);
|
||||
Object channelWrapper =
|
||||
ReflectionUtils.getValue(event.getConnection(), PLAYER_CHANNEL_WRAPPER);
|
||||
|
||||
Channel channel = ReflectionUtils.getCastedValue(channelWrapper, PLAYER_CHANNEL);
|
||||
|
||||
HandshakeResult result = handler.handle(channel, extraData);
|
||||
switch (result.getResultType()) {
|
||||
case EXCEPTION:
|
||||
event.setCancelReason(config.getDisconnect().getInvalidKey());
|
||||
@@ -117,7 +123,13 @@ public final class BungeeDataHandler {
|
||||
}
|
||||
|
||||
FloodgatePlayer player = result.getFloodgatePlayer();
|
||||
api.addEncryptedData(player.getCorrectUniqueId(), result.getHandshakeData()[1]);
|
||||
|
||||
String encryptedData = result.getHandshakeData()[1];
|
||||
// remove skin from encrypted data if it has a skin
|
||||
if (encryptedData.indexOf(0x21) != -1) {
|
||||
encryptedData = encryptedData.substring(0, encryptedData.indexOf(0x21) - 1);
|
||||
}
|
||||
api.addEncryptedData(player.getCorrectUniqueId(), encryptedData);
|
||||
|
||||
event.getConnection().setOnlineMode(false);
|
||||
event.getConnection().setUniqueId(player.getCorrectUniqueId());
|
||||
@@ -126,9 +138,6 @@ public final class BungeeDataHandler {
|
||||
event.getConnection(), PLAYER_NAME, player.getCorrectUsername()
|
||||
);
|
||||
|
||||
Object channelWrapper =
|
||||
ReflectionUtils.getValue(event.getConnection(), PLAYER_CHANNEL_WRAPPER);
|
||||
|
||||
SocketAddress remoteAddress =
|
||||
ReflectionUtils.getCastedValue(channelWrapper, PLAYER_REMOTE_ADDRESS);
|
||||
|
||||
@@ -137,15 +146,15 @@ public final class BungeeDataHandler {
|
||||
"Ignoring the player, I guess.",
|
||||
player.getUsername(), remoteAddress.getClass().getSimpleName()
|
||||
);
|
||||
} else {
|
||||
int port = ((InetSocketAddress) remoteAddress).getPort();
|
||||
ReflectionUtils.setValue(
|
||||
channelWrapper, PLAYER_REMOTE_ADDRESS,
|
||||
new InetSocketAddress(result.getBedrockData().getIp(), port)
|
||||
);
|
||||
event.setCancelled(true);
|
||||
event.setCancelReason(
|
||||
new TextComponent("remoteAddress is not an InetSocketAddress!"));
|
||||
event.completeIntent(plugin);
|
||||
return;
|
||||
}
|
||||
|
||||
Channel channel = ReflectionUtils.getCastedValue(channelWrapper, PLAYER_CHANNEL);
|
||||
InetSocketAddress correctAddress = player.getProperty(PropertyKey.SOCKET_ADDRESS);
|
||||
ReflectionUtils.setValue(channelWrapper, PLAYER_REMOTE_ADDRESS, correctAddress);
|
||||
|
||||
channel.attr(playerAttribute).set(player);
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import net.md_5.bungee.api.event.LoginEvent;
|
||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
import net.md_5.bungee.api.event.PreLoginEvent;
|
||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
||||
import net.md_5.bungee.api.event.ServerConnectedEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.event.EventPriority;
|
||||
@@ -40,7 +41,10 @@ import org.geysermc.floodgate.FloodgatePlayerImpl;
|
||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.handler.BungeeDataHandler;
|
||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||
import org.geysermc.floodgate.skin.SkinHandler;
|
||||
import org.geysermc.floodgate.util.LanguageManager;
|
||||
|
||||
public final class BungeeListener implements Listener {
|
||||
@@ -49,6 +53,10 @@ public final class BungeeListener implements Listener {
|
||||
@Inject private LanguageManager languageManager;
|
||||
@Inject private FloodgateLogger logger;
|
||||
|
||||
@Inject private ProxyFloodgateConfig config;
|
||||
@Inject private PluginMessageHandler pluginMessageHandler;
|
||||
@Inject private SkinHandler skinHandler;
|
||||
|
||||
@Inject
|
||||
public void init(Injector injector) {
|
||||
dataHandler = injector.getInstance(BungeeDataHandler.class);
|
||||
@@ -59,6 +67,24 @@ public final class BungeeListener implements Listener {
|
||||
dataHandler.handleServerConnect(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerConnected(ServerConnectedEvent event) {
|
||||
ProxiedPlayer player = event.getPlayer();
|
||||
FloodgatePlayer floodgatePlayer = api.getPlayer(player.getUniqueId());
|
||||
if (floodgatePlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// send skin request to server if data forwarding allows that
|
||||
if (config.isSendFloodgateData()) {
|
||||
pluginMessageHandler.sendSkinRequest(player.getUniqueId(),
|
||||
floodgatePlayer.getRawSkin());
|
||||
} else {
|
||||
//todo also a Proxy SkinHandler to keep stuff clean?
|
||||
skinHandler.handleSkinUploadFor(floodgatePlayer, null);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPreLogin(PreLoginEvent event) {
|
||||
dataHandler.handlePreLogin(event);
|
||||
|
||||
@@ -33,14 +33,9 @@ import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import org.geysermc.floodgate.BungeePlugin;
|
||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.command.BungeeCommandRegistration;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||
import org.geysermc.floodgate.inject.bungee.BungeeInjector;
|
||||
import org.geysermc.floodgate.listener.BungeeListenerRegistration;
|
||||
@@ -50,6 +45,9 @@ import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.platform.listener.ListenerRegistration;
|
||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||
import org.geysermc.floodgate.pluginmessage.BungeePluginMessageHandler;
|
||||
import org.geysermc.floodgate.pluginmessage.BungeeSkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinHandler;
|
||||
import org.geysermc.floodgate.util.BungeeCommandUtil;
|
||||
import org.geysermc.floodgate.util.LanguageManager;
|
||||
|
||||
@@ -57,31 +55,12 @@ import org.geysermc.floodgate.util.LanguageManager;
|
||||
public final class BungeePlatformModule extends AbstractModule {
|
||||
private final BungeePlugin plugin;
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(SimpleFloodgateApi.class).to(ProxyFloodgateApi.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public Plugin bungeePlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("configClass")
|
||||
public Class<? extends FloodgateConfig> floodgateConfigClass() {
|
||||
return ProxyFloodgateConfig.class;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public ProxyFloodgateApi proxyFloodgateApi(PluginMessageHandler pluginMessageHandler,
|
||||
FloodgateCipher cipher) {
|
||||
return new ProxyFloodgateApi(pluginMessageHandler, cipher);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public FloodgateLogger floodgateLogger(LanguageManager languageManager) {
|
||||
@@ -117,6 +96,18 @@ public final class BungeePlatformModule extends AbstractModule {
|
||||
return new BungeePluginMessageHandler(configHolder);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public SkinApplier skinApplier(FloodgateLogger logger) {
|
||||
return new BungeeSkinApplier(logger);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public SkinHandler skinHandler(SkinApplier skinApplier, FloodgateLogger logger) {
|
||||
return new SkinHandler(skinApplier, logger);
|
||||
}
|
||||
|
||||
/*
|
||||
DebugAddon / PlatformInjector
|
||||
*/
|
||||
|
||||
@@ -25,10 +25,12 @@
|
||||
|
||||
package org.geysermc.floodgate.pluginmessage;
|
||||
|
||||
import static org.geysermc.floodgate.util.MessageFormatter.format;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.UUID;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
@@ -40,15 +42,22 @@ import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import org.geysermc.cumulus.Form;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinUploader.UploadResult;
|
||||
import org.geysermc.floodgate.util.RawSkin;
|
||||
|
||||
public final class BungeePluginMessageHandler extends PluginMessageHandler implements Listener {
|
||||
private ProxyServer proxy;
|
||||
private FloodgateLogger logger;
|
||||
private String formChannel;
|
||||
private String skinChannel;
|
||||
private FloodgateApi api;
|
||||
private SkinApplier skinApplier;
|
||||
|
||||
public BungeePluginMessageHandler(FloodgateConfigHolder configHolder) {
|
||||
super(configHolder);
|
||||
@@ -57,10 +66,14 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple
|
||||
@Inject // called because this is a listener as well
|
||||
public void init(Plugin plugin, FloodgateLogger logger,
|
||||
@Named("formChannel") String formChannel,
|
||||
@Named("skinChannel") String skinChannel) {
|
||||
@Named("skinChannel") String skinChannel,
|
||||
FloodgateApi api, SkinApplier skinApplier) {
|
||||
this.proxy = plugin.getProxy();
|
||||
this.logger = logger;
|
||||
this.formChannel = formChannel;
|
||||
this.skinChannel = skinChannel;
|
||||
this.api = api;
|
||||
this.skinApplier = skinApplier;
|
||||
|
||||
proxy.registerChannel(formChannel);
|
||||
proxy.registerChannel(skinChannel);
|
||||
@@ -69,6 +82,7 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple
|
||||
@EventHandler
|
||||
public void onPluginMessage(PluginMessageEvent event) {
|
||||
Connection source = event.getSender();
|
||||
|
||||
if (event.getTag().equals(formChannel)) {
|
||||
if (source instanceof Server) {
|
||||
// send it to the client
|
||||
@@ -79,8 +93,7 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple
|
||||
if (source instanceof ProxiedPlayer) {
|
||||
byte[] data = event.getData();
|
||||
if (data.length < 2) {
|
||||
logger.error("Invalid form response! Closing connection");
|
||||
source.disconnect(new TextComponent("Invalid form response!"));
|
||||
logKick(source, "Invalid form response!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,12 +108,73 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple
|
||||
event.setCancelled(true);
|
||||
|
||||
if (!callResponseConsumer(data)) {
|
||||
logger.error(format(
|
||||
"Couldn't find stored form with id {} for player {}",
|
||||
formId, ((ProxiedPlayer) source).getName()));
|
||||
logger.error("Couldn't find stored form with id {} for player {}",
|
||||
formId, ((ProxiedPlayer) source).getName());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getTag().equals(skinChannel)) {
|
||||
byte[] data = event.getData();
|
||||
|
||||
if (data.length < 1) {
|
||||
logKick(source, "Got invalid Skin request/response.");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean request = data[0] == 1;
|
||||
|
||||
if (!request && data.length < 2) {
|
||||
logKick(source, "Got invalid Skin response.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (source instanceof Server) {
|
||||
if (request) {
|
||||
logKick(source, "Got Skin request from Server?");
|
||||
return;
|
||||
}
|
||||
|
||||
UUID playerUniqueId = ((ProxiedPlayer) event.getReceiver()).getUniqueId();
|
||||
FloodgatePlayer floodgatePlayer = api.getPlayer(playerUniqueId);
|
||||
|
||||
if (floodgatePlayer == null) {
|
||||
logKick(source, "Server issued Skin request for non-Floodgate player.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 1 = failed, 0 = successful.
|
||||
|
||||
// we'll try it again on the next server if it failed
|
||||
if (data[1] != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonObject response;
|
||||
try {
|
||||
Reader reader = new InputStreamReader(
|
||||
new ByteArrayInputStream(event.getData()));
|
||||
response = GSON.fromJson(reader, JsonObject.class);
|
||||
} catch (Throwable throwable) {
|
||||
logger.error("Failed to read Skin response", throwable);
|
||||
return;
|
||||
}
|
||||
|
||||
skinApplier.applySkin(floodgatePlayer, UploadResult.success(response));
|
||||
return;
|
||||
}
|
||||
|
||||
// Players (Geyser) can't send requests nor responses
|
||||
if (source instanceof ProxiedPlayer) {
|
||||
logKick(source, "Got Skin " + (request ? "request" : "response") + " from Player?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void logKick(Connection source, String reason) {
|
||||
logger.error(reason + " Closing connection");
|
||||
source.disconnect(new TextComponent(reason));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -114,12 +188,12 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendSkinRequest(UUID player, RawSkin skin) {
|
||||
return false; //todo
|
||||
public boolean sendSkinRequest(UUID uuid, RawSkin skin) {
|
||||
ProxiedPlayer player = proxy.getPlayer(uuid);
|
||||
if (player != null) {
|
||||
player.sendData(skinChannel, createSkinRequestData(skin.encode()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSkinResponse(UUID player, String response) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 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.pluginmessage;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.connection.InitialHandler;
|
||||
import net.md_5.bungee.connection.LoginResult;
|
||||
import net.md_5.bungee.connection.LoginResult.Property;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinUploader.UploadResult;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public final class BungeeSkinApplier implements SkinApplier {
|
||||
private final FloodgateLogger logger;
|
||||
|
||||
@Override
|
||||
public void applySkin(FloodgatePlayer uuid, UploadResult result) {
|
||||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid.getCorrectUniqueId());
|
||||
|
||||
InitialHandler handler;
|
||||
try {
|
||||
handler = (InitialHandler) player.getPendingConnection();
|
||||
} catch (Exception exception) {
|
||||
logger.error("Incompatible Bungeecord fork detected", exception);
|
||||
return;
|
||||
}
|
||||
|
||||
LoginResult loginResult = handler.getLoginProfile();
|
||||
// expected to be null since LoginResult is the data from hasJoined,
|
||||
// which Floodgate players don't have
|
||||
if (loginResult == null) {
|
||||
// id and name are unused and properties will be overridden
|
||||
loginResult = new LoginResult(null, null, null);
|
||||
}
|
||||
|
||||
JsonObject response = result.getResponse();
|
||||
Property property = new Property(
|
||||
"textures",
|
||||
response.get("value").getAsString(),
|
||||
response.get("signature").getAsString()
|
||||
);
|
||||
|
||||
loginResult.setProperties(new Property[]{property});
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,11 @@
|
||||
<artifactId>api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.geysermc.cumulus</groupId>
|
||||
<artifactId>cumulus</artifactId>
|
||||
<version>${cumulus.version}</version>
|
||||
</dependency>
|
||||
<!-- <dependency> todo -->
|
||||
<!-- <groupId>com.mojang</groupId>-->
|
||||
<!-- <artifactId>brigadier</artifactId>-->
|
||||
@@ -64,12 +69,6 @@
|
||||
<version>1.27</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.5</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||
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;
|
||||
|
||||
public class FloodgatePlatform {
|
||||
@@ -56,16 +55,16 @@ public class FloodgatePlatform {
|
||||
|
||||
@Inject
|
||||
public FloodgatePlatform(FloodgateApi api, PlatformInjector platformInjector,
|
||||
FloodgateLogger logger) {
|
||||
FloodgateLogger logger, Injector guice) {
|
||||
this.api = api;
|
||||
this.injector = platformInjector;
|
||||
this.logger = logger;
|
||||
this.guice = guice;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void init(@Named("dataDirectory") Path dataDirectory, ConfigLoader configLoader,
|
||||
PlayerLinkLoader playerLinkLoader, FloodgateConfigHolder configHolder,
|
||||
Injector injector) {
|
||||
PlayerLinkLoader playerLinkLoader, FloodgateConfigHolder configHolder) {
|
||||
|
||||
if (!Files.isDirectory(dataDirectory)) {
|
||||
try {
|
||||
@@ -84,9 +83,6 @@ public class FloodgatePlatform {
|
||||
configHolder.set(config);
|
||||
PlayerLink link = playerLinkLoader.load();
|
||||
|
||||
// make the config available for other classes (who are injected later on)
|
||||
guice = injector.createChildInjector(new ConfigLoadedModule(config));
|
||||
|
||||
InstanceHolder.setInstance(api, link, this.injector, KEY);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
package org.geysermc.floodgate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@@ -37,6 +39,7 @@ import org.geysermc.floodgate.api.InstanceHolder;
|
||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
@@ -48,11 +51,11 @@ import org.geysermc.floodgate.util.UiProfile;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
||||
private final String version;
|
||||
private final String username;
|
||||
private final String javaUsername;
|
||||
//todo maybe add a map for platform specific things
|
||||
private final UUID javaUniqueId;
|
||||
private final String xuid;
|
||||
private final DeviceOs deviceOs;
|
||||
@@ -60,10 +63,13 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
||||
private final UiProfile uiProfile;
|
||||
private final InputMode inputMode;
|
||||
private final String ip;
|
||||
private final boolean fromProxy; //todo remove hasBungeeData
|
||||
private final boolean fromProxy;
|
||||
private final LinkedPlayer linkedPlayer;
|
||||
private final RawSkin rawSkin;
|
||||
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
public Map<PropertyKey, Object> propertyKeyToValue;
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
private Map<String, PropertyKey> stringToPropertyKey;
|
||||
/**
|
||||
* Returns true if the player is still logging in
|
||||
*/
|
||||
@@ -87,6 +93,12 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
||||
UiProfile uiProfile = UiProfile.getById(data.getUiProfile());
|
||||
InputMode inputMode = InputMode.getById(data.getInputMode());
|
||||
|
||||
// RawSkin must be removed from the encrypted data
|
||||
if (api instanceof ProxyFloodgateApi) {
|
||||
InstanceHolder.castApi(ProxyFloodgateApi.class)
|
||||
.updateEncryptedData(javaUniqueId, data);
|
||||
}
|
||||
|
||||
LinkedPlayer linkedPlayer;
|
||||
|
||||
// we'll use the LinkedPlayer provided by Bungee or Velocity (if they included one)
|
||||
@@ -103,7 +115,7 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
||||
deviceOs, data.getLanguageCode(), uiProfile, inputMode, data.getIp(),
|
||||
data.isFromProxy(), linkedPlayer, skin);
|
||||
|
||||
// oh oh, after fetching the linkedPlayer our encrypted data is incorrect.
|
||||
// encrypted data has been changed after fetching the linkedPlayer
|
||||
// We have to update it...
|
||||
if (linkedPlayer != null && api instanceof ProxyFloodgateApi) {
|
||||
InstanceHolder.castApi(ProxyFloodgateApi.class)
|
||||
@@ -112,14 +124,6 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
||||
return player;
|
||||
}
|
||||
|
||||
public UUID getCorrectUniqueId() {
|
||||
return linkedPlayer != null ? linkedPlayer.getJavaUniqueId() : javaUniqueId;
|
||||
}
|
||||
|
||||
public String getCorrectUsername() {
|
||||
return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and return the LinkedPlayer object associated to the player if the player is linked.
|
||||
* Please note that this method loads the LinkedPlayer synchronously.
|
||||
@@ -154,9 +158,108 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
||||
CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
public UUID getCorrectUniqueId() {
|
||||
return linkedPlayer != null ? linkedPlayer.getJavaUniqueId() : javaUniqueId;
|
||||
}
|
||||
|
||||
public String getCorrectUsername() {
|
||||
return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername;
|
||||
}
|
||||
|
||||
public BedrockData toBedrockData() {
|
||||
return BedrockData.of(
|
||||
version, username, xuid, deviceOs.ordinal(), languageCode,
|
||||
uiProfile.ordinal(), inputMode.ordinal(), ip, linkedPlayer, fromProxy);
|
||||
}
|
||||
|
||||
public <T> T getProperty(PropertyKey key) {
|
||||
if (propertyKeyToValue == null) {
|
||||
return null;
|
||||
}
|
||||
return (T) propertyKeyToValue.get(key);
|
||||
}
|
||||
|
||||
public <T> T getProperty(String key) {
|
||||
if (stringToPropertyKey == null) {
|
||||
return null;
|
||||
}
|
||||
return getProperty(stringToPropertyKey.get(key));
|
||||
}
|
||||
|
||||
public <T> T removeProperty(String key) {
|
||||
if (stringToPropertyKey == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyKey propertyKey = stringToPropertyKey.get(key);
|
||||
|
||||
if (propertyKey == null || !propertyKey.isRemoveable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (T) propertyKeyToValue.remove(propertyKey);
|
||||
}
|
||||
|
||||
public <T> T removeProperty(PropertyKey key) {
|
||||
if (stringToPropertyKey == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyKey propertyKey = stringToPropertyKey.get(key.getKey());
|
||||
|
||||
if (propertyKey == null || !propertyKey.equals(key) || !propertyKey.isRemoveable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (T) propertyKeyToValue.remove(key);
|
||||
}
|
||||
|
||||
public <T> T addProperty(PropertyKey key, Object value) {
|
||||
if (stringToPropertyKey == null) {
|
||||
stringToPropertyKey = new HashMap<>();
|
||||
propertyKeyToValue = new HashMap<>();
|
||||
|
||||
stringToPropertyKey.put(key.getKey(), key);
|
||||
propertyKeyToValue.put(key, value);
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyKey propertyKey = stringToPropertyKey.get(key.getKey());
|
||||
|
||||
if (propertyKey != null && propertyKey.equals(key) && key.isChangeable()) {
|
||||
stringToPropertyKey.put(key.getKey(), key);
|
||||
return (T) propertyKeyToValue.put(key, value);
|
||||
}
|
||||
|
||||
return (T) stringToPropertyKey.computeIfAbsent(key.getKey(), (keyString) -> {
|
||||
propertyKeyToValue.put(key, value);
|
||||
return key;
|
||||
});
|
||||
}
|
||||
|
||||
public <T> T addProperty(String key, Object value) {
|
||||
PropertyKey propertyKey = new PropertyKey(key, true, true);
|
||||
|
||||
if (stringToPropertyKey == null) {
|
||||
stringToPropertyKey = new HashMap<>();
|
||||
propertyKeyToValue = new HashMap<>();
|
||||
|
||||
stringToPropertyKey.put(key, propertyKey);
|
||||
propertyKeyToValue.put(propertyKey, value);
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyKey currentPropertyKey = stringToPropertyKey.get(key);
|
||||
|
||||
// key is always changeable if it passes this if statement
|
||||
if (currentPropertyKey != null && currentPropertyKey.equals(propertyKey)) {
|
||||
stringToPropertyKey.put(key, propertyKey);
|
||||
return (T) propertyKeyToValue.put(propertyKey, value);
|
||||
}
|
||||
|
||||
return (T) stringToPropertyKey.computeIfAbsent(key, (keyString) -> {
|
||||
propertyKeyToValue.put(propertyKey, value);
|
||||
return propertyKey;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ package org.geysermc.floodgate;
|
||||
import static org.geysermc.floodgate.util.BedrockData.EXPECTED_LENGTH;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import io.netty.channel.Channel;
|
||||
import java.net.InetSocketAddress;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
@@ -35,6 +37,7 @@ import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||
import org.geysermc.floodgate.crypto.AesCipher;
|
||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||
@@ -48,7 +51,7 @@ public final class HandshakeHandler {
|
||||
private final FloodgateCipher cipher;
|
||||
private final FloodgateConfigHolder configHolder;
|
||||
|
||||
public HandshakeResult handle(@NonNull String handshakeData) {
|
||||
public HandshakeResult handle(Channel channel, @NonNull String handshakeData) {
|
||||
try {
|
||||
String[] dataArray = handshakeData.split("\0");
|
||||
|
||||
@@ -95,11 +98,13 @@ public final class HandshakeHandler {
|
||||
rawSkin = RawSkin.decode(rawSkinData);
|
||||
}
|
||||
|
||||
System.out.println(rawSkin);
|
||||
|
||||
FloodgatePlayer player = FloodgatePlayerImpl.from(bedrockData, rawSkin, configHolder);
|
||||
api.addPlayer(player.getJavaUniqueId(), player);
|
||||
|
||||
int port = ((InetSocketAddress) channel.remoteAddress()).getPort();
|
||||
InetSocketAddress socketAddress = new InetSocketAddress(bedrockData.getIp(), port);
|
||||
player.addProperty(PropertyKey.SOCKET_ADDRESS, socketAddress);
|
||||
|
||||
return new HandshakeResult(ResultType.SUCCESS, dataArray, bedrockData, player);
|
||||
} catch (InvalidFormatException formatException) {
|
||||
// only header exceptions should return 'not floodgate data',
|
||||
|
||||
@@ -27,10 +27,10 @@ package org.geysermc.floodgate.addon;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import org.geysermc.floodgate.addon.addonmanager.AddonManagerHandler;
|
||||
import org.geysermc.floodgate.api.inject.InjectorAddon;
|
||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
|
||||
public final class AddonManagerAddon implements InjectorAddon {
|
||||
@Inject private CommonPlatformInjector injector;
|
||||
@@ -47,10 +47,7 @@ public final class AddonManagerAddon implements InjectorAddon {
|
||||
|
||||
@Override
|
||||
public void onRemoveInject(Channel channel) {
|
||||
ChannelHandler handler = channel.pipeline().get("floodgate_addon");
|
||||
if (handler != null) {
|
||||
channel.pipeline().remove(handler);
|
||||
}
|
||||
Utils.removeHandler(channel.pipeline(), "floodgate_addon");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.geysermc.floodgate.addon.debug.ChannelOutDebugHandler;
|
||||
import org.geysermc.floodgate.api.inject.InjectorAddon;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
|
||||
public final class DebugAddon implements InjectorAddon {
|
||||
@Inject private FloodgateConfig config;
|
||||
@@ -71,8 +72,8 @@ public final class DebugAddon implements InjectorAddon {
|
||||
public void onRemoveInject(Channel channel) {
|
||||
ChannelPipeline pipeline = channel.pipeline();
|
||||
|
||||
pipeline.remove("floodgate_debug_out");
|
||||
pipeline.remove("floodgate_debug_in");
|
||||
Utils.removeHandler(pipeline, "floodgate_debug_out");
|
||||
Utils.removeHandler(pipeline, "floodgate_debug_in");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,9 +29,10 @@ import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.name.Named;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@@ -124,8 +125,17 @@ public final class PlayerLinkLoader {
|
||||
return null;
|
||||
}
|
||||
|
||||
// allow the FloodgateConfig to be used directly instead of the FloodgateConfigHolder
|
||||
Injector child = injector.createChildInjector(new AbstractModule() {
|
||||
@Provides
|
||||
@Singleton
|
||||
public FloodgateConfig floodgateConfig() {
|
||||
return config;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
PlayerLink instance = injector.getInstance(mainClass);
|
||||
PlayerLink instance = child.getInstance(mainClass);
|
||||
instance.load();
|
||||
return instance;
|
||||
} catch (Exception exception) {
|
||||
|
||||
@@ -54,7 +54,7 @@ import org.geysermc.floodgate.link.PlayerLinkLoader;
|
||||
import org.geysermc.floodgate.util.LanguageManager;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public final class CommonModule extends AbstractModule {
|
||||
public class CommonModule extends AbstractModule {
|
||||
private final Path dataDirectory;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 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.module;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.name.Named;
|
||||
import java.nio.file.Path;
|
||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinHandler;
|
||||
|
||||
public final class ProxyCommonModule extends CommonModule {
|
||||
public ProxyCommonModule(Path dataDirectory) {
|
||||
super(dataDirectory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
bind(SimpleFloodgateApi.class).to(ProxyFloodgateApi.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("configClass")
|
||||
public Class<? extends FloodgateConfig> floodgateConfigClass() {
|
||||
return ProxyFloodgateConfig.class;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public ProxyFloodgateApi proxyFloodgateApi(PluginMessageHandler pluginMessageHandler,
|
||||
FloodgateCipher cipher) {
|
||||
return new ProxyFloodgateApi(pluginMessageHandler, cipher);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public SkinHandler skinHandler(SkinApplier skinApplier, FloodgateLogger logger) {
|
||||
return new SkinHandler(skinApplier, logger);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 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.module;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.name.Named;
|
||||
import java.nio.file.Path;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||
import org.geysermc.floodgate.skin.ServerSkinHandler;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinHandler;
|
||||
|
||||
public final class ServerCommonModule extends CommonModule {
|
||||
public ServerCommonModule(Path dataDirectory) {
|
||||
super(dataDirectory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
bind(SkinHandler.class).to(ServerSkinHandler.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("configClass")
|
||||
public Class<? extends FloodgateConfig> floodgateConfigClass() {
|
||||
return FloodgateConfig.class;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public SimpleFloodgateApi floodgateApi(PluginMessageHandler pluginMessageHandler) {
|
||||
return new SimpleFloodgateApi(pluginMessageHandler);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public ServerSkinHandler skinHandler(SkinApplier skinApplier, FloodgateLogger logger,
|
||||
PluginMessageHandler pluginMessageHandler) {
|
||||
return new ServerSkinHandler(skinApplier, logger, pluginMessageHandler);
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,10 @@
|
||||
package org.geysermc.floodgate.platform.pluginmessage;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.gson.Gson;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.geysermc.cumulus.Form;
|
||||
@@ -35,6 +37,7 @@ import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||
import org.geysermc.floodgate.util.RawSkin;
|
||||
|
||||
public abstract class PluginMessageHandler {
|
||||
protected static final Gson GSON = new Gson();
|
||||
protected final Short2ObjectMap<Form> storedForms = new Short2ObjectOpenHashMap<>();
|
||||
private final AtomicInteger nextFormId = new AtomicInteger(0);
|
||||
private final FloodgateConfigHolder configHolder;
|
||||
@@ -45,9 +48,13 @@ public abstract class PluginMessageHandler {
|
||||
|
||||
public abstract boolean sendForm(UUID player, Form form);
|
||||
|
||||
public abstract boolean sendSkinRequest(UUID player, RawSkin skin);
|
||||
public boolean sendSkinRequest(UUID player, RawSkin skin) {
|
||||
return false; // Non-proxy implementations don't send requests
|
||||
}
|
||||
|
||||
public abstract void sendSkinResponse(UUID player, String response);
|
||||
public void sendSkinResponse(UUID player, boolean failed, String response) {
|
||||
return; // Proxy implementations don't send responses
|
||||
}
|
||||
|
||||
protected byte[] createFormData(Form form) {
|
||||
short formId = getNextFormId();
|
||||
@@ -66,11 +73,40 @@ public abstract class PluginMessageHandler {
|
||||
return data;
|
||||
}
|
||||
|
||||
protected boolean callResponseConsumer(byte[] data) {
|
||||
protected byte[] createSkinRequestData(byte[] data) {
|
||||
// data format:
|
||||
// 0 = is request
|
||||
// remaining = request data
|
||||
|
||||
byte[] output = new byte[data.length + 1];
|
||||
|
||||
output[0] = 1;
|
||||
System.arraycopy(data, 0, output, 1, data.length);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
protected byte[] createSkinResponseData(boolean failed, String data) {
|
||||
// data format:
|
||||
// 0 = is request
|
||||
// 1 = has failed
|
||||
// remaining = response data
|
||||
|
||||
byte[] rawData = data.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] output = new byte[rawData.length + 2];
|
||||
|
||||
output[0] = 0;
|
||||
output[1] = (byte) (failed ? 1 : 0);
|
||||
System.arraycopy(rawData, 0, output, 2, rawData.length);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public boolean callResponseConsumer(byte[] data) {
|
||||
Form storedForm = storedForms.remove(getFormId(data));
|
||||
if (storedForm != null) {
|
||||
storedForm.getResponseHandler().accept(
|
||||
new String(data, 2, data.length - 2, Charsets.UTF_8));
|
||||
String responseData = new String(data, 2, data.length -2, Charsets.UTF_8);
|
||||
storedForm.getResponseHandler().accept(responseData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 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.skin;
|
||||
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||
import org.geysermc.floodgate.util.RawSkin;
|
||||
|
||||
public final class ServerSkinHandler extends SkinHandler {
|
||||
private final PluginMessageHandler pluginMessageHandler;
|
||||
|
||||
public ServerSkinHandler(SkinApplier skinApplier,
|
||||
FloodgateLogger logger,
|
||||
PluginMessageHandler pluginMessageHandler) {
|
||||
super(skinApplier, logger);
|
||||
this.pluginMessageHandler = pluginMessageHandler;
|
||||
}
|
||||
|
||||
public void handleSkinUploadFor(FloodgatePlayer player) {
|
||||
handleSkinUploadFor(player, player.getRawSkin());
|
||||
}
|
||||
|
||||
public void handleSkinUploadFor(FloodgatePlayer player, RawSkin rawSkin) {
|
||||
handleSkinUploadFor(player, rawSkin,
|
||||
(failed, response) -> {
|
||||
if (player.isFromProxy()) {
|
||||
pluginMessageHandler.sendSkinResponse(
|
||||
player.getCorrectUniqueId(),
|
||||
failed,
|
||||
response
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -23,29 +23,11 @@
|
||||
* @link https://github.com/GeyserMC/Floodgate
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.module;
|
||||
package org.geysermc.floodgate.skin;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Singleton;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.skin.SkinUploader.UploadResult;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public final class ConfigLoadedModule extends AbstractModule {
|
||||
private final FloodgateConfig config;
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
if (config instanceof ProxyFloodgateConfig) {
|
||||
bind(ProxyFloodgateConfig.class).toInstance((ProxyFloodgateConfig) config);
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public FloodgateConfig floodgateConfig() {
|
||||
return config;
|
||||
}
|
||||
public interface SkinApplier {
|
||||
void applySkin(FloodgatePlayer floodgatePlayer, UploadResult result);
|
||||
}
|
||||
@@ -25,50 +25,66 @@
|
||||
|
||||
package org.geysermc.floodgate.skin;
|
||||
|
||||
import static org.geysermc.floodgate.util.MessageFormatter.format;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||
import org.geysermc.floodgate.skin.SkinUploader.UploadResult;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||
import org.geysermc.floodgate.util.RawSkin;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class SkinHandler {
|
||||
public class SkinHandler {
|
||||
private final SkinUploader uploader = new SkinUploader();
|
||||
private final PluginMessageHandler messageHandler;
|
||||
private final SkinApplier skinApplier;
|
||||
private final FloodgateLogger logger;
|
||||
|
||||
public final void handleSkinUploadFor(FloodgatePlayer player) {
|
||||
uploader.uploadSkin(player.getRawSkin())
|
||||
public final void handleSkinUploadFor(FloodgatePlayer player,
|
||||
BiConsumer<Boolean, String> consumer) {
|
||||
handleSkinUploadFor(player, player.getRawSkin(), consumer);
|
||||
}
|
||||
|
||||
public final void handleSkinUploadFor(FloodgatePlayer player,
|
||||
RawSkin rawSkin,
|
||||
BiConsumer<Boolean, String> consumer) {
|
||||
if (player == null || rawSkin == null) {
|
||||
if (consumer != null) {
|
||||
consumer.accept(true, "Skin or Player is null");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uploader.uploadSkin(rawSkin)
|
||||
.whenComplete((uploadResult, throwable) -> {
|
||||
if (throwable != null) {
|
||||
logger.error(
|
||||
"Failed to upload player skin for " + player.getCorrectUsername(),
|
||||
throwable);
|
||||
|
||||
messageHandler.sendSkinResponse(
|
||||
player.getJavaUniqueId(), throwable.getMessage());
|
||||
if (consumer != null) {
|
||||
consumer.accept(true, throwable.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (uploadResult.getError() != null) {
|
||||
logger.error(format(
|
||||
"Error while uploading player skin for {}: {}",
|
||||
player.getCorrectUsername(), uploadResult.getError()));
|
||||
logger.error("Error while uploading player skin for {}: {}",
|
||||
player.getCorrectUsername(), uploadResult.getError());
|
||||
|
||||
messageHandler.sendSkinResponse(
|
||||
player.getJavaUniqueId(), uploadResult.getError());
|
||||
if (consumer != null) {
|
||||
consumer.accept(true, uploadResult.getError());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Skin upload successful for " + player.getCorrectUsername());
|
||||
logger.info(uploadResult.getResponse().toString());
|
||||
messageHandler.sendSkinResponse(
|
||||
player.getJavaUniqueId(), uploadResult.getResponse().toString());
|
||||
applySkin(player, uploadResult);
|
||||
|
||||
if (consumer != null) {
|
||||
consumer.accept(false, uploadResult.getResponse().toString());
|
||||
}
|
||||
player.addProperty(PropertyKey.SKIN_UPLOADED, uploadResult.getResponse());
|
||||
|
||||
skinApplier.applySkin(player, uploadResult);
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract void applySkin(FloodgatePlayer player, UploadResult result);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.awt.image.BufferedImage;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import javax.annotation.Nonnull;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
@@ -44,7 +45,7 @@ public final class SkinUploader {
|
||||
private final Executor requestExecutor = Executors.newSingleThreadExecutor();
|
||||
private long nextResult = 0;
|
||||
|
||||
public CompletableFuture<UploadResult> uploadSkin(RawSkin rawSkin) {
|
||||
public CompletableFuture<UploadResult> uploadSkin(@Nonnull RawSkin rawSkin) {
|
||||
return CompletableFuture.supplyAsync(() -> uploadSkinInner(rawSkin, 0), requestExecutor);
|
||||
}
|
||||
|
||||
@@ -149,5 +150,9 @@ public final class SkinUploader {
|
||||
|
||||
return new UploadResult(httpCode, null, false, model, skinUrl, capeUrl, response);
|
||||
}
|
||||
|
||||
public static UploadResult success(JsonObject response) {
|
||||
return new UploadResult(200, null, false, null, null, null, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
47
common/src/main/java/org/geysermc/floodgate/util/Utils.java
Normal file
47
common/src/main/java/org/geysermc/floodgate/util/Utils.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 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;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
|
||||
public class Utils {
|
||||
/**
|
||||
* This method is used in Addons.<br> Most addons can be removed once the player associated to
|
||||
* the channel has been logged in, but they should also be removed once the inject is removed.
|
||||
* Because of how Netty works it will throw an exception and we don't want that. This method
|
||||
* removes those handlers safely.
|
||||
*
|
||||
* @param pipeline the pipeline
|
||||
* @param handler the name of the handler to remove
|
||||
*/
|
||||
public static void removeHandler(ChannelPipeline pipeline, String handler) {
|
||||
ChannelHandler channelHandler = pipeline.get(handler);
|
||||
if (channelHandler != null) {
|
||||
pipeline.remove(channelHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
pom.xml
1
pom.xml
@@ -45,6 +45,7 @@
|
||||
|
||||
<properties>
|
||||
<geyser.version>1.2.0-SNAPSHOT</geyser.version>
|
||||
<cumulus.version>1.0-SNAPSHOT</cumulus.version>
|
||||
<spigot.version>1.13-R0.1-SNAPSHOT</spigot.version>
|
||||
<bungee.version>1.15-SNAPSHOT</bungee.version>
|
||||
<velocity.version>1.1.0</velocity.version>
|
||||
|
||||
@@ -26,20 +26,23 @@
|
||||
package org.geysermc.floodgate;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.pluginmessage.SpigotPluginMessageRegister;
|
||||
|
||||
public final class SpigotPlatform extends FloodgatePlatform {
|
||||
@Inject private JavaPlugin plugin;
|
||||
@Inject private Injector guice;
|
||||
|
||||
@Inject
|
||||
public SpigotPlatform(FloodgateApi api, PlatformInjector platformInjector,
|
||||
FloodgateLogger logger) {
|
||||
super(api, platformInjector, logger);
|
||||
FloodgateLogger logger, Injector injector) {
|
||||
super(api, platformInjector, logger, injector);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,7 +50,9 @@ public final class SpigotPlatform extends FloodgatePlatform {
|
||||
boolean success = super.enable(postInitializeModules);
|
||||
if (!success) {
|
||||
Bukkit.getPluginManager().disablePlugin(plugin);
|
||||
return false;
|
||||
}
|
||||
return success;
|
||||
guice.getInstance(SpigotPluginMessageRegister.class).register();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import com.google.inject.Injector;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.module.CommandModule;
|
||||
import org.geysermc.floodgate.module.CommonModule;
|
||||
import org.geysermc.floodgate.module.ServerCommonModule;
|
||||
import org.geysermc.floodgate.module.SpigotAddonModule;
|
||||
import org.geysermc.floodgate.module.SpigotListenerModule;
|
||||
import org.geysermc.floodgate.module.SpigotPlatformModule;
|
||||
@@ -46,7 +46,7 @@ public final class SpigotPlugin extends JavaPlugin {
|
||||
|
||||
long ctm = System.currentTimeMillis();
|
||||
Injector injector = Guice.createInjector(
|
||||
new CommonModule(getDataFolder().toPath()),
|
||||
new ServerCommonModule(getDataFolder().toPath()),
|
||||
new SpigotPlatformModule(this)
|
||||
);
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.geysermc.floodgate.api.inject.InjectorAddon;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
|
||||
public final class SpigotDataAddon implements InjectorAddon {
|
||||
@Inject private HandshakeHandler handshakeHandler;
|
||||
@@ -63,7 +64,7 @@ public final class SpigotDataAddon implements InjectorAddon {
|
||||
|
||||
@Override
|
||||
public void onRemoveInject(Channel channel) {
|
||||
channel.pipeline().remove("floodgate_data_handler");
|
||||
Utils.removeHandler(channel.pipeline(), "floodgate_data_handler");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,6 +48,7 @@ import org.geysermc.floodgate.HandshakeHandler;
|
||||
import org.geysermc.floodgate.HandshakeHandler.HandshakeResult;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||
@@ -180,7 +181,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
||||
networkManager = ctx.channel().pipeline().get("packet_handler");
|
||||
|
||||
String handshakeValue = getCastedValue(packet, HANDSHAKE_HOST);
|
||||
HandshakeResult result = handshakeHandler.handle(handshakeValue);
|
||||
HandshakeResult result = handshakeHandler.handle(ctx.channel(), handshakeValue);
|
||||
switch (result.getResultType()) {
|
||||
case SUCCESS:
|
||||
break;
|
||||
@@ -204,6 +205,8 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
||||
String[] data = result.getHandshakeData();
|
||||
bungeeData = isBungeeData();
|
||||
|
||||
InetSocketAddress correctAddress = fPlayer.getProperty(PropertyKey.SOCKET_ADDRESS);
|
||||
|
||||
if (bungeeData) {
|
||||
setValue(packet, HANDSHAKE_HOST, data[0] + '\0' +
|
||||
bedrockData.getIp() + '\0' +
|
||||
@@ -213,12 +216,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
||||
// Use a spoofedUUID for initUUID (just like Bungeecord)
|
||||
setValue(networkManager, "spoofedUUID", fPlayer.getCorrectUniqueId());
|
||||
// Use the player his IP for stuff instead of Geyser his IP
|
||||
SocketAddress newAddress = new InetSocketAddress(
|
||||
bedrockData.getIp(),
|
||||
((InetSocketAddress) ctx.channel().remoteAddress()).getPort()
|
||||
);
|
||||
|
||||
setValue(networkManager, SOCKET_ADDRESS, newAddress);
|
||||
setValue(networkManager, SOCKET_ADDRESS, correctAddress);
|
||||
}
|
||||
} else if (isLogin) {
|
||||
if (!bungeeData) {
|
||||
|
||||
@@ -38,12 +38,12 @@ import org.geysermc.floodgate.FloodgatePlayerImpl;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.skin.SkinHandler;
|
||||
import org.geysermc.floodgate.skin.ServerSkinHandler;
|
||||
import org.geysermc.floodgate.util.LanguageManager;
|
||||
|
||||
public final class SpigotListener implements Listener {
|
||||
@Inject private SimpleFloodgateApi api;
|
||||
@Inject private SkinHandler skinHandler;
|
||||
@Inject private ServerSkinHandler skinHandler;
|
||||
@Inject private LanguageManager languageManager;
|
||||
@Inject private FloodgateLogger logger;
|
||||
|
||||
|
||||
@@ -33,10 +33,9 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.floodgate.SpigotPlugin;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.command.SpigotCommandRegistration;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||
import org.geysermc.floodgate.inject.spigot.SpigotInjector;
|
||||
@@ -47,8 +46,10 @@ import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.platform.listener.ListenerRegistration;
|
||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||
import org.geysermc.floodgate.pluginmessage.SpigotPluginMessageHandler;
|
||||
import org.geysermc.floodgate.pluginmessage.SpigotSkinHandler;
|
||||
import org.geysermc.floodgate.skin.SkinHandler;
|
||||
import org.geysermc.floodgate.pluginmessage.SpigotPluginMessageRegister;
|
||||
import org.geysermc.floodgate.pluginmessage.SpigotSkinApplier;
|
||||
import org.geysermc.floodgate.skin.ServerSkinHandler;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.util.LanguageManager;
|
||||
import org.geysermc.floodgate.util.SpigotCommandUtil;
|
||||
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
|
||||
@@ -57,25 +58,17 @@ import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
|
||||
public final class SpigotPlatformModule extends AbstractModule {
|
||||
private final SpigotPlugin plugin;
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(PluginMessageHandler.class).to(SpigotPluginMessageHandler.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public JavaPlugin javaPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("configClass")
|
||||
public Class<? extends FloodgateConfig> floodgateConfigClass() {
|
||||
return FloodgateConfig.class;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public SimpleFloodgateApi floodgateApi(PluginMessageHandler pluginMessageHandler) {
|
||||
return new SimpleFloodgateApi(pluginMessageHandler);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public FloodgateLogger floodgateLogger(LanguageManager languageManager) {
|
||||
@@ -90,7 +83,8 @@ public final class SpigotPlatformModule extends AbstractModule {
|
||||
@Singleton
|
||||
public CommandRegistration commandRegistration(
|
||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||
CommandUtil commandUtil) {
|
||||
CommandUtil commandUtil
|
||||
) {
|
||||
return new SpigotCommandRegistration(versionSpecificMethods, plugin, commandUtil);
|
||||
}
|
||||
|
||||
@@ -106,24 +100,6 @@ public final class SpigotPlatformModule extends AbstractModule {
|
||||
return new SpigotListenerRegistration(plugin);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public PluginMessageHandler pluginMessageHandler(FloodgateConfigHolder configHolder,
|
||||
@Named("formChannel") String formChannel,
|
||||
@Named("skinChannel") String skinChannel) {
|
||||
return new SpigotPluginMessageHandler(configHolder, plugin, formChannel, skinChannel);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public SkinHandler skinHandler(PluginMessageHandler messageHandler, FloodgateLogger logger,
|
||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||
FloodgateConfigHolder configHolder) {
|
||||
return new SpigotSkinHandler(
|
||||
messageHandler, logger, versionSpecificMethods, plugin, configHolder
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
DebugAddon / PlatformInjector
|
||||
*/
|
||||
@@ -157,4 +133,47 @@ public final class SpigotPlatformModule extends AbstractModule {
|
||||
public String implementationName() {
|
||||
return "Spigot";
|
||||
}
|
||||
|
||||
/*
|
||||
Others
|
||||
*/
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public SpigotPluginMessageHandler pluginMessageHandler(
|
||||
FloodgateConfigHolder configHolder,
|
||||
@Named("formChannel") String formChannel,
|
||||
@Named("skinChannel") String skinChannel
|
||||
) {
|
||||
return new SpigotPluginMessageHandler(configHolder, plugin, formChannel, skinChannel);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public SpigotPluginMessageRegister pluginMessageRegister(
|
||||
FloodgateApi api,
|
||||
@Named("formChannel") String formChannel,
|
||||
@Named("skinChannel") String skinChannel,
|
||||
SpigotPluginMessageHandler pluginMessageHandler,
|
||||
ServerSkinHandler skinHandler,
|
||||
FloodgateLogger logger
|
||||
) {
|
||||
return new SpigotPluginMessageRegister(plugin, api, formChannel, skinChannel,
|
||||
pluginMessageHandler, skinHandler, logger);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public SkinApplier skinApplier(
|
||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||
FloodgateConfigHolder configHolder
|
||||
) {
|
||||
return new SpigotSkinApplier(versionSpecificMethods, plugin, configHolder);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public SpigotVersionSpecificMethods versionSpecificMethods() {
|
||||
return new SpigotVersionSpecificMethods(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,47 +25,28 @@
|
||||
|
||||
package org.geysermc.floodgate.pluginmessage;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.messaging.Messenger;
|
||||
import org.geysermc.cumulus.Form;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||
import org.geysermc.floodgate.util.RawSkin;
|
||||
|
||||
public class SpigotPluginMessageHandler extends PluginMessageHandler {
|
||||
private final JavaPlugin plugin;
|
||||
private final String formChannel;
|
||||
private final String skinChannel;
|
||||
|
||||
public SpigotPluginMessageHandler(FloodgateConfigHolder configHolder, JavaPlugin plugin,
|
||||
String formChannel, String skinChannel) {
|
||||
public SpigotPluginMessageHandler(
|
||||
FloodgateConfigHolder configHolder,
|
||||
JavaPlugin plugin,
|
||||
String formChannel,
|
||||
String skinChannel
|
||||
) {
|
||||
super(configHolder);
|
||||
this.plugin = plugin;
|
||||
this.formChannel = formChannel;
|
||||
this.skinChannel = skinChannel;
|
||||
|
||||
Messenger messenger = plugin.getServer().getMessenger();
|
||||
|
||||
// form
|
||||
messenger.registerIncomingPluginChannel(
|
||||
plugin, formChannel,
|
||||
(channel, player, message) -> callResponseConsumer(message));
|
||||
messenger.registerOutgoingPluginChannel(plugin, formChannel);
|
||||
|
||||
// skin
|
||||
messenger.registerIncomingPluginChannel(
|
||||
plugin, skinChannel,
|
||||
(channel, player, message) -> {
|
||||
String origin =
|
||||
FloodgateApi.getInstance().getPlayer(player.getUniqueId()) != null
|
||||
? "Geyser" : "player";
|
||||
System.out.println("Got skin from " + origin + "!");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,22 +62,9 @@ public class SpigotPluginMessageHandler extends PluginMessageHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendSkinRequest(UUID playerId, RawSkin skin) {
|
||||
public void sendSkinResponse(UUID playerId, boolean failed, String response) {
|
||||
try {
|
||||
byte[] skinData = skin.toString().getBytes(Charsets.UTF_8);
|
||||
Bukkit.getPlayer(playerId).sendPluginMessage(plugin, skinChannel, skinData);
|
||||
//todo use json or something to split request and response
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSkinResponse(UUID playerId, String response) {
|
||||
try {
|
||||
byte[] responseData = response.getBytes(Charsets.UTF_8);
|
||||
byte[] responseData = createSkinResponseData(failed, response);
|
||||
Bukkit.getPlayer(playerId).sendPluginMessage(plugin, skinChannel, responseData);
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 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.pluginmessage;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.messaging.Messenger;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.skin.ServerSkinHandler;
|
||||
import org.geysermc.floodgate.util.Base64Utils;
|
||||
import org.geysermc.floodgate.util.RawSkin;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class SpigotPluginMessageRegister {
|
||||
private final JavaPlugin plugin;
|
||||
private final FloodgateApi api;
|
||||
private final String formChannel;
|
||||
private final String skinChannel;
|
||||
private final SpigotPluginMessageHandler pluginMessageHandler;
|
||||
private final ServerSkinHandler skinHandler;
|
||||
private final FloodgateLogger logger;
|
||||
|
||||
public void register() {
|
||||
Messenger messenger = plugin.getServer().getMessenger();
|
||||
|
||||
// form
|
||||
messenger.registerIncomingPluginChannel(
|
||||
plugin, formChannel,
|
||||
(channel, player, message) ->
|
||||
pluginMessageHandler.callResponseConsumer(message));
|
||||
|
||||
messenger.registerOutgoingPluginChannel(plugin, formChannel);
|
||||
|
||||
// skin
|
||||
messenger.registerIncomingPluginChannel(
|
||||
plugin, skinChannel,
|
||||
(channel, player, message) -> {
|
||||
//todo make a Proxy and a Server class for this?
|
||||
FloodgatePlayer floodgatePlayer = api.getPlayer(player.getUniqueId());
|
||||
if (floodgatePlayer == null) {
|
||||
logKick(player, "Non-Floodgate player sent a Skin plugin message.");
|
||||
return;
|
||||
}
|
||||
|
||||
// non-proxy servers can only handle requests (from proxies)
|
||||
|
||||
if (!floodgatePlayer.isFromProxy()) {
|
||||
logKick(player, "Cannot receive Skin request from Player.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 1 byte for isRequest and 9 for RawSkin itself
|
||||
if (message.length < Base64Utils.getEncodedLength(9 + 1)) {
|
||||
logKick(player, "Skin request data has to be at least 10 byte long.");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean request = message[0] == 1;
|
||||
|
||||
if (!request) {
|
||||
logKick(player, "Proxy sent a response instead of a request?");
|
||||
return;
|
||||
}
|
||||
|
||||
RawSkin rawSkin = null;
|
||||
try {
|
||||
rawSkin = RawSkin.decode(message, 1);
|
||||
} catch (Exception exception) {
|
||||
logger.error("Failed to decode RawSkin", exception);
|
||||
}
|
||||
// we let it continue since SkinHandler sends the plugin message for us
|
||||
skinHandler.handleSkinUploadFor(floodgatePlayer, rawSkin);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void logKick(Player player, String reason) {
|
||||
logger.error(reason + " Closing connection for " + player.getName());
|
||||
player.kickPlayer(reason);
|
||||
}
|
||||
}
|
||||
@@ -33,16 +33,14 @@ import java.lang.reflect.Method;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.geysermc.floodgate.SpigotPlugin;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||
import org.geysermc.floodgate.skin.SkinHandler;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinUploader.UploadResult;
|
||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
|
||||
|
||||
public class SpigotSkinHandler extends SkinHandler {
|
||||
public final class SpigotSkinApplier implements SkinApplier {
|
||||
private static final Method GET_PROFILE_METHOD;
|
||||
|
||||
static {
|
||||
@@ -56,17 +54,18 @@ public class SpigotSkinHandler extends SkinHandler {
|
||||
private final SpigotPlugin plugin;
|
||||
private final FloodgateConfigHolder configHolder;
|
||||
|
||||
public SpigotSkinHandler(PluginMessageHandler messageHandler, FloodgateLogger logger,
|
||||
public SpigotSkinApplier(
|
||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||
SpigotPlugin plugin, FloodgateConfigHolder configHolder) {
|
||||
super(messageHandler, logger);
|
||||
SpigotPlugin plugin,
|
||||
FloodgateConfigHolder configHolder
|
||||
) {
|
||||
this.versionSpecificMethods = versionSpecificMethods;
|
||||
this.plugin = plugin;
|
||||
this.configHolder = configHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applySkin(FloodgatePlayer floodgatePlayer, UploadResult result) {
|
||||
public void applySkin(FloodgatePlayer floodgatePlayer, UploadResult result) {
|
||||
Player player = Bukkit.getPlayer(floodgatePlayer.getCorrectUniqueId());
|
||||
GameProfile profile = ReflectionUtils.castedInvoke(player, GET_PROFILE_METHOD);
|
||||
|
||||
@@ -89,7 +88,7 @@ public class SpigotSkinHandler extends SkinHandler {
|
||||
if (configHolder.get().isApplySkinDirectly()) {
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
if (p != player) {
|
||||
if (p != player && p.canSee(player)) {
|
||||
versionSpecificMethods.hidePlayer(p, player);
|
||||
versionSpecificMethods.showPlayer(p, player);
|
||||
}
|
||||
@@ -33,7 +33,7 @@ import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||
import java.nio.file.Path;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.module.CommandModule;
|
||||
import org.geysermc.floodgate.module.CommonModule;
|
||||
import org.geysermc.floodgate.module.ProxyCommonModule;
|
||||
import org.geysermc.floodgate.module.VelocityAddonModule;
|
||||
import org.geysermc.floodgate.module.VelocityListenerModule;
|
||||
import org.geysermc.floodgate.module.VelocityPlatformModule;
|
||||
@@ -48,7 +48,7 @@ public final class VelocityPlugin {
|
||||
|
||||
long ctm = System.currentTimeMillis();
|
||||
Injector injector = guice.createChildInjector(
|
||||
new CommonModule(dataDirectory),
|
||||
new ProxyCommonModule(dataDirectory),
|
||||
new VelocityPlatformModule()
|
||||
);
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.geysermc.floodgate.api.inject.InjectorAddon;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
|
||||
public final class VelocityDataAddon implements InjectorAddon {
|
||||
@Inject private HandshakeHandler handshakeHandler;
|
||||
@@ -84,7 +85,7 @@ public final class VelocityDataAddon implements InjectorAddon {
|
||||
|
||||
@Override
|
||||
public void onRemoveInject(Channel channel) {
|
||||
channel.pipeline().remove("floodgate_data_handler");
|
||||
Utils.removeHandler(channel.pipeline(), "floodgate_data_handler");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -89,7 +89,7 @@ public final class VelocityProxyDataHandler extends SimpleChannelInboundHandler<
|
||||
private void handleClientToProxy(ChannelHandlerContext ctx, Object packet) {
|
||||
String address = getCastedValue(packet, HANDSHAKE_SERVER_ADDRESS);
|
||||
|
||||
HandshakeResult result = handshakeHandler.handle(address);
|
||||
HandshakeResult result = handshakeHandler.handle(ctx.channel(), address);
|
||||
switch (result.getResultType()) {
|
||||
case SUCCESS:
|
||||
break;
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
package org.geysermc.floodgate.listener;
|
||||
|
||||
import static org.geysermc.floodgate.util.MessageFormatter.format;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
@@ -98,9 +96,8 @@ public class VelocityPluginMessageHandler extends PluginMessageHandler {
|
||||
event.setResult(ForwardResult.handled());
|
||||
|
||||
if (!callResponseConsumer(data)) {
|
||||
logger.error(format(
|
||||
"Couldn't find stored form with id {} for player {}",
|
||||
formId, ((Player) source).getUsername()));
|
||||
logger.error("Couldn't find stored form with id {} for player {}",
|
||||
formId, ((Player) source).getUsername());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,9 +116,4 @@ public class VelocityPluginMessageHandler extends PluginMessageHandler {
|
||||
public boolean sendSkinRequest(UUID player, RawSkin skin) {
|
||||
return false; //todo
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSkinResponse(UUID player, String response) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user