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();
|
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.
|
* Returns the LinkedPlayer object if the player is linked to a Java account.
|
||||||
*/
|
*/
|
||||||
@@ -115,6 +120,18 @@ public interface FloodgatePlayer {
|
|||||||
return sendForm(formBuilder.build());
|
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.
|
* 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>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>com.github.SpigotMC.BungeeCord</groupId>
|
||||||
<artifactId>bungeecord-protocol</artifactId>
|
<artifactId>bungeecord-proxy</artifactId>
|
||||||
<version>${bungee.version}</version>
|
<version>master-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -88,5 +88,9 @@
|
|||||||
<id>bungeecord-repo</id>
|
<id>bungeecord-repo</id>
|
||||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>jitpack</id>
|
||||||
|
<url>https://jitpack.io</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
</project>
|
</project>
|
||||||
@@ -33,7 +33,7 @@ import org.geysermc.floodgate.module.BungeeAddonModule;
|
|||||||
import org.geysermc.floodgate.module.BungeeListenerModule;
|
import org.geysermc.floodgate.module.BungeeListenerModule;
|
||||||
import org.geysermc.floodgate.module.BungeePlatformModule;
|
import org.geysermc.floodgate.module.BungeePlatformModule;
|
||||||
import org.geysermc.floodgate.module.CommandModule;
|
import org.geysermc.floodgate.module.CommandModule;
|
||||||
import org.geysermc.floodgate.module.CommonModule;
|
import org.geysermc.floodgate.module.ProxyCommonModule;
|
||||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||||
|
|
||||||
public final class BungeePlugin extends Plugin {
|
public final class BungeePlugin extends Plugin {
|
||||||
@@ -45,7 +45,7 @@ public final class BungeePlugin extends Plugin {
|
|||||||
|
|
||||||
long ctm = System.currentTimeMillis();
|
long ctm = System.currentTimeMillis();
|
||||||
Injector injector = Guice.createInjector(
|
Injector injector = Guice.createInjector(
|
||||||
new CommonModule(getDataFolder().toPath()),
|
new ProxyCommonModule(getDataFolder().toPath()),
|
||||||
new BungeePlatformModule(this)
|
new BungeePlatformModule(this)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import org.geysermc.floodgate.HandshakeHandler.HandshakeResult;
|
|||||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||||
import org.geysermc.floodgate.util.BedrockData;
|
import org.geysermc.floodgate.util.BedrockData;
|
||||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||||
@@ -97,7 +98,12 @@ public final class BungeeDataHandler {
|
|||||||
event.getConnection(), EXTRA_HANDSHAKE_DATA
|
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()) {
|
switch (result.getResultType()) {
|
||||||
case EXCEPTION:
|
case EXCEPTION:
|
||||||
event.setCancelReason(config.getDisconnect().getInvalidKey());
|
event.setCancelReason(config.getDisconnect().getInvalidKey());
|
||||||
@@ -117,7 +123,13 @@ public final class BungeeDataHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FloodgatePlayer player = result.getFloodgatePlayer();
|
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().setOnlineMode(false);
|
||||||
event.getConnection().setUniqueId(player.getCorrectUniqueId());
|
event.getConnection().setUniqueId(player.getCorrectUniqueId());
|
||||||
@@ -126,9 +138,6 @@ public final class BungeeDataHandler {
|
|||||||
event.getConnection(), PLAYER_NAME, player.getCorrectUsername()
|
event.getConnection(), PLAYER_NAME, player.getCorrectUsername()
|
||||||
);
|
);
|
||||||
|
|
||||||
Object channelWrapper =
|
|
||||||
ReflectionUtils.getValue(event.getConnection(), PLAYER_CHANNEL_WRAPPER);
|
|
||||||
|
|
||||||
SocketAddress remoteAddress =
|
SocketAddress remoteAddress =
|
||||||
ReflectionUtils.getCastedValue(channelWrapper, PLAYER_REMOTE_ADDRESS);
|
ReflectionUtils.getCastedValue(channelWrapper, PLAYER_REMOTE_ADDRESS);
|
||||||
|
|
||||||
@@ -137,15 +146,15 @@ public final class BungeeDataHandler {
|
|||||||
"Ignoring the player, I guess.",
|
"Ignoring the player, I guess.",
|
||||||
player.getUsername(), remoteAddress.getClass().getSimpleName()
|
player.getUsername(), remoteAddress.getClass().getSimpleName()
|
||||||
);
|
);
|
||||||
} else {
|
event.setCancelled(true);
|
||||||
int port = ((InetSocketAddress) remoteAddress).getPort();
|
event.setCancelReason(
|
||||||
ReflectionUtils.setValue(
|
new TextComponent("remoteAddress is not an InetSocketAddress!"));
|
||||||
channelWrapper, PLAYER_REMOTE_ADDRESS,
|
event.completeIntent(plugin);
|
||||||
new InetSocketAddress(result.getBedrockData().getIp(), port)
|
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);
|
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.PlayerDisconnectEvent;
|
||||||
import net.md_5.bungee.api.event.PreLoginEvent;
|
import net.md_5.bungee.api.event.PreLoginEvent;
|
||||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
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.api.plugin.Listener;
|
||||||
import net.md_5.bungee.event.EventHandler;
|
import net.md_5.bungee.event.EventHandler;
|
||||||
import net.md_5.bungee.event.EventPriority;
|
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.ProxyFloodgateApi;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||||
import org.geysermc.floodgate.handler.BungeeDataHandler;
|
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;
|
import org.geysermc.floodgate.util.LanguageManager;
|
||||||
|
|
||||||
public final class BungeeListener implements Listener {
|
public final class BungeeListener implements Listener {
|
||||||
@@ -49,6 +53,10 @@ public final class BungeeListener implements Listener {
|
|||||||
@Inject private LanguageManager languageManager;
|
@Inject private LanguageManager languageManager;
|
||||||
@Inject private FloodgateLogger logger;
|
@Inject private FloodgateLogger logger;
|
||||||
|
|
||||||
|
@Inject private ProxyFloodgateConfig config;
|
||||||
|
@Inject private PluginMessageHandler pluginMessageHandler;
|
||||||
|
@Inject private SkinHandler skinHandler;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void init(Injector injector) {
|
public void init(Injector injector) {
|
||||||
dataHandler = injector.getInstance(BungeeDataHandler.class);
|
dataHandler = injector.getInstance(BungeeDataHandler.class);
|
||||||
@@ -59,6 +67,24 @@ public final class BungeeListener implements Listener {
|
|||||||
dataHandler.handleServerConnect(event.getPlayer());
|
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)
|
@EventHandler(priority = EventPriority.LOW)
|
||||||
public void onPreLogin(PreLoginEvent event) {
|
public void onPreLogin(PreLoginEvent event) {
|
||||||
dataHandler.handlePreLogin(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.Listener;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import org.geysermc.floodgate.BungeePlugin;
|
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.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.command.BungeeCommandRegistration;
|
import org.geysermc.floodgate.command.BungeeCommandRegistration;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
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.CommonPlatformInjector;
|
||||||
import org.geysermc.floodgate.inject.bungee.BungeeInjector;
|
import org.geysermc.floodgate.inject.bungee.BungeeInjector;
|
||||||
import org.geysermc.floodgate.listener.BungeeListenerRegistration;
|
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.listener.ListenerRegistration;
|
||||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||||
import org.geysermc.floodgate.pluginmessage.BungeePluginMessageHandler;
|
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.BungeeCommandUtil;
|
||||||
import org.geysermc.floodgate.util.LanguageManager;
|
import org.geysermc.floodgate.util.LanguageManager;
|
||||||
|
|
||||||
@@ -57,31 +55,12 @@ import org.geysermc.floodgate.util.LanguageManager;
|
|||||||
public final class BungeePlatformModule extends AbstractModule {
|
public final class BungeePlatformModule extends AbstractModule {
|
||||||
private final BungeePlugin plugin;
|
private final BungeePlugin plugin;
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
bind(SimpleFloodgateApi.class).to(ProxyFloodgateApi.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public Plugin bungeePlugin() {
|
public Plugin bungeePlugin() {
|
||||||
return plugin;
|
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
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public FloodgateLogger floodgateLogger(LanguageManager languageManager) {
|
public FloodgateLogger floodgateLogger(LanguageManager languageManager) {
|
||||||
@@ -117,6 +96,18 @@ public final class BungeePlatformModule extends AbstractModule {
|
|||||||
return new BungeePluginMessageHandler(configHolder);
|
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
|
DebugAddon / PlatformInjector
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -25,10 +25,12 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.pluginmessage;
|
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.Inject;
|
||||||
import com.google.inject.name.Named;
|
import com.google.inject.name.Named;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
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.api.plugin.Plugin;
|
||||||
import net.md_5.bungee.event.EventHandler;
|
import net.md_5.bungee.event.EventHandler;
|
||||||
import org.geysermc.cumulus.Form;
|
import org.geysermc.cumulus.Form;
|
||||||
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
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;
|
import org.geysermc.floodgate.util.RawSkin;
|
||||||
|
|
||||||
public final class BungeePluginMessageHandler extends PluginMessageHandler implements Listener {
|
public final class BungeePluginMessageHandler extends PluginMessageHandler implements Listener {
|
||||||
private ProxyServer proxy;
|
private ProxyServer proxy;
|
||||||
private FloodgateLogger logger;
|
private FloodgateLogger logger;
|
||||||
private String formChannel;
|
private String formChannel;
|
||||||
|
private String skinChannel;
|
||||||
|
private FloodgateApi api;
|
||||||
|
private SkinApplier skinApplier;
|
||||||
|
|
||||||
public BungeePluginMessageHandler(FloodgateConfigHolder configHolder) {
|
public BungeePluginMessageHandler(FloodgateConfigHolder configHolder) {
|
||||||
super(configHolder);
|
super(configHolder);
|
||||||
@@ -57,10 +66,14 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple
|
|||||||
@Inject // called because this is a listener as well
|
@Inject // called because this is a listener as well
|
||||||
public void init(Plugin plugin, FloodgateLogger logger,
|
public void init(Plugin plugin, FloodgateLogger logger,
|
||||||
@Named("formChannel") String formChannel,
|
@Named("formChannel") String formChannel,
|
||||||
@Named("skinChannel") String skinChannel) {
|
@Named("skinChannel") String skinChannel,
|
||||||
|
FloodgateApi api, SkinApplier skinApplier) {
|
||||||
this.proxy = plugin.getProxy();
|
this.proxy = plugin.getProxy();
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.formChannel = formChannel;
|
this.formChannel = formChannel;
|
||||||
|
this.skinChannel = skinChannel;
|
||||||
|
this.api = api;
|
||||||
|
this.skinApplier = skinApplier;
|
||||||
|
|
||||||
proxy.registerChannel(formChannel);
|
proxy.registerChannel(formChannel);
|
||||||
proxy.registerChannel(skinChannel);
|
proxy.registerChannel(skinChannel);
|
||||||
@@ -69,6 +82,7 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPluginMessage(PluginMessageEvent event) {
|
public void onPluginMessage(PluginMessageEvent event) {
|
||||||
Connection source = event.getSender();
|
Connection source = event.getSender();
|
||||||
|
|
||||||
if (event.getTag().equals(formChannel)) {
|
if (event.getTag().equals(formChannel)) {
|
||||||
if (source instanceof Server) {
|
if (source instanceof Server) {
|
||||||
// send it to the client
|
// send it to the client
|
||||||
@@ -79,8 +93,7 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple
|
|||||||
if (source instanceof ProxiedPlayer) {
|
if (source instanceof ProxiedPlayer) {
|
||||||
byte[] data = event.getData();
|
byte[] data = event.getData();
|
||||||
if (data.length < 2) {
|
if (data.length < 2) {
|
||||||
logger.error("Invalid form response! Closing connection");
|
logKick(source, "Invalid form response!");
|
||||||
source.disconnect(new TextComponent("Invalid form response!"));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,12 +108,73 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple
|
|||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
|
|
||||||
if (!callResponseConsumer(data)) {
|
if (!callResponseConsumer(data)) {
|
||||||
logger.error(format(
|
logger.error("Couldn't find stored form with id {} for player {}",
|
||||||
"Couldn't find stored form with id {} for player {}",
|
formId, ((ProxiedPlayer) source).getName());
|
||||||
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
|
@Override
|
||||||
@@ -114,12 +188,12 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sendSkinRequest(UUID player, RawSkin skin) {
|
public boolean sendSkinRequest(UUID uuid, RawSkin skin) {
|
||||||
return false; //todo
|
ProxiedPlayer player = proxy.getPlayer(uuid);
|
||||||
|
if (player != null) {
|
||||||
|
player.sendData(skinChannel, createSkinRequestData(skin.encode()));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
@Override
|
|
||||||
public void sendSkinResponse(UUID player, String response) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
<artifactId>api</artifactId>
|
||||||
<version>${project.parent.version}</version>
|
<version>${project.parent.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.geysermc.cumulus</groupId>
|
||||||
|
<artifactId>cumulus</artifactId>
|
||||||
|
<version>${cumulus.version}</version>
|
||||||
|
</dependency>
|
||||||
<!-- <dependency> todo -->
|
<!-- <dependency> todo -->
|
||||||
<!-- <groupId>com.mojang</groupId>-->
|
<!-- <groupId>com.mojang</groupId>-->
|
||||||
<!-- <artifactId>brigadier</artifactId>-->
|
<!-- <artifactId>brigadier</artifactId>-->
|
||||||
@@ -64,12 +69,6 @@
|
|||||||
<version>1.27</version>
|
<version>1.27</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.gson</groupId>
|
|
||||||
<artifactId>gson</artifactId>
|
|
||||||
<version>2.8.5</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<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.FloodgateConfigHolder;
|
||||||
import org.geysermc.floodgate.config.loader.ConfigLoader;
|
import org.geysermc.floodgate.config.loader.ConfigLoader;
|
||||||
import org.geysermc.floodgate.link.PlayerLinkLoader;
|
import org.geysermc.floodgate.link.PlayerLinkLoader;
|
||||||
import org.geysermc.floodgate.module.ConfigLoadedModule;
|
|
||||||
import org.geysermc.floodgate.module.PostInitializeModule;
|
import org.geysermc.floodgate.module.PostInitializeModule;
|
||||||
|
|
||||||
public class FloodgatePlatform {
|
public class FloodgatePlatform {
|
||||||
@@ -56,16 +55,16 @@ public class FloodgatePlatform {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public FloodgatePlatform(FloodgateApi api, PlatformInjector platformInjector,
|
public FloodgatePlatform(FloodgateApi api, PlatformInjector platformInjector,
|
||||||
FloodgateLogger logger) {
|
FloodgateLogger logger, Injector guice) {
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.injector = platformInjector;
|
this.injector = platformInjector;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
|
this.guice = guice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public void init(@Named("dataDirectory") Path dataDirectory, ConfigLoader configLoader,
|
public void init(@Named("dataDirectory") Path dataDirectory, ConfigLoader configLoader,
|
||||||
PlayerLinkLoader playerLinkLoader, FloodgateConfigHolder configHolder,
|
PlayerLinkLoader playerLinkLoader, FloodgateConfigHolder configHolder) {
|
||||||
Injector injector) {
|
|
||||||
|
|
||||||
if (!Files.isDirectory(dataDirectory)) {
|
if (!Files.isDirectory(dataDirectory)) {
|
||||||
try {
|
try {
|
||||||
@@ -84,9 +83,6 @@ public class FloodgatePlatform {
|
|||||||
configHolder.set(config);
|
configHolder.set(config);
|
||||||
PlayerLink link = playerLinkLoader.load();
|
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);
|
InstanceHolder.setInstance(api, link, this.injector, KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate;
|
package org.geysermc.floodgate;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
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.ProxyFloodgateApi;
|
||||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
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.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||||
import org.geysermc.floodgate.util.BedrockData;
|
import org.geysermc.floodgate.util.BedrockData;
|
||||||
@@ -48,11 +51,11 @@ import org.geysermc.floodgate.util.UiProfile;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
||||||
private final String version;
|
private final String version;
|
||||||
private final String username;
|
private final String username;
|
||||||
private final String javaUsername;
|
private final String javaUsername;
|
||||||
//todo maybe add a map for platform specific things
|
|
||||||
private final UUID javaUniqueId;
|
private final UUID javaUniqueId;
|
||||||
private final String xuid;
|
private final String xuid;
|
||||||
private final DeviceOs deviceOs;
|
private final DeviceOs deviceOs;
|
||||||
@@ -60,10 +63,13 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
|||||||
private final UiProfile uiProfile;
|
private final UiProfile uiProfile;
|
||||||
private final InputMode inputMode;
|
private final InputMode inputMode;
|
||||||
private final String ip;
|
private final String ip;
|
||||||
private final boolean fromProxy; //todo remove hasBungeeData
|
private final boolean fromProxy;
|
||||||
private final LinkedPlayer linkedPlayer;
|
private final LinkedPlayer linkedPlayer;
|
||||||
private final RawSkin rawSkin;
|
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
|
* 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());
|
UiProfile uiProfile = UiProfile.getById(data.getUiProfile());
|
||||||
InputMode inputMode = InputMode.getById(data.getInputMode());
|
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;
|
LinkedPlayer linkedPlayer;
|
||||||
|
|
||||||
// we'll use the LinkedPlayer provided by Bungee or Velocity (if they included one)
|
// 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(),
|
deviceOs, data.getLanguageCode(), uiProfile, inputMode, data.getIp(),
|
||||||
data.isFromProxy(), linkedPlayer, skin);
|
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...
|
// We have to update it...
|
||||||
if (linkedPlayer != null && api instanceof ProxyFloodgateApi) {
|
if (linkedPlayer != null && api instanceof ProxyFloodgateApi) {
|
||||||
InstanceHolder.castApi(ProxyFloodgateApi.class)
|
InstanceHolder.castApi(ProxyFloodgateApi.class)
|
||||||
@@ -112,14 +124,6 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
|||||||
return player;
|
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.
|
* Fetch and return the LinkedPlayer object associated to the player if the player is linked.
|
||||||
* Please note that this method loads the LinkedPlayer synchronously.
|
* Please note that this method loads the LinkedPlayer synchronously.
|
||||||
@@ -154,9 +158,108 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
|||||||
CompletableFuture.completedFuture(null);
|
CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UUID getCorrectUniqueId() {
|
||||||
|
return linkedPlayer != null ? linkedPlayer.getJavaUniqueId() : javaUniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCorrectUsername() {
|
||||||
|
return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername;
|
||||||
|
}
|
||||||
|
|
||||||
public BedrockData toBedrockData() {
|
public BedrockData toBedrockData() {
|
||||||
return BedrockData.of(
|
return BedrockData.of(
|
||||||
version, username, xuid, deviceOs.ordinal(), languageCode,
|
version, username, xuid, deviceOs.ordinal(), languageCode,
|
||||||
uiProfile.ordinal(), inputMode.ordinal(), ip, linkedPlayer, fromProxy);
|
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 static org.geysermc.floodgate.util.BedrockData.EXPECTED_LENGTH;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -35,6 +37,7 @@ import lombok.NonNull;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||||
import org.geysermc.floodgate.crypto.AesCipher;
|
import org.geysermc.floodgate.crypto.AesCipher;
|
||||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||||
@@ -48,7 +51,7 @@ public final class HandshakeHandler {
|
|||||||
private final FloodgateCipher cipher;
|
private final FloodgateCipher cipher;
|
||||||
private final FloodgateConfigHolder configHolder;
|
private final FloodgateConfigHolder configHolder;
|
||||||
|
|
||||||
public HandshakeResult handle(@NonNull String handshakeData) {
|
public HandshakeResult handle(Channel channel, @NonNull String handshakeData) {
|
||||||
try {
|
try {
|
||||||
String[] dataArray = handshakeData.split("\0");
|
String[] dataArray = handshakeData.split("\0");
|
||||||
|
|
||||||
@@ -95,11 +98,13 @@ public final class HandshakeHandler {
|
|||||||
rawSkin = RawSkin.decode(rawSkinData);
|
rawSkin = RawSkin.decode(rawSkinData);
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println(rawSkin);
|
|
||||||
|
|
||||||
FloodgatePlayer player = FloodgatePlayerImpl.from(bedrockData, rawSkin, configHolder);
|
FloodgatePlayer player = FloodgatePlayerImpl.from(bedrockData, rawSkin, configHolder);
|
||||||
api.addPlayer(player.getJavaUniqueId(), player);
|
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);
|
return new HandshakeResult(ResultType.SUCCESS, dataArray, bedrockData, player);
|
||||||
} catch (InvalidFormatException formatException) {
|
} catch (InvalidFormatException formatException) {
|
||||||
// only header exceptions should return 'not floodgate data',
|
// only header exceptions should return 'not floodgate data',
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ package org.geysermc.floodgate.addon;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandler;
|
|
||||||
import org.geysermc.floodgate.addon.addonmanager.AddonManagerHandler;
|
import org.geysermc.floodgate.addon.addonmanager.AddonManagerHandler;
|
||||||
import org.geysermc.floodgate.api.inject.InjectorAddon;
|
import org.geysermc.floodgate.api.inject.InjectorAddon;
|
||||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||||
|
import org.geysermc.floodgate.util.Utils;
|
||||||
|
|
||||||
public final class AddonManagerAddon implements InjectorAddon {
|
public final class AddonManagerAddon implements InjectorAddon {
|
||||||
@Inject private CommonPlatformInjector injector;
|
@Inject private CommonPlatformInjector injector;
|
||||||
@@ -47,10 +47,7 @@ public final class AddonManagerAddon implements InjectorAddon {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRemoveInject(Channel channel) {
|
public void onRemoveInject(Channel channel) {
|
||||||
ChannelHandler handler = channel.pipeline().get("floodgate_addon");
|
Utils.removeHandler(channel.pipeline(), "floodgate_addon");
|
||||||
if (handler != null) {
|
|
||||||
channel.pipeline().remove(handler);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.geysermc.floodgate.addon.debug.ChannelOutDebugHandler;
|
|||||||
import org.geysermc.floodgate.api.inject.InjectorAddon;
|
import org.geysermc.floodgate.api.inject.InjectorAddon;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||||
|
import org.geysermc.floodgate.util.Utils;
|
||||||
|
|
||||||
public final class DebugAddon implements InjectorAddon {
|
public final class DebugAddon implements InjectorAddon {
|
||||||
@Inject private FloodgateConfig config;
|
@Inject private FloodgateConfig config;
|
||||||
@@ -71,8 +72,8 @@ public final class DebugAddon implements InjectorAddon {
|
|||||||
public void onRemoveInject(Channel channel) {
|
public void onRemoveInject(Channel channel) {
|
||||||
ChannelPipeline pipeline = channel.pipeline();
|
ChannelPipeline pipeline = channel.pipeline();
|
||||||
|
|
||||||
pipeline.remove("floodgate_debug_out");
|
Utils.removeHandler(pipeline, "floodgate_debug_out");
|
||||||
pipeline.remove("floodgate_debug_in");
|
Utils.removeHandler(pipeline, "floodgate_debug_in");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -29,9 +29,10 @@ import static java.util.Objects.requireNonNull;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Injector;
|
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.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
@@ -124,8 +125,17 @@ public final class PlayerLinkLoader {
|
|||||||
return null;
|
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 {
|
try {
|
||||||
PlayerLink instance = injector.getInstance(mainClass);
|
PlayerLink instance = child.getInstance(mainClass);
|
||||||
instance.load();
|
instance.load();
|
||||||
return instance;
|
return instance;
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ import org.geysermc.floodgate.link.PlayerLinkLoader;
|
|||||||
import org.geysermc.floodgate.util.LanguageManager;
|
import org.geysermc.floodgate.util.LanguageManager;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public final class CommonModule extends AbstractModule {
|
public class CommonModule extends AbstractModule {
|
||||||
private final Path dataDirectory;
|
private final Path dataDirectory;
|
||||||
|
|
||||||
@Override
|
@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;
|
package org.geysermc.floodgate.platform.pluginmessage;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.gson.Gson;
|
||||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
|
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import org.geysermc.cumulus.Form;
|
import org.geysermc.cumulus.Form;
|
||||||
@@ -35,6 +37,7 @@ import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
|||||||
import org.geysermc.floodgate.util.RawSkin;
|
import org.geysermc.floodgate.util.RawSkin;
|
||||||
|
|
||||||
public abstract class PluginMessageHandler {
|
public abstract class PluginMessageHandler {
|
||||||
|
protected static final Gson GSON = new Gson();
|
||||||
protected final Short2ObjectMap<Form> storedForms = new Short2ObjectOpenHashMap<>();
|
protected final Short2ObjectMap<Form> storedForms = new Short2ObjectOpenHashMap<>();
|
||||||
private final AtomicInteger nextFormId = new AtomicInteger(0);
|
private final AtomicInteger nextFormId = new AtomicInteger(0);
|
||||||
private final FloodgateConfigHolder configHolder;
|
private final FloodgateConfigHolder configHolder;
|
||||||
@@ -45,9 +48,13 @@ public abstract class PluginMessageHandler {
|
|||||||
|
|
||||||
public abstract boolean sendForm(UUID player, Form form);
|
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) {
|
protected byte[] createFormData(Form form) {
|
||||||
short formId = getNextFormId();
|
short formId = getNextFormId();
|
||||||
@@ -66,11 +73,40 @@ public abstract class PluginMessageHandler {
|
|||||||
return data;
|
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));
|
Form storedForm = storedForms.remove(getFormId(data));
|
||||||
if (storedForm != null) {
|
if (storedForm != null) {
|
||||||
storedForm.getResponseHandler().accept(
|
String responseData = new String(data, 2, data.length -2, Charsets.UTF_8);
|
||||||
new String(data, 2, data.length - 2, Charsets.UTF_8));
|
storedForm.getResponseHandler().accept(responseData);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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
|
* @link https://github.com/GeyserMC/Floodgate
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.geysermc.floodgate.module;
|
package org.geysermc.floodgate.skin;
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
import com.google.inject.Provides;
|
import org.geysermc.floodgate.skin.SkinUploader.UploadResult;
|
||||||
import com.google.inject.Singleton;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
|
||||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
public interface SkinApplier {
|
||||||
public final class ConfigLoadedModule extends AbstractModule {
|
void applySkin(FloodgatePlayer floodgatePlayer, UploadResult result);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -25,50 +25,66 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.skin;
|
package org.geysermc.floodgate.skin;
|
||||||
|
|
||||||
import static org.geysermc.floodgate.util.MessageFormatter.format;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||||
import org.geysermc.floodgate.skin.SkinUploader.UploadResult;
|
import org.geysermc.floodgate.util.RawSkin;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public abstract class SkinHandler {
|
public class SkinHandler {
|
||||||
private final SkinUploader uploader = new SkinUploader();
|
private final SkinUploader uploader = new SkinUploader();
|
||||||
private final PluginMessageHandler messageHandler;
|
private final SkinApplier skinApplier;
|
||||||
private final FloodgateLogger logger;
|
private final FloodgateLogger logger;
|
||||||
|
|
||||||
public final void handleSkinUploadFor(FloodgatePlayer player) {
|
public final void handleSkinUploadFor(FloodgatePlayer player,
|
||||||
uploader.uploadSkin(player.getRawSkin())
|
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) -> {
|
.whenComplete((uploadResult, throwable) -> {
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
logger.error(
|
logger.error(
|
||||||
"Failed to upload player skin for " + player.getCorrectUsername(),
|
"Failed to upload player skin for " + player.getCorrectUsername(),
|
||||||
throwable);
|
throwable);
|
||||||
|
|
||||||
messageHandler.sendSkinResponse(
|
if (consumer != null) {
|
||||||
player.getJavaUniqueId(), throwable.getMessage());
|
consumer.accept(true, throwable.getMessage());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uploadResult.getError() != null) {
|
if (uploadResult.getError() != null) {
|
||||||
logger.error(format(
|
logger.error("Error while uploading player skin for {}: {}",
|
||||||
"Error while uploading player skin for {}: {}",
|
player.getCorrectUsername(), uploadResult.getError());
|
||||||
player.getCorrectUsername(), uploadResult.getError()));
|
|
||||||
|
|
||||||
messageHandler.sendSkinResponse(
|
if (consumer != null) {
|
||||||
player.getJavaUniqueId(), uploadResult.getError());
|
consumer.accept(true, uploadResult.getError());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("Skin upload successful for " + player.getCorrectUsername());
|
logger.info("Skin upload successful for " + player.getCorrectUsername());
|
||||||
logger.info(uploadResult.getResponse().toString());
|
logger.info(uploadResult.getResponse().toString());
|
||||||
messageHandler.sendSkinResponse(
|
|
||||||
player.getJavaUniqueId(), uploadResult.getResponse().toString());
|
if (consumer != null) {
|
||||||
applySkin(player, uploadResult);
|
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.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -44,7 +45,7 @@ public final class SkinUploader {
|
|||||||
private final Executor requestExecutor = Executors.newSingleThreadExecutor();
|
private final Executor requestExecutor = Executors.newSingleThreadExecutor();
|
||||||
private long nextResult = 0;
|
private long nextResult = 0;
|
||||||
|
|
||||||
public CompletableFuture<UploadResult> uploadSkin(RawSkin rawSkin) {
|
public CompletableFuture<UploadResult> uploadSkin(@Nonnull RawSkin rawSkin) {
|
||||||
return CompletableFuture.supplyAsync(() -> uploadSkinInner(rawSkin, 0), requestExecutor);
|
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);
|
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>
|
<properties>
|
||||||
<geyser.version>1.2.0-SNAPSHOT</geyser.version>
|
<geyser.version>1.2.0-SNAPSHOT</geyser.version>
|
||||||
|
<cumulus.version>1.0-SNAPSHOT</cumulus.version>
|
||||||
<spigot.version>1.13-R0.1-SNAPSHOT</spigot.version>
|
<spigot.version>1.13-R0.1-SNAPSHOT</spigot.version>
|
||||||
<bungee.version>1.15-SNAPSHOT</bungee.version>
|
<bungee.version>1.15-SNAPSHOT</bungee.version>
|
||||||
<velocity.version>1.1.0</velocity.version>
|
<velocity.version>1.1.0</velocity.version>
|
||||||
|
|||||||
@@ -26,20 +26,23 @@
|
|||||||
package org.geysermc.floodgate;
|
package org.geysermc.floodgate;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
|
import org.geysermc.floodgate.pluginmessage.SpigotPluginMessageRegister;
|
||||||
|
|
||||||
public final class SpigotPlatform extends FloodgatePlatform {
|
public final class SpigotPlatform extends FloodgatePlatform {
|
||||||
@Inject private JavaPlugin plugin;
|
@Inject private JavaPlugin plugin;
|
||||||
|
@Inject private Injector guice;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SpigotPlatform(FloodgateApi api, PlatformInjector platformInjector,
|
public SpigotPlatform(FloodgateApi api, PlatformInjector platformInjector,
|
||||||
FloodgateLogger logger) {
|
FloodgateLogger logger, Injector injector) {
|
||||||
super(api, platformInjector, logger);
|
super(api, platformInjector, logger, injector);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -47,7 +50,9 @@ public final class SpigotPlatform extends FloodgatePlatform {
|
|||||||
boolean success = super.enable(postInitializeModules);
|
boolean success = super.enable(postInitializeModules);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
Bukkit.getPluginManager().disablePlugin(plugin);
|
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.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.module.CommandModule;
|
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.SpigotAddonModule;
|
||||||
import org.geysermc.floodgate.module.SpigotListenerModule;
|
import org.geysermc.floodgate.module.SpigotListenerModule;
|
||||||
import org.geysermc.floodgate.module.SpigotPlatformModule;
|
import org.geysermc.floodgate.module.SpigotPlatformModule;
|
||||||
@@ -46,7 +46,7 @@ public final class SpigotPlugin extends JavaPlugin {
|
|||||||
|
|
||||||
long ctm = System.currentTimeMillis();
|
long ctm = System.currentTimeMillis();
|
||||||
Injector injector = Guice.createInjector(
|
Injector injector = Guice.createInjector(
|
||||||
new CommonModule(getDataFolder().toPath()),
|
new ServerCommonModule(getDataFolder().toPath()),
|
||||||
new SpigotPlatformModule(this)
|
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.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||||
|
import org.geysermc.floodgate.util.Utils;
|
||||||
|
|
||||||
public final class SpigotDataAddon implements InjectorAddon {
|
public final class SpigotDataAddon implements InjectorAddon {
|
||||||
@Inject private HandshakeHandler handshakeHandler;
|
@Inject private HandshakeHandler handshakeHandler;
|
||||||
@@ -63,7 +64,7 @@ public final class SpigotDataAddon implements InjectorAddon {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRemoveInject(Channel channel) {
|
public void onRemoveInject(Channel channel) {
|
||||||
channel.pipeline().remove("floodgate_data_handler");
|
Utils.removeHandler(channel.pipeline(), "floodgate_data_handler");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import org.geysermc.floodgate.HandshakeHandler;
|
|||||||
import org.geysermc.floodgate.HandshakeHandler.HandshakeResult;
|
import org.geysermc.floodgate.HandshakeHandler.HandshakeResult;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
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.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.util.BedrockData;
|
import org.geysermc.floodgate.util.BedrockData;
|
||||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||||
@@ -180,7 +181,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
|||||||
networkManager = ctx.channel().pipeline().get("packet_handler");
|
networkManager = ctx.channel().pipeline().get("packet_handler");
|
||||||
|
|
||||||
String handshakeValue = getCastedValue(packet, HANDSHAKE_HOST);
|
String handshakeValue = getCastedValue(packet, HANDSHAKE_HOST);
|
||||||
HandshakeResult result = handshakeHandler.handle(handshakeValue);
|
HandshakeResult result = handshakeHandler.handle(ctx.channel(), handshakeValue);
|
||||||
switch (result.getResultType()) {
|
switch (result.getResultType()) {
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
break;
|
break;
|
||||||
@@ -204,6 +205,8 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
|||||||
String[] data = result.getHandshakeData();
|
String[] data = result.getHandshakeData();
|
||||||
bungeeData = isBungeeData();
|
bungeeData = isBungeeData();
|
||||||
|
|
||||||
|
InetSocketAddress correctAddress = fPlayer.getProperty(PropertyKey.SOCKET_ADDRESS);
|
||||||
|
|
||||||
if (bungeeData) {
|
if (bungeeData) {
|
||||||
setValue(packet, HANDSHAKE_HOST, data[0] + '\0' +
|
setValue(packet, HANDSHAKE_HOST, data[0] + '\0' +
|
||||||
bedrockData.getIp() + '\0' +
|
bedrockData.getIp() + '\0' +
|
||||||
@@ -213,12 +216,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
|||||||
// Use a spoofedUUID for initUUID (just like Bungeecord)
|
// Use a spoofedUUID for initUUID (just like Bungeecord)
|
||||||
setValue(networkManager, "spoofedUUID", fPlayer.getCorrectUniqueId());
|
setValue(networkManager, "spoofedUUID", fPlayer.getCorrectUniqueId());
|
||||||
// Use the player his IP for stuff instead of Geyser his IP
|
// Use the player his IP for stuff instead of Geyser his IP
|
||||||
SocketAddress newAddress = new InetSocketAddress(
|
setValue(networkManager, SOCKET_ADDRESS, correctAddress);
|
||||||
bedrockData.getIp(),
|
|
||||||
((InetSocketAddress) ctx.channel().remoteAddress()).getPort()
|
|
||||||
);
|
|
||||||
|
|
||||||
setValue(networkManager, SOCKET_ADDRESS, newAddress);
|
|
||||||
}
|
}
|
||||||
} else if (isLogin) {
|
} else if (isLogin) {
|
||||||
if (!bungeeData) {
|
if (!bungeeData) {
|
||||||
|
|||||||
@@ -38,12 +38,12 @@ import org.geysermc.floodgate.FloodgatePlayerImpl;
|
|||||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
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;
|
import org.geysermc.floodgate.util.LanguageManager;
|
||||||
|
|
||||||
public final class SpigotListener implements Listener {
|
public final class SpigotListener implements Listener {
|
||||||
@Inject private SimpleFloodgateApi api;
|
@Inject private SimpleFloodgateApi api;
|
||||||
@Inject private SkinHandler skinHandler;
|
@Inject private ServerSkinHandler skinHandler;
|
||||||
@Inject private LanguageManager languageManager;
|
@Inject private LanguageManager languageManager;
|
||||||
@Inject private FloodgateLogger logger;
|
@Inject private FloodgateLogger logger;
|
||||||
|
|
||||||
|
|||||||
@@ -33,10 +33,9 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.geysermc.floodgate.SpigotPlugin;
|
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.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.command.SpigotCommandRegistration;
|
import org.geysermc.floodgate.command.SpigotCommandRegistration;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||||
import org.geysermc.floodgate.inject.spigot.SpigotInjector;
|
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.listener.ListenerRegistration;
|
||||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||||
import org.geysermc.floodgate.pluginmessage.SpigotPluginMessageHandler;
|
import org.geysermc.floodgate.pluginmessage.SpigotPluginMessageHandler;
|
||||||
import org.geysermc.floodgate.pluginmessage.SpigotSkinHandler;
|
import org.geysermc.floodgate.pluginmessage.SpigotPluginMessageRegister;
|
||||||
import org.geysermc.floodgate.skin.SkinHandler;
|
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.LanguageManager;
|
||||||
import org.geysermc.floodgate.util.SpigotCommandUtil;
|
import org.geysermc.floodgate.util.SpigotCommandUtil;
|
||||||
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
|
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
|
||||||
@@ -57,25 +58,17 @@ import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
|
|||||||
public final class SpigotPlatformModule extends AbstractModule {
|
public final class SpigotPlatformModule extends AbstractModule {
|
||||||
private final SpigotPlugin plugin;
|
private final SpigotPlugin plugin;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(PluginMessageHandler.class).to(SpigotPluginMessageHandler.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public JavaPlugin javaPlugin() {
|
public JavaPlugin javaPlugin() {
|
||||||
return plugin;
|
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
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public FloodgateLogger floodgateLogger(LanguageManager languageManager) {
|
public FloodgateLogger floodgateLogger(LanguageManager languageManager) {
|
||||||
@@ -90,7 +83,8 @@ public final class SpigotPlatformModule extends AbstractModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
public CommandRegistration commandRegistration(
|
public CommandRegistration commandRegistration(
|
||||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||||
CommandUtil commandUtil) {
|
CommandUtil commandUtil
|
||||||
|
) {
|
||||||
return new SpigotCommandRegistration(versionSpecificMethods, plugin, commandUtil);
|
return new SpigotCommandRegistration(versionSpecificMethods, plugin, commandUtil);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,24 +100,6 @@ public final class SpigotPlatformModule extends AbstractModule {
|
|||||||
return new SpigotListenerRegistration(plugin);
|
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
|
DebugAddon / PlatformInjector
|
||||||
*/
|
*/
|
||||||
@@ -157,4 +133,47 @@ public final class SpigotPlatformModule extends AbstractModule {
|
|||||||
public String implementationName() {
|
public String implementationName() {
|
||||||
return "Spigot";
|
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;
|
package org.geysermc.floodgate.pluginmessage;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.bukkit.plugin.messaging.Messenger;
|
|
||||||
import org.geysermc.cumulus.Form;
|
import org.geysermc.cumulus.Form;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||||
import org.geysermc.floodgate.util.RawSkin;
|
|
||||||
|
|
||||||
public class SpigotPluginMessageHandler extends PluginMessageHandler {
|
public class SpigotPluginMessageHandler extends PluginMessageHandler {
|
||||||
private final JavaPlugin plugin;
|
private final JavaPlugin plugin;
|
||||||
private final String formChannel;
|
private final String formChannel;
|
||||||
private final String skinChannel;
|
private final String skinChannel;
|
||||||
|
|
||||||
public SpigotPluginMessageHandler(FloodgateConfigHolder configHolder, JavaPlugin plugin,
|
public SpigotPluginMessageHandler(
|
||||||
String formChannel, String skinChannel) {
|
FloodgateConfigHolder configHolder,
|
||||||
|
JavaPlugin plugin,
|
||||||
|
String formChannel,
|
||||||
|
String skinChannel
|
||||||
|
) {
|
||||||
super(configHolder);
|
super(configHolder);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.formChannel = formChannel;
|
this.formChannel = formChannel;
|
||||||
this.skinChannel = skinChannel;
|
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
|
@Override
|
||||||
@@ -81,22 +62,9 @@ public class SpigotPluginMessageHandler extends PluginMessageHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean sendSkinRequest(UUID playerId, RawSkin skin) {
|
public void sendSkinResponse(UUID playerId, boolean failed, String response) {
|
||||||
try {
|
try {
|
||||||
byte[] skinData = skin.toString().getBytes(Charsets.UTF_8);
|
byte[] responseData = createSkinResponseData(failed, response);
|
||||||
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);
|
|
||||||
Bukkit.getPlayer(playerId).sendPluginMessage(plugin, skinChannel, responseData);
|
Bukkit.getPlayer(playerId).sendPluginMessage(plugin, skinChannel, responseData);
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
exception.printStackTrace();
|
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.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.geysermc.floodgate.SpigotPlugin;
|
import org.geysermc.floodgate.SpigotPlugin;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
||||||
import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
import org.geysermc.floodgate.skin.SkinApplier;
|
||||||
import org.geysermc.floodgate.skin.SkinHandler;
|
|
||||||
import org.geysermc.floodgate.skin.SkinUploader.UploadResult;
|
import org.geysermc.floodgate.skin.SkinUploader.UploadResult;
|
||||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||||
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
|
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
|
||||||
|
|
||||||
public class SpigotSkinHandler extends SkinHandler {
|
public final class SpigotSkinApplier implements SkinApplier {
|
||||||
private static final Method GET_PROFILE_METHOD;
|
private static final Method GET_PROFILE_METHOD;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -56,17 +54,18 @@ public class SpigotSkinHandler extends SkinHandler {
|
|||||||
private final SpigotPlugin plugin;
|
private final SpigotPlugin plugin;
|
||||||
private final FloodgateConfigHolder configHolder;
|
private final FloodgateConfigHolder configHolder;
|
||||||
|
|
||||||
public SpigotSkinHandler(PluginMessageHandler messageHandler, FloodgateLogger logger,
|
public SpigotSkinApplier(
|
||||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||||
SpigotPlugin plugin, FloodgateConfigHolder configHolder) {
|
SpigotPlugin plugin,
|
||||||
super(messageHandler, logger);
|
FloodgateConfigHolder configHolder
|
||||||
|
) {
|
||||||
this.versionSpecificMethods = versionSpecificMethods;
|
this.versionSpecificMethods = versionSpecificMethods;
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.configHolder = configHolder;
|
this.configHolder = configHolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void applySkin(FloodgatePlayer floodgatePlayer, UploadResult result) {
|
public void applySkin(FloodgatePlayer floodgatePlayer, UploadResult result) {
|
||||||
Player player = Bukkit.getPlayer(floodgatePlayer.getCorrectUniqueId());
|
Player player = Bukkit.getPlayer(floodgatePlayer.getCorrectUniqueId());
|
||||||
GameProfile profile = ReflectionUtils.castedInvoke(player, GET_PROFILE_METHOD);
|
GameProfile profile = ReflectionUtils.castedInvoke(player, GET_PROFILE_METHOD);
|
||||||
|
|
||||||
@@ -89,7 +88,7 @@ public class SpigotSkinHandler extends SkinHandler {
|
|||||||
if (configHolder.get().isApplySkinDirectly()) {
|
if (configHolder.get().isApplySkinDirectly()) {
|
||||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||||
if (p != player) {
|
if (p != player && p.canSee(player)) {
|
||||||
versionSpecificMethods.hidePlayer(p, player);
|
versionSpecificMethods.hidePlayer(p, player);
|
||||||
versionSpecificMethods.showPlayer(p, player);
|
versionSpecificMethods.showPlayer(p, player);
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.module.CommandModule;
|
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.VelocityAddonModule;
|
||||||
import org.geysermc.floodgate.module.VelocityListenerModule;
|
import org.geysermc.floodgate.module.VelocityListenerModule;
|
||||||
import org.geysermc.floodgate.module.VelocityPlatformModule;
|
import org.geysermc.floodgate.module.VelocityPlatformModule;
|
||||||
@@ -48,7 +48,7 @@ public final class VelocityPlugin {
|
|||||||
|
|
||||||
long ctm = System.currentTimeMillis();
|
long ctm = System.currentTimeMillis();
|
||||||
Injector injector = guice.createChildInjector(
|
Injector injector = guice.createChildInjector(
|
||||||
new CommonModule(dataDirectory),
|
new ProxyCommonModule(dataDirectory),
|
||||||
new VelocityPlatformModule()
|
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.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||||
|
import org.geysermc.floodgate.util.Utils;
|
||||||
|
|
||||||
public final class VelocityDataAddon implements InjectorAddon {
|
public final class VelocityDataAddon implements InjectorAddon {
|
||||||
@Inject private HandshakeHandler handshakeHandler;
|
@Inject private HandshakeHandler handshakeHandler;
|
||||||
@@ -84,7 +85,7 @@ public final class VelocityDataAddon implements InjectorAddon {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRemoveInject(Channel channel) {
|
public void onRemoveInject(Channel channel) {
|
||||||
channel.pipeline().remove("floodgate_data_handler");
|
Utils.removeHandler(channel.pipeline(), "floodgate_data_handler");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public final class VelocityProxyDataHandler extends SimpleChannelInboundHandler<
|
|||||||
private void handleClientToProxy(ChannelHandlerContext ctx, Object packet) {
|
private void handleClientToProxy(ChannelHandlerContext ctx, Object packet) {
|
||||||
String address = getCastedValue(packet, HANDSHAKE_SERVER_ADDRESS);
|
String address = getCastedValue(packet, HANDSHAKE_SERVER_ADDRESS);
|
||||||
|
|
||||||
HandshakeResult result = handshakeHandler.handle(address);
|
HandshakeResult result = handshakeHandler.handle(ctx.channel(), address);
|
||||||
switch (result.getResultType()) {
|
switch (result.getResultType()) {
|
||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.listener;
|
package org.geysermc.floodgate.listener;
|
||||||
|
|
||||||
import static org.geysermc.floodgate.util.MessageFormatter.format;
|
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.name.Named;
|
import com.google.inject.name.Named;
|
||||||
import com.velocitypowered.api.event.Subscribe;
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
@@ -98,9 +96,8 @@ public class VelocityPluginMessageHandler extends PluginMessageHandler {
|
|||||||
event.setResult(ForwardResult.handled());
|
event.setResult(ForwardResult.handled());
|
||||||
|
|
||||||
if (!callResponseConsumer(data)) {
|
if (!callResponseConsumer(data)) {
|
||||||
logger.error(format(
|
logger.error("Couldn't find stored form with id {} for player {}",
|
||||||
"Couldn't find stored form with id {} for player {}",
|
formId, ((Player) source).getUsername());
|
||||||
formId, ((Player) source).getUsername()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,9 +116,4 @@ public class VelocityPluginMessageHandler extends PluginMessageHandler {
|
|||||||
public boolean sendSkinRequest(UUID player, RawSkin skin) {
|
public boolean sendSkinRequest(UUID player, RawSkin skin) {
|
||||||
return false; //todo
|
return false; //todo
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendSkinResponse(UUID player, String response) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user