mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2026-01-04 15:31:48 +00:00
Allow Floodgate to run embedded. Support Velocity's 'none' forwarding
The classes that were removed from the legacy Floodgate API have also been brought back
This commit is contained in:
@@ -5,8 +5,8 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("org.geysermc", "api", "3.0.0-SNAPSHOT")
|
||||
api(projects.api)
|
||||
api("org.geysermc", "api", "3.0.0-SNAPSHOT")
|
||||
// api("org.geysermc", "floodgate-legacy-api", "3.0.0-SNAPSHOT")
|
||||
api("org.geysermc.configutils", "configutils", Versions.configUtilsVersion)
|
||||
|
||||
|
||||
@@ -29,13 +29,15 @@ import com.google.inject.Guice;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.InstanceHolder;
|
||||
import org.geysermc.floodgate.api.impl.FloodgateApiWrapper;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
||||
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
@@ -67,10 +69,11 @@ public abstract class FloodgatePlatform {
|
||||
|
||||
GeyserApiBase api = guice.getInstance(GeyserApiBase.class);
|
||||
InstanceHolder.set(
|
||||
new FloodgateApiWrapper(api),
|
||||
guice.getInstance(FloodgateApi.class),
|
||||
guice.getInstance(PlayerLink.class),
|
||||
injector,
|
||||
guice.getInstance(PacketHandlers.class),
|
||||
guice.getInstance(HandshakeHandlers.class),
|
||||
KEY
|
||||
);
|
||||
Geyser.set(api);
|
||||
@@ -80,7 +83,7 @@ public abstract class FloodgatePlatform {
|
||||
.translatedInfo("floodgate.core.finish", endTime - startTime);
|
||||
}
|
||||
|
||||
protected abstract Module[] loadStageModules();
|
||||
protected abstract List<Module> loadStageModules();
|
||||
|
||||
public void enable() throws RuntimeException {
|
||||
if (injector == null) {
|
||||
@@ -98,7 +101,7 @@ public abstract class FloodgatePlatform {
|
||||
guice.getInstance(EventBus.class).fire(new PostEnableEvent());
|
||||
}
|
||||
|
||||
protected abstract Module[] postEnableStageModules();
|
||||
protected abstract List<Module> postEnableStageModules();
|
||||
|
||||
public void disable() {
|
||||
guice.getInstance(EventBus.class).fire(new ShutdownEvent());
|
||||
@@ -115,4 +118,8 @@ public abstract class FloodgatePlatform {
|
||||
public boolean isProxy() {
|
||||
return config.isProxy();
|
||||
}
|
||||
|
||||
public <T> T getInstance(Class<T> clazz) {
|
||||
return guice.getInstance(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.floodgate.addon.data;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.util.Random;
|
||||
@@ -32,7 +33,8 @@ import org.geysermc.floodgate.api.handshake.HandshakeData;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeHandler;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
||||
|
||||
public class HandshakeHandlersImpl {
|
||||
@Singleton
|
||||
public class HandshakeHandlersImpl implements HandshakeHandlers {
|
||||
private final Random random = new Random();
|
||||
private final Int2ObjectMap<HandshakeHandler> handshakeHandlers = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
|
||||
@@ -26,10 +26,12 @@
|
||||
package org.geysermc.floodgate.api;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
|
||||
@Singleton
|
||||
public final class ProxyFloodgateApi extends SimpleFloodgateApi {
|
||||
@Inject
|
||||
private FloodgateCipher cipher;
|
||||
|
||||
@@ -28,6 +28,7 @@ package org.geysermc.floodgate.api;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -48,6 +49,7 @@ import org.geysermc.floodgate.pluginmessage.channel.FormChannel;
|
||||
import org.geysermc.floodgate.pluginmessage.channel.TransferChannel;
|
||||
import org.geysermc.floodgate.util.HttpClient;
|
||||
|
||||
@Singleton
|
||||
public class SimpleFloodgateApi implements GeyserApiBase {
|
||||
private final Map<UUID, Connection> players = new HashMap<>();
|
||||
private final Cache<UUID, Connection> pendingRemove =
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Floodgate
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.api.legacy;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.cumulus.form.Form;
|
||||
import org.geysermc.cumulus.form.util.FormBuilder;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.unsafe.Unsafe;
|
||||
import org.geysermc.floodgate.player.FloodgateConnection;
|
||||
import org.geysermc.floodgate.util.WebEndpoints;
|
||||
|
||||
public final class LegacyApiWrapper implements FloodgateApi {
|
||||
private final GeyserApiBase apiBase;
|
||||
private final WebEndpoints webEndpoints;
|
||||
|
||||
public LegacyApiWrapper(GeyserApiBase apiBase, WebEndpoints webEndpoints) {
|
||||
this.apiBase = apiBase;
|
||||
this.webEndpoints = webEndpoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerPrefix() {
|
||||
return apiBase.usernamePrefix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FloodgatePlayer> getPlayers() {
|
||||
return apiBase.onlineConnections()
|
||||
.stream()
|
||||
.map(connection -> new LegacyPlayerWrapper((FloodgateConnection) connection))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
return apiBase.onlineConnectionsCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFloodgatePlayer(UUID uuid) {
|
||||
return apiBase.isBedrockPlayer(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloodgatePlayer getPlayer(UUID uuid) {
|
||||
FloodgateConnection connection = (FloodgateConnection) apiBase.connectionByUuid(uuid);
|
||||
if (connection != null) {
|
||||
return new LegacyPlayerWrapper(connection);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID createJavaPlayerId(long xuid) {
|
||||
return new UUID(0, xuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFloodgateId(UUID uuid) {
|
||||
return uuid.getMostSignificantBits() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(UUID uuid, Form form) {
|
||||
return apiBase.sendForm(uuid, form);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(UUID uuid, FormBuilder<?, ?, ?> formBuilder) {
|
||||
return apiBase.sendForm(uuid, formBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(UUID uuid, org.geysermc.cumulus.Form<?> form) {
|
||||
return sendForm(uuid, form.newForm());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(UUID uuid, org.geysermc.cumulus.util.FormBuilder<?, ?> formBuilder) {
|
||||
return sendForm(uuid, formBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean transferPlayer(UUID uuid, String address, int port) {
|
||||
return apiBase.transfer(uuid, address, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Long> getXuidFor(String gamertag) {
|
||||
return webEndpoints.getXuidFor(gamertag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<String> getGamertagFor(long xuid) {
|
||||
return webEndpoints.getGamertagFor(xuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Unsafe unsafe() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Floodgate
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.api.legacy;
|
||||
|
||||
import java.util.UUID;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||
import org.geysermc.floodgate.player.FloodgateConnection;
|
||||
import org.geysermc.floodgate.util.DeviceOs;
|
||||
import org.geysermc.floodgate.util.InputMode;
|
||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||
import org.geysermc.floodgate.util.UiProfile;
|
||||
|
||||
public class LegacyPlayerWrapper implements FloodgatePlayer {
|
||||
private final FloodgateConnection connection;
|
||||
|
||||
public LegacyPlayerWrapper(FloodgateConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJavaUsername() {
|
||||
throw new UnsupportedOperationException(); //todo
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getJavaUniqueId() {
|
||||
throw new UnsupportedOperationException(); //todo
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getCorrectUniqueId() {
|
||||
return connection.javaUuid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCorrectUsername() {
|
||||
return connection.javaUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return connection.version();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return connection.bedrockUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getXuid() {
|
||||
return connection.xuid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceOs getDeviceOs() {
|
||||
return DeviceOs.fromId(connection.platform().ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguageCode() {
|
||||
return connection.languageCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UiProfile getUiProfile() {
|
||||
return UiProfile.fromId(connection.uiProfile().ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputMode getInputMode() {
|
||||
return InputMode.fromId(connection.inputMode().ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFromProxy() {
|
||||
throw new UnsupportedOperationException(); //todo
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedPlayer getLinkedPlayer() {
|
||||
if (isLinked()) {
|
||||
return LinkedPlayer.of(
|
||||
connection.javaUsername(), connection.javaUuid(),
|
||||
FloodgateApi.getInstance().createJavaPlayerId(Long.parseLong(getXuid()))
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLinked() {
|
||||
return connection.isLinked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProperty(PropertyKey key) {
|
||||
return connection.propertyGlue().hasProperty(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProperty(String key) {
|
||||
return connection.propertyGlue().hasProperty(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getProperty(PropertyKey key) {
|
||||
return connection.propertyGlue().getProperty(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getProperty(String key) {
|
||||
return connection.propertyGlue().getProperty(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T removeProperty(PropertyKey key) {
|
||||
return connection.propertyGlue().removeProperty(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T removeProperty(String key) {
|
||||
return connection.propertyGlue().removeProperty(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T addProperty(PropertyKey key, Object value) {
|
||||
return connection.propertyGlue().addProperty(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T addProperty(String key, Object value) {
|
||||
return connection.propertyGlue().addProperty(key, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Floodgate
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.api.legacy;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey.Result;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class PropertyGlue {
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
private Map<PropertyKey, Object> propertyKeyToValue;
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
private Map<String, PropertyKey> stringToPropertyKey;
|
||||
|
||||
public boolean hasProperty(PropertyKey key) {
|
||||
if (propertyKeyToValue == null) {
|
||||
return false;
|
||||
}
|
||||
return propertyKeyToValue.get(key) != null;
|
||||
}
|
||||
|
||||
public boolean hasProperty(String key) {
|
||||
if (stringToPropertyKey == null) {
|
||||
return false;
|
||||
}
|
||||
return hasProperty(stringToPropertyKey.get(key));
|
||||
}
|
||||
|
||||
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.isRemovable()) {
|
||||
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.isRemovable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
stringToPropertyKey.remove(key.getKey());
|
||||
|
||||
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.isAddAllowed(key) == Result.ALLOWED) {
|
||||
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.isAddAllowed(key) == Result.ALLOWED) {
|
||||
stringToPropertyKey.put(key, propertyKey);
|
||||
return (T) propertyKeyToValue.put(propertyKey, value);
|
||||
}
|
||||
|
||||
return (T) stringToPropertyKey.computeIfAbsent(key, (keyString) -> {
|
||||
propertyKeyToValue.put(propertyKey, value);
|
||||
return propertyKey;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -25,12 +25,14 @@
|
||||
|
||||
package org.geysermc.floodgate.config;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.name.Named;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.Key;
|
||||
import java.util.UUID;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.geysermc.configutils.ConfigUtilities;
|
||||
import org.geysermc.configutils.file.codec.PathFileCodec;
|
||||
import org.geysermc.configutils.file.template.ResourceTemplateReader;
|
||||
@@ -39,13 +41,26 @@ import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||
import org.geysermc.floodgate.crypto.KeyProducer;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
@Singleton
|
||||
public final class ConfigLoader {
|
||||
private final Path dataDirectory;
|
||||
private final Class<? extends FloodgateConfig> configClass;
|
||||
@Inject
|
||||
@Named("dataDirectory")
|
||||
private Path dataDirectory;
|
||||
|
||||
private final KeyProducer keyProducer;
|
||||
private final FloodgateCipher cipher;
|
||||
@Inject
|
||||
@Named("configClass")
|
||||
private Class<? extends FloodgateConfig> configClass;
|
||||
|
||||
@Inject
|
||||
|
||||
private KeyProducer keyProducer;
|
||||
|
||||
@Inject
|
||||
private FloodgateCipher cipher;
|
||||
|
||||
@Inject(optional = true)
|
||||
@Named("configFile")
|
||||
private String configFile = "config.yml";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends FloodgateConfig> T load() {
|
||||
@@ -53,6 +68,7 @@ public final class ConfigLoader {
|
||||
if (ProxyFloodgateConfig.class.isAssignableFrom(configClass)) {
|
||||
templateFile = "proxy-" + templateFile;
|
||||
}
|
||||
templateFile = "floodgate-" + templateFile;
|
||||
|
||||
//todo old Floodgate logged a message when version = 0 and it generated a new key.
|
||||
// Might be nice to allow you to run a function for a specific version.
|
||||
@@ -63,7 +79,7 @@ public final class ConfigLoader {
|
||||
ConfigUtilities utilities =
|
||||
ConfigUtilities.builder()
|
||||
.fileCodec(PathFileCodec.of(dataDirectory))
|
||||
.configFile("config.yml")
|
||||
.configFile(configFile)
|
||||
.templateReader(ResourceTemplateReader.of(getClass()))
|
||||
.template(templateFile)
|
||||
.changes(Changes.builder()
|
||||
|
||||
@@ -43,9 +43,11 @@ import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.event.PostOrder;
|
||||
import org.geysermc.floodgate.addon.data.HandshakeHandlersImpl;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
||||
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
||||
import org.geysermc.floodgate.api.legacy.LegacyApiWrapper;
|
||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.packet.PacketHandlers;
|
||||
@@ -67,7 +69,7 @@ import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinUploadManager;
|
||||
import org.geysermc.floodgate.util.Constants;
|
||||
import org.geysermc.floodgate.util.HttpClient;
|
||||
import org.geysermc.floodgate.util.WebEndpoints;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class CommonModule extends AbstractModule {
|
||||
@@ -89,13 +91,10 @@ public class CommonModule extends AbstractModule {
|
||||
eventBus.subscribe(ShutdownEvent.class, ignored -> commonPool.shutdown(), PostOrder.LAST);
|
||||
bind(ExecutorService.class).annotatedWith(Names.named("commonPool")).toInstance(commonPool);
|
||||
|
||||
bind(HttpClient.class).in(Singleton.class);
|
||||
|
||||
bind(GeyserApiBase.class).to(SimpleFloodgateApi.class);
|
||||
bind(PlatformInjector.class).to(CommonPlatformInjector.class);
|
||||
|
||||
bind(HandshakeHandlers.class).to(HandshakeHandlersImpl.class);
|
||||
bind(HandshakeHandlersImpl.class).in(Singleton.class);
|
||||
|
||||
bind(PacketHandlers.class).to(PacketHandlersImpl.class);
|
||||
bind(PacketHandlersImpl.class).asEagerSingleton();
|
||||
@@ -103,6 +102,12 @@ public class CommonModule extends AbstractModule {
|
||||
install(new AutoBindModule());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public FloodgateApi floodgateApi(GeyserApiBase api, WebEndpoints webEndpoints) {
|
||||
return new LegacyApiWrapper(api, webEndpoints);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public FloodgateConfig floodgateConfig(ConfigLoader configLoader) {
|
||||
@@ -134,15 +139,6 @@ public class CommonModule extends AbstractModule {
|
||||
return dataDirectory;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public ConfigLoader configLoader(
|
||||
@Named("configClass") Class<? extends FloodgateConfig> configClass,
|
||||
KeyProducer producer,
|
||||
FloodgateCipher cipher) {
|
||||
return new ConfigLoader(dataDirectory, configClass, producer, cipher);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public FloodgateHandshakeHandler handshakeHandler(
|
||||
|
||||
@@ -27,11 +27,12 @@ package org.geysermc.floodgate.module;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Module;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public final class PostEnableModules extends AbstractModule {
|
||||
private final Module[] postInitializeModules;
|
||||
private final List<Module> postInitializeModules;
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
|
||||
@@ -44,7 +44,6 @@ public final class ProxyCommonModule extends CommonModule {
|
||||
super.configure();
|
||||
|
||||
bind(SimpleFloodgateApi.class).to(ProxyFloodgateApi.class);
|
||||
bind(ProxyFloodgateApi.class).in(Singleton.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -29,7 +29,6 @@ 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.config.FloodgateConfig;
|
||||
|
||||
public final class ServerCommonModule extends CommonModule {
|
||||
@@ -37,12 +36,6 @@ public final class ServerCommonModule extends CommonModule {
|
||||
super(dataDirectory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
bind(SimpleFloodgateApi.class).in(Singleton.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("configClass")
|
||||
|
||||
@@ -28,7 +28,6 @@ package org.geysermc.floodgate.player;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.UUID;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Builder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@@ -40,14 +39,14 @@ import org.geysermc.api.util.InputMode;
|
||||
import org.geysermc.api.util.UiProfile;
|
||||
import org.geysermc.cumulus.form.Form;
|
||||
import org.geysermc.cumulus.form.util.FormBuilder;
|
||||
import org.geysermc.floodgate.addon.data.HandshakeDataImpl;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeData;
|
||||
import org.geysermc.floodgate.api.legacy.PropertyGlue;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@Builder
|
||||
public final class FloodgatePlayerImpl implements Connection {
|
||||
public final class FloodgateConnection implements Connection {
|
||||
private final String version;
|
||||
private final String username;
|
||||
private final String javaUsername;
|
||||
@@ -66,7 +65,9 @@ public final class FloodgatePlayerImpl implements Connection {
|
||||
|
||||
private final InetSocketAddress socketAddress;
|
||||
|
||||
static FloodgatePlayerImpl from(BedrockData data, HandshakeDataImpl handshakeData, int port) {
|
||||
private final PropertyGlue propertyGlue = new PropertyGlue();
|
||||
|
||||
static FloodgateConnection from(BedrockData data, HandshakeData handshakeData, int port) {
|
||||
UUID javaUniqueId = Utils.getJavaUuid(data.getXuid());
|
||||
|
||||
BedrockPlatform deviceOs = BedrockPlatform.fromId(data.getDeviceOs());
|
||||
@@ -77,7 +78,7 @@ public final class FloodgatePlayerImpl implements Connection {
|
||||
|
||||
InetSocketAddress socketAddress = new InetSocketAddress(data.getIp(), port);
|
||||
|
||||
return new FloodgatePlayerImpl(
|
||||
return new FloodgateConnection(
|
||||
data.getVersion(), data.getUsername(), handshakeData.getJavaUsername(),
|
||||
javaUniqueId, data.getXuid(), deviceOs, data.getLanguageCode(), uiProfile,
|
||||
inputMode, data.getIp(), data.isFromProxy(),
|
||||
@@ -150,7 +151,7 @@ public final class FloodgatePlayerImpl implements Connection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress socketAddress() {
|
||||
public @NonNull InetSocketAddress socketAddress() {
|
||||
return socketAddress;
|
||||
}
|
||||
|
||||
@@ -159,4 +160,8 @@ public final class FloodgatePlayerImpl implements Connection {
|
||||
uiProfile.ordinal(), inputMode.ordinal(), ip, linkedPlayer, proxy, subscribeId,
|
||||
verifyCode);
|
||||
}
|
||||
|
||||
public PropertyGlue propertyGlue() {
|
||||
return propertyGlue;
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,7 @@ public final class FloodgateHandshakeHandler {
|
||||
LinkedPlayer linkedPlayer) {
|
||||
|
||||
try {
|
||||
HandshakeDataImpl handshakeData = new HandshakeDataImpl(
|
||||
HandshakeData handshakeData = new HandshakeDataImpl(
|
||||
channel, true, bedrockData.clone(), config,
|
||||
linkedPlayer != null ? linkedPlayer.clone() : null, hostname);
|
||||
|
||||
@@ -222,7 +222,7 @@ public final class FloodgateHandshakeHandler {
|
||||
|
||||
int port = ((InetSocketAddress) channel.remoteAddress()).getPort();
|
||||
|
||||
Connection player = FloodgatePlayerImpl.from(bedrockData, handshakeData, port);
|
||||
Connection player = FloodgateConnection.from(bedrockData, handshakeData, port);
|
||||
|
||||
api.addPlayer(player);
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
@@ -160,6 +162,7 @@ public class Utils {
|
||||
* @param input the fully qualified name of the annotation
|
||||
* @return a set of all the classes annotated by the given annotation
|
||||
*/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static Set<Class<?>> getGeneratedClassesForAnnotation(String input) {
|
||||
try (InputStream annotatedClass = Utils.class.getClassLoader().getResourceAsStream(input);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(annotatedClass))) {
|
||||
@@ -174,4 +177,13 @@ public class Utils {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"ManualArrayToCollectionCopy", "UseBulkOperation"})
|
||||
public static <T> List<T> asList(T... data) {
|
||||
List<T> list = new ArrayList<>(data.length);
|
||||
for (T entry : data) {
|
||||
list.add(entry);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Floodgate
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.util;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Singleton
|
||||
public class WebEndpoints {
|
||||
@Inject
|
||||
private HttpClient httpClient;
|
||||
|
||||
public CompletableFuture<Long> getXuidFor(String gamertag) {
|
||||
if (gamertag == null || gamertag.isEmpty() || gamertag.length() > 16) {
|
||||
return Utils.failedFuture(new IllegalStateException("Received an invalid gamertag"));
|
||||
}
|
||||
|
||||
return httpClient.asyncGet(Constants.GET_XUID_URL + gamertag)
|
||||
.thenApply(result -> {
|
||||
JsonObject response = result.getResponse();
|
||||
|
||||
if (!result.isCodeOk()) {
|
||||
throw new IllegalStateException(response.get("message").getAsString());
|
||||
}
|
||||
|
||||
JsonElement xuid = response.get("xuid");
|
||||
return xuid != null ? xuid.getAsLong() : null;
|
||||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<String> getGamertagFor(long xuid) {
|
||||
return httpClient.asyncGet(Constants.GET_GAMERTAG_URL + xuid)
|
||||
.thenApply(result -> {
|
||||
JsonObject response = result.getResponse();
|
||||
|
||||
if (!result.isCodeOk()) {
|
||||
throw new IllegalStateException(response.get("message").getAsString());
|
||||
}
|
||||
|
||||
JsonElement gamertag = response.get("gamertag");
|
||||
return gamertag != null ? gamertag.getAsString() : null;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
>> config.yml
|
||||
>> floodgate-config.yml
|
||||
>>| 16
|
||||
# Should the proxy send the bedrock player data to the servers it is connecting to?
|
||||
# This requires Floodgate to be installed on the servers.
|
||||
Reference in New Issue
Block a user