Merge remote-tracking branch 'origin/feature/floodgate-merge'

# Conflicts:
#	bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java
#	bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java
#	bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
#	bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java
#	bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java
#	bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java
#	core/build.gradle.kts
#	core/src/main/java/org/geysermc/geyser/GeyserImpl.java
#	core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java
#	core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java
#	core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java
#	core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java
#	core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java
#	core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java
#	gradle/libs.versions.toml
This commit is contained in:
Tim203 2023-05-05 12:09:20 +02:00
commit 6ca53f5bf3
No known key found for this signature in database
GPG key ID: 736F3CD49EF01DBF
56 changed files with 733 additions and 315 deletions

View file

@ -7,7 +7,7 @@ plugins {
}
dependencies {
api(projects.common)
api("org.geysermc.floodgate", "core", "2.2.0-SNAPSHOT")
api(projects.api)
// Jackson JSON and YAML serialization

View file

@ -26,9 +26,9 @@
package org.geysermc.connector;
import org.geysermc.api.Geyser;
import org.geysermc.common.PlatformType;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.util.PlatformType;
import java.util.UUID;

View file

@ -25,9 +25,12 @@
package org.geysermc.geyser;
import org.geysermc.floodgate.skin.SkinApplier;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.hybrid.FloodgateHybridProvider;
import org.geysermc.geyser.hybrid.HybridProvider;
import org.geysermc.geyser.level.GeyserWorldManager;
import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
@ -134,6 +137,20 @@ public interface GeyserBootstrap {
return Paths.get("logs/latest.log");
}
/**
* Creates the hybrid provider for this platform. The provider will differ based on server access.
*/
default HybridProvider createHybridProvider(GeyserImpl geyser) {
return new FloodgateHybridProvider(geyser);
}
/**
* Returns the skin applier for this platform, if the hybrid provider is integrated with the system.
*/
default SkinApplier createSkinApplier() {
throw new IllegalStateException();
}
/**
* Get an InputStream for the given resource path.
* Overridden on platforms that have different class loader properties.

View file

@ -43,14 +43,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.api.Geyser;
import org.geysermc.common.PlatformType;
import org.geysermc.cumulus.form.Form;
import org.geysermc.cumulus.form.util.FormBuilder;
import org.geysermc.erosion.packet.Packets;
import org.geysermc.floodgate.crypto.AesCipher;
import org.geysermc.floodgate.crypto.AesKeyProducer;
import org.geysermc.floodgate.crypto.Base64Topping;
import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.floodgate.FloodgatePlatform;
import org.geysermc.floodgate.news.NewsItemAction;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.event.EventBus;
@ -67,6 +63,7 @@ import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.erosion.UnixSocketClientListener;
import org.geysermc.geyser.event.GeyserEventBus;
import org.geysermc.geyser.extension.GeyserExtensionManager;
import org.geysermc.geyser.hybrid.HybridProvider;
import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.network.netty.GeyserServer;
import org.geysermc.geyser.pack.ResourcePack;
@ -76,7 +73,7 @@ import org.geysermc.geyser.scoreboard.ScoreboardUpdater;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
import org.geysermc.geyser.session.SessionManager;
import org.geysermc.geyser.skin.FloodgateSkinUploader;
import org.geysermc.geyser.skin.BedrockSkinUploader;
import org.geysermc.geyser.skin.ProvidedSkins;
import org.geysermc.geyser.skin.SkinProvider;
import org.geysermc.geyser.text.GeyserLocale;
@ -90,7 +87,6 @@ import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.security.Key;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@ -133,8 +129,8 @@ public class GeyserImpl implements GeyserApi {
@Setter
private static boolean shouldStartListener = true;
private FloodgateCipher cipher;
private FloodgateSkinUploader skinUploader;
private HybridProvider hybridProvider;
private BedrockSkinUploader skinUploader;
private NewsHandler newsHandler;
private UnixSocketClientListener erosionUnixListener;
@ -158,10 +154,18 @@ public class GeyserImpl implements GeyserApi {
private static GeyserImpl instance;
private GeyserImpl(PlatformType platformType, GeyserBootstrap bootstrap) {
instance = this;
private final FloodgatePlatform floodgatePlatform;
Geyser.set(this);
private GeyserImpl(PlatformType platformType, GeyserBootstrap bootstrap, FloodgatePlatform floodgatePlatform) {
instance = this;
this.floodgatePlatform = floodgatePlatform;
if (floodgatePlatform != null) {
floodgatePlatform.load();
floodgatePlatform.enable();
} else {
Geyser.set(this);
}
this.platformType = platformType;
this.bootstrap = bootstrap;
@ -259,7 +263,7 @@ public class GeyserImpl implements GeyserApi {
SkinProvider.registerCacheImageTask(this);
ResourcePack.loadPacks();
//TODO start
String geyserUdpPort = System.getProperty("geyserUdpPort", "");
String pluginUdpPort = geyserUdpPort.isEmpty() ? System.getProperty("pluginUdpPort", "") : geyserUdpPort;
if ("-1".equals(pluginUdpPort)) {
@ -335,6 +339,7 @@ public class GeyserImpl implements GeyserApi {
config.getRemote().setAuthType(AuthType.FLOODGATE);
}
}
//TODO end
String remoteAddress = config.getRemote().address();
// Filters whether it is not an IP address or localhost, because otherwise it is not possible to find out an SRV entry.
@ -392,16 +397,14 @@ public class GeyserImpl implements GeyserApi {
}
if (config.getRemote().authType() == AuthType.FLOODGATE) {
hybridProvider = bootstrap.createHybridProvider(this);
try {
Key key = new AesKeyProducer().produceFrom(config.getFloodgateKeyPath());
cipher = new AesCipher(new Base64Topping());
cipher.init(key);
logger.debug("Loaded Floodgate key!");
// Note: this is positioned after the bind so the skin uploader doesn't try to run if Geyser fails
// to load successfully. Spigot complains about class loader if the plugin is disabled.
skinUploader = new FloodgateSkinUploader(this).start();
// TODO not Floodgate exclusive?
skinUploader = new BedrockSkinUploader(this).start();
} catch (Exception exception) {
logger.severe(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.bad_key"), exception);
logger.severe("Could not start the skin uploader!", exception);
}
}
@ -687,9 +690,9 @@ public class GeyserImpl implements GeyserApi {
return Integer.parseInt(BUILD_NUMBER);
}
public static GeyserImpl load(PlatformType platformType, GeyserBootstrap bootstrap) {
public static GeyserImpl load(PlatformType platformType, GeyserBootstrap bootstrap, FloodgatePlatform floodgatePlatform) {
if (instance == null) {
return new GeyserImpl(platformType, bootstrap);
return new GeyserImpl(platformType, bootstrap, floodgatePlatform);
}
return instance;

View file

@ -29,38 +29,22 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.api.command.CommandExecutor;
import org.geysermc.geyser.api.command.CommandSource;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCommandsEvent;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.command.defaults.AdvancedTooltipsCommand;
import org.geysermc.geyser.command.defaults.AdvancementsCommand;
import org.geysermc.geyser.command.defaults.ConnectionTestCommand;
import org.geysermc.geyser.command.defaults.DumpCommand;
import org.geysermc.geyser.command.defaults.ExtensionsCommand;
import org.geysermc.geyser.command.defaults.HelpCommand;
import org.geysermc.geyser.command.defaults.ListCommand;
import org.geysermc.geyser.command.defaults.OffhandCommand;
import org.geysermc.geyser.command.defaults.ReloadCommand;
import org.geysermc.geyser.command.defaults.SettingsCommand;
import org.geysermc.geyser.command.defaults.StatisticsCommand;
import org.geysermc.geyser.command.defaults.StopCommand;
import org.geysermc.geyser.command.defaults.VersionCommand;
import org.geysermc.geyser.command.defaults.*;
import org.geysermc.geyser.event.type.GeyserDefineCommandsEventImpl;
import org.geysermc.geyser.extension.command.GeyserExtensionCommand;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.PlatformType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.*;
@RequiredArgsConstructor
public class GeyserCommandManager {

View file

@ -26,13 +26,13 @@
package org.geysermc.geyser.command.defaults;
import com.fasterxml.jackson.databind.JsonNode;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.LoopbackUtil;
import org.geysermc.geyser.util.PlatformType;
import org.geysermc.geyser.util.WebUtils;
import org.jetbrains.annotations.Nullable;

View file

@ -30,7 +30,6 @@ import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
@ -39,6 +38,7 @@ import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.AsteriskSerializer;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.PlatformType;
import org.geysermc.geyser.util.WebUtils;
import java.io.FileOutputStream;

View file

@ -25,7 +25,6 @@
package org.geysermc.geyser.command.defaults;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.command.GeyserCommand;
@ -33,6 +32,7 @@ import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.PlatformType;
import java.util.Collections;
import java.util.Map;

View file

@ -25,12 +25,12 @@
package org.geysermc.geyser.command.defaults;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.PlatformType;
public class ReloadCommand extends GeyserCommand {

View file

@ -25,12 +25,12 @@
package org.geysermc.geyser.command.defaults;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.PlatformType;
import java.util.Collections;

View file

@ -26,7 +26,6 @@
package org.geysermc.geyser.command.defaults;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
@ -34,6 +33,7 @@ import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.PlatformType;
import org.geysermc.geyser.util.WebUtils;
import java.io.IOException;

View file

@ -51,6 +51,8 @@ public interface GeyserConfiguration {
IRemoteConfiguration getRemote();
HybridInfo getHybridInfo();
List<String> getSavedUserLogins();
@Deprecated
@ -164,6 +166,13 @@ public interface GeyserConfiguration {
void setAuthType(AuthType authType);
}
// TODO this is definitely temporary
interface HybridInfo {
String usernamePrefix();
boolean replaceSpaces();
}
interface IUserAuthenticationInfo {
String getEmail();

View file

@ -59,6 +59,18 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
private BedrockConfiguration bedrock = new BedrockConfiguration();
private RemoteConfiguration remote = new RemoteConfiguration();
private HybridInfo hybridInfo = new HybridInfo() {
@Override
public String usernamePrefix() {
return ".";
}
@Override
public boolean replaceSpaces() {
return true;
}
};
@JsonProperty("saved-user-logins")
private List<String> savedUserLogins = Collections.emptyList();

View file

@ -27,9 +27,9 @@ package org.geysermc.geyser.dump;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.text.AsteriskSerializer;
import org.geysermc.geyser.util.PlatformType;
import java.util.List;

View file

@ -36,8 +36,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.geysermc.floodgate.util.DeviceOs;
import org.geysermc.floodgate.util.FloodgateInfoHolder;
import org.geysermc.api.util.BedrockPlatform;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.extension.Extension;
@ -78,7 +77,7 @@ public class DumpInfo {
private final GitInfo gitInfo;
private final GeyserConfiguration config;
private final Floodgate floodgate;
private final Object2IntMap<DeviceOs> userPlatforms;
private final Object2IntMap<BedrockPlatform> userPlatforms;
private final HashInfo hashInfo;
private final RamInfo ramInfo;
private LogsInfo logsInfo;
@ -126,7 +125,7 @@ public class DumpInfo {
this.userPlatforms = new Object2IntOpenHashMap<>();
for (GeyserSession session : GeyserImpl.getInstance().getSessionManager().getAllSessions()) {
DeviceOs device = session.getClientData().getDeviceOs();
BedrockPlatform device = session.getClientData().getDeviceOs();
userPlatforms.put(device, userPlatforms.getOrDefault(device, 0) + 1);
}
@ -238,8 +237,11 @@ public class DumpInfo {
private final Object config;
Floodgate() {
this.gitInfo = FloodgateInfoHolder.getGitProperties();
this.config = FloodgateInfoHolder.getConfig();
//todo we can get the information from Floodgate directly now
this.gitInfo = null;
this.config = null;
// this.gitInfo = FloodgateInfoHolder.getGitProperties();
// this.config = FloodgateInfoHolder.getConfig();
}
}

View file

@ -36,7 +36,6 @@ import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket;
import org.geysermc.floodgate.util.DeviceOs;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.level.FireworkColor;
@ -65,13 +64,6 @@ public class FireworkEntity extends Entity {
return;
}
// TODO: Remove once Mojang fixes bugs with fireworks crashing clients on these specific devices.
// https://bugs.mojang.com/browse/MCPE-89115
if (session.getClientData().getDeviceOs() == DeviceOs.XBOX
|| session.getClientData().getDeviceOs() == DeviceOs.PS4) {
return;
}
CompoundTag fireworks = tag.get("Fireworks");
if (fireworks == null) {
// Thank you Mineplex very cool

View file

@ -0,0 +1,40 @@
/*
* 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/Geyser
*/
package org.geysermc.geyser.floodgate;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
public class GeyserLoadStage extends AbstractModule {
@Provides
@Singleton
@Named("configFile")
private String floodgateConfigName() {
return "floodgate.yml";
}
}

View file

@ -0,0 +1,53 @@
/*
* 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/Geyser
*/
package org.geysermc.geyser.hybrid;
import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.GeyserSession;
import java.nio.charset.StandardCharsets;
public final class FloodgateHybridProvider implements HybridProvider {
private final FloodgateCipher cipher;
public FloodgateHybridProvider(GeyserImpl geyser) {
cipher = geyser.getFloodgatePlatform().getInstance(FloodgateCipher.class);
}
@Override
public void onSkinUpload(GeyserSession session, String value, String signature) {
byte[] bytes = (value + '\0' + signature)
.getBytes(StandardCharsets.UTF_8);
//todo
// PluginMessageUtils.sendMessage(session, PluginMessageChannels.SKIN, bytes);
}
@Override
public FloodgateCipher getCipher() {
return cipher;
}
}

View file

@ -0,0 +1,35 @@
/*
* 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/Geyser
*/
package org.geysermc.geyser.hybrid;
import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.geyser.session.GeyserSession;
public interface HybridProvider {
void onSkinUpload(GeyserSession session, String value, String signature);
FloodgateCipher getCipher();
}

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.hybrid;
import io.netty.util.AttributeKey;
import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.floodgate.skin.SkinApplier;
import org.geysermc.floodgate.skin.SkinData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.GeyserSession;
public class IntegratedHybridProvider implements HybridProvider {
// TODO This will probably end up as its own class.
public static final AttributeKey<GeyserSession> SESSION_KEY = AttributeKey.valueOf("geyser-session");
private final SkinApplier skinApplier;
public IntegratedHybridProvider(GeyserImpl geyser) {
skinApplier = geyser.getBootstrap().createSkinApplier();
}
@Override
public void onSkinUpload(GeyserSession session, String value, String signature) {
skinApplier.applySkin(session, new SkinData(value, signature));
}
@Override
public FloodgateCipher getCipher() {
throw new UnsupportedOperationException();
}
}

View file

@ -0,0 +1,43 @@
/*
* 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/Geyser
*/
package org.geysermc.geyser.hybrid;
import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.geyser.GeyserImpl;
public final class ProxyHybridProvider extends IntegratedHybridProvider {
private final FloodgateCipher cipher;
public ProxyHybridProvider(GeyserImpl geyser) {
super(geyser);
this.cipher = geyser.getFloodgatePlatform().getInstance(FloodgateCipher.class);
}
@Override
public FloodgateCipher getCipher() {
return cipher;
}
}

View file

@ -27,6 +27,10 @@ package org.geysermc.geyser.network.netty;
import io.netty.channel.local.LocalChannel;
import io.netty.channel.local.LocalServerChannel;
import io.netty.util.Attribute;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.hybrid.IntegratedHybridProvider;
import org.geysermc.geyser.session.GeyserSession;
/**
* If the incoming channel if an instance of LocalChannelWithRemoteAddress, this server creates a LocalChannelWrapper
@ -36,9 +40,17 @@ public class LocalServerChannelWrapper extends LocalServerChannel {
@Override
protected LocalChannel newLocalChannel(LocalChannel peer) {
// LocalChannel here should be an instance of LocalChannelWithRemoteAddress, which we can use to set the "remote address" on the other end
if (peer instanceof LocalChannelWithRemoteAddress) {
if (peer instanceof LocalChannelWithRemoteAddress) { // TODO also use attribute for this
LocalChannelWrapper channel = new LocalChannelWrapper(this, peer);
channel.wrapper().remoteAddress(((LocalChannelWithRemoteAddress) peer).spoofedRemoteAddress());
if (GeyserImpl.getInstance().getHybridProvider() instanceof IntegratedHybridProvider) {
Attribute<GeyserSession> attribute = peer.attr(IntegratedHybridProvider.SESSION_KEY);
GeyserSession session = attribute.get();
// Garbage collect since it's no longer relevant for the PacketLib side.
attribute.set(null);
channel.attr(IntegratedHybridProvider.SESSION_KEY).set(session);
}
return channel;
}
return super.newLocalChannel(peer);

View file

@ -37,7 +37,12 @@ import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.unix.PreferredDirectByteBufAllocator;
import io.netty.handler.codec.haproxy.*;
import io.netty.util.Attribute;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.hybrid.IntegratedHybridProvider;
import org.geysermc.geyser.session.GeyserSession;
import javax.annotation.Nullable;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
@ -53,11 +58,14 @@ public final class LocalSession extends TcpSession {
private final String clientIp;
private final PacketCodecHelper codecHelper;
public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, MinecraftCodecHelper codecHelper) {
private final GeyserSession session;
public LocalSession(@Nullable GeyserSession session, String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, MinecraftCodecHelper codecHelper) {
super(host, port, protocol);
this.targetAddress = targetAddress;
this.clientIp = clientIp;
this.codecHelper = codecHelper;
this.session = session;
}
@Override
@ -89,6 +97,11 @@ public final class LocalSession extends TcpSession {
pipeline.addLast("manager", LocalSession.this);
addHAProxySupport(pipeline);
if (GeyserImpl.getInstance().getHybridProvider() instanceof IntegratedHybridProvider) {
Attribute<GeyserSession> attribute = channel.attr(IntegratedHybridProvider.SESSION_KEY);
attribute.set(session);
}
}
}).group(DEFAULT_EVENT_LOOP_GROUP).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getConnectTimeout() * 1000);

View file

@ -33,6 +33,7 @@ import org.geysermc.geyser.registry.loader.RegistryLoaders;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.util.PlatformType;
import java.util.Collections;
import java.util.IdentityHashMap;

View file

@ -94,7 +94,6 @@ import org.cloudburstmc.protocol.common.util.OptionalBoolean;
import org.geysermc.api.util.BedrockPlatform;
import org.geysermc.api.util.InputMode;
import org.geysermc.api.util.UiProfile;
import org.geysermc.common.PlatformType;
import org.geysermc.cumulus.form.Form;
import org.geysermc.cumulus.form.util.FormBuilder;
import org.geysermc.floodgate.crypto.FloodgateCipher;
@ -116,6 +115,8 @@ import org.geysermc.geyser.entity.type.Tickable;
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.erosion.AbstractGeyserboundPacketHandler;
import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler;
import org.geysermc.geyser.hybrid.FloodgateHybridProvider;
import org.geysermc.geyser.hybrid.HybridProvider;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
@ -131,15 +132,13 @@ import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.auth.AuthData;
import org.geysermc.geyser.session.auth.BedrockClientData;
import org.geysermc.geyser.session.cache.*;
import org.geysermc.geyser.skin.FloodgateSkinUploader;
import org.geysermc.geyser.skin.BedrockSkinUploader;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.text.TextDecoration;
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.LoginEncryptionUtils;
import org.geysermc.geyser.util.*;
import org.jetbrains.annotations.NotNull;
import java.net.ConnectException;
@ -886,7 +885,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
TcpSession downstream;
if (geyser.getBootstrap().getSocketAddress() != null) {
// We're going to connect through the JVM and not through TCP
downstream = new LocalSession(this.remoteServer.address(), this.remoteServer.port(),
downstream = new LocalSession(this, this.remoteServer.address(), this.remoteServer.port(),
geyser.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(),
this.protocol, this.protocol.createHelper());
this.downstream = new DownstreamSession(downstream);
@ -910,12 +909,13 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
//todo move this somewhere else
if (event.getPacket() instanceof ClientIntentionPacket) {
String addressSuffix;
if (floodgate) {
HybridProvider provider;
if (floodgate && (provider = geyser.getHybridProvider()) instanceof FloodgateHybridProvider) {
byte[] encryptedData;
try {
FloodgateSkinUploader skinUploader = geyser.getSkinUploader();
FloodgateCipher cipher = geyser.getCipher();
BedrockSkinUploader skinUploader = geyser.getSkinUploader();
FloodgateCipher cipher = provider.getCipher();
String bedrockAddress = upstream.getAddress().getAddress().getHostAddress();
// both BungeeCord and Velocity remove the IPv6 scope (if there is one) for Spigot
@ -1434,7 +1434,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
upstream.sendPacket(chunkRadiusUpdatedPacket);
}
public InetSocketAddress getSocketAddress() {
@Override
public InetSocketAddress socketAddress() {
return this.upstream.getAddress();
}
@ -1885,7 +1886,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
@Override
public @NonNull BedrockPlatform platform() {
return BedrockPlatform.values()[clientData.getDeviceOs().ordinal()]; //todo
return clientData.getDeviceOs();
}
@Override
@ -1895,12 +1896,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
@Override
public @NonNull UiProfile uiProfile() {
return UiProfile.values()[clientData.getUiProfile().ordinal()]; //todo
return clientData.getUiProfile();
}
@Override
public @NonNull InputMode inputMode() {
return InputMode.values()[clientData.getCurrentInputMode().ordinal()]; //todo
return clientData.getCurrentInputMode();
}
@Override

View file

@ -30,9 +30,9 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.floodgate.util.DeviceOs;
import org.geysermc.floodgate.util.InputMode;
import org.geysermc.floodgate.util.UiProfile;
import org.geysermc.api.util.BedrockPlatform;
import org.geysermc.api.util.InputMode;
import org.geysermc.api.util.UiProfile;
import java.util.UUID;
@ -80,7 +80,7 @@ public final class BedrockClientData {
@JsonProperty(value = "DeviceModel")
private String deviceModel;
@JsonProperty(value = "DeviceOS")
private DeviceOs deviceOs;
private BedrockPlatform deviceOs;
@JsonProperty(value = "UIProfile")
private UiProfile uiProfile;
@JsonProperty(value = "GuiScale")
@ -113,8 +113,8 @@ public final class BedrockClientData {
@Setter
private String originalString = null;
public DeviceOs getDeviceOs() {
return deviceOs != null ? deviceOs : DeviceOs.UNKNOWN;
public BedrockPlatform getDeviceOs() {
return deviceOs != null ? deviceOs : BedrockPlatform.UNKNOWN;
}
public InputMode getCurrentInputMode() {

View file

@ -32,26 +32,23 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.nimbusds.jwt.SignedJWT;
import lombok.Getter;
import org.geysermc.floodgate.pluginmessage.PluginMessageChannels;
import org.geysermc.floodgate.util.WebsocketEventType;
import org.geysermc.geyser.Constants;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.PluginMessageUtils;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import javax.net.ssl.SSLException;
import java.net.ConnectException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
public final class FloodgateSkinUploader {
public final class BedrockSkinUploader {
private final ObjectMapper JACKSON = new ObjectMapper();
private final List<String> skinQueue = new ArrayList<>();
@ -61,9 +58,8 @@ public final class FloodgateSkinUploader {
@Getter private int id;
@Getter private String verifyCode;
@Getter private int subscribersCount;
public FloodgateSkinUploader(GeyserImpl geyser) {
public BedrockSkinUploader(GeyserImpl geyser) {
this.logger = geyser.getLogger();
this.client = new WebSocketClient(Constants.GLOBAL_API_WS_URI) {
@Override
@ -102,14 +98,11 @@ public final class FloodgateSkinUploader {
verifyCode = node.get("verify_code").asText();
break;
case SUBSCRIBER_COUNT:
subscribersCount = node.get("subscribers_count").asInt();
logger.debug("Ignoring subscribers count message.");
break;
case SKIN_UPLOADED:
// if Geyser is the only subscriber we have send it to the server manually
// otherwise it's handled by the Floodgate plugin subscribers
if (subscribersCount != 1) {
break;
}
String xuid = node.get("xuid").asText();
GeyserSession session = geyser.connectionByXuid(xuid);
@ -125,9 +118,7 @@ public final class FloodgateSkinUploader {
String value = data.get("value").asText();
String signature = data.get("signature").asText();
byte[] bytes = (value + '\0' + signature)
.getBytes(StandardCharsets.UTF_8);
PluginMessageUtils.sendMessage(session, PluginMessageChannels.SKIN, bytes);
geyser.getHybridProvider().onSkinUpload(session, value, signature);
}
break;
case LOG_MESSAGE:
@ -226,7 +217,7 @@ public final class FloodgateSkinUploader {
.schedule(client::reconnect, 8 + additionalTime, TimeUnit.SECONDS);
}
public FloodgateSkinUploader start() {
public BedrockSkinUploader start() {
client.connect();
return this;
}

View file

@ -36,7 +36,6 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import lombok.Getter;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.physics.Axis;
import org.geysermc.geyser.level.physics.BoundingBox;
@ -50,6 +49,7 @@ import org.geysermc.geyser.translator.collision.BlockCollision;
import org.geysermc.geyser.util.BlockEntityUtils;
import org.geysermc.geyser.util.BlockUtils;
import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.PlatformType;
import java.util.LinkedList;
import java.util.Map;

View file

@ -26,13 +26,13 @@
package org.geysermc.geyser.translator.protocol.bedrock;
import org.cloudburstmc.protocol.bedrock.packet.CommandRequestPacket;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.PlatformType;
@Translator(packet = CommandRequestPacket.class)
public class BedrockCommandRequestTranslator extends PacketTranslator<CommandRequestPacket> {

View file

@ -29,7 +29,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundKe
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
import org.cloudburstmc.protocol.bedrock.packet.NetworkStackLatencyPacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import org.geysermc.floodgate.util.DeviceOs;
import org.geysermc.api.util.BedrockPlatform;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
@ -50,7 +50,7 @@ public class BedrockNetworkStackLatencyTranslator extends PacketTranslator<Netwo
// so apparently, as of 1.16.200
// PS4 divides the network stack latency timestamp FOR US!!!
// WTF
if (session.getClientData().getDeviceOs().equals(DeviceOs.PS4)) {
if (session.getClientData().getDeviceOs() == BedrockPlatform.PS4) {
pingId = packet.getTimestamp();
} else {
pingId = packet.getTimestamp() / 1000;

View file

@ -26,28 +26,12 @@
package org.geysermc.geyser.translator.protocol.java;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCustomPayloadPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCustomPayloadPacket;
import com.google.common.base.Charsets;
import org.cloudburstmc.protocol.bedrock.packet.TransferPacket;
import org.cloudburstmc.protocol.bedrock.packet.UnknownPacket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.geysermc.cumulus.Forms;
import org.geysermc.cumulus.form.Form;
import org.geysermc.cumulus.form.util.FormType;
import org.geysermc.erosion.Constants;
import org.geysermc.erosion.packet.ErosionPacket;
import org.geysermc.erosion.packet.Packets;
import org.geysermc.erosion.packet.geyserbound.GeyserboundPacket;
import org.geysermc.floodgate.pluginmessage.PluginMessageChannels;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import java.nio.charset.StandardCharsets;
@Translator(packet = ClientboundCustomPayloadPacket.class)
public class JavaCustomPayloadTranslator extends PacketTranslator<ClientboundCustomPayloadPacket> {
private final GeyserLogger logger = GeyserImpl.getInstance().getLogger();
@ -56,89 +40,89 @@ public class JavaCustomPayloadTranslator extends PacketTranslator<ClientboundCus
public void translate(GeyserSession session, ClientboundCustomPayloadPacket packet) {
String channel = packet.getChannel();
if (channel.equals(Constants.PLUGIN_MESSAGE)) {
ByteBuf buf = Unpooled.wrappedBuffer(packet.getData());
ErosionPacket<?> erosionPacket = Packets.decode(buf);
((GeyserboundPacket) erosionPacket).handle(session.getErosionHandler());
return;
}
if (channel.equals(PluginMessageChannels.FORM)) {
session.ensureInEventLoop(() -> {
byte[] data = packet.getData();
// receive: first byte is form type, second and third are the id, remaining is the form data
// respond: first and second byte id, remaining is form response data
FormType type = FormType.fromOrdinal(data[0]);
if (type == null) {
throw new NullPointerException("Got type " + data[0] + " which isn't a valid form type!");
}
String dataString = new String(data, 3, data.length - 3, Charsets.UTF_8);
Form form = Forms.fromJson(dataString, type, (ignored, response) -> {
byte[] finalData;
if (response == null) {
// Response data can be null as of 1.19.20 (same behaviour as empty response data)
// Only need to send the form id
finalData = new byte[]{data[1], data[2]};
} else {
byte[] raw = response.getBytes(StandardCharsets.UTF_8);
finalData = new byte[raw.length + 2];
finalData[0] = data[1];
finalData[1] = data[2];
System.arraycopy(raw, 0, finalData, 2, raw.length);
}
session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(channel, finalData));
});
session.sendForm(form);
});
} else if (channel.equals(PluginMessageChannels.TRANSFER)) {
session.ensureInEventLoop(() -> {
byte[] data = packet.getData();
// port (4 bytes), address (remaining data)
if (data.length < 5) {
throw new NullPointerException("Transfer data should be at least 5 bytes long");
}
int port = data[0] << 24 | (data[1] & 0xFF) << 16 | (data[2] & 0xFF) << 8 | data[3] & 0xFF;
String address = new String(data, 4, data.length - 4);
if (logger.isDebug()) {
logger.info("Transferring client to: " + address + ":" + port);
}
TransferPacket transferPacket = new TransferPacket();
transferPacket.setAddress(address);
transferPacket.setPort(port);
session.sendUpstreamPacket(transferPacket);
});
} else if (channel.equals(PluginMessageChannels.PACKET)) {
session.ensureInEventLoop(() -> {
logger.debug("A packet has been sent using the Floodgate api");
byte[] data = packet.getData();
// packet id, packet data
if (data.length < 2) {
throw new IllegalStateException("Packet data should be at least 2 bytes long");
}
int packetId = data[0] & 0xFF;
ByteBuf packetData = Unpooled.wrappedBuffer(data, 1, data.length - 1);
var toSend = new UnknownPacket();
toSend.setPacketId(packetId);
toSend.setPayload(packetData);
session.sendUpstreamPacket(toSend);
});
}
// if (channel.equals(Constants.PLUGIN_MESSAGE)) {
// ByteBuf buf = Unpooled.wrappedBuffer(packet.getData());
// ErosionPacket<?> erosionPacket = Packets.decode(buf);
// ((GeyserboundPacket) erosionPacket).handle(session.getErosionHandler());
// return;
// }
//
// if (channel.equals(PluginMessageChannels.FORM)) {
// session.ensureInEventLoop(() -> {
// byte[] data = packet.getData();
//
// // receive: first byte is form type, second and third are the id, remaining is the form data
// // respond: first and second byte id, remaining is form response data
//
// FormType type = FormType.fromOrdinal(data[0]);
// if (type == null) {
// throw new NullPointerException("Got type " + data[0] + " which isn't a valid form type!");
// }
//
// String dataString = new String(data, 3, data.length - 3, Charsets.UTF_8);
//
// Form form = Forms.fromJson(dataString, type, (ignored, response) -> {
// byte[] finalData;
// if (response == null) {
// // Response data can be null as of 1.19.20 (same behaviour as empty response data)
// // Only need to send the form id
// finalData = new byte[]{data[1], data[2]};
// } else {
// byte[] raw = response.getBytes(StandardCharsets.UTF_8);
// finalData = new byte[raw.length + 2];
//
// finalData[0] = data[1];
// finalData[1] = data[2];
// System.arraycopy(raw, 0, finalData, 2, raw.length);
// }
//
// session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(channel, finalData));
// });
// session.sendForm(form);
// });
//
// } else if (channel.equals(PluginMessageChannels.TRANSFER)) {
// session.ensureInEventLoop(() -> {
// byte[] data = packet.getData();
//
// // port (4 bytes), address (remaining data)
// if (data.length < 5) {
// throw new NullPointerException("Transfer data should be at least 5 bytes long");
// }
//
// int port = data[0] << 24 | (data[1] & 0xFF) << 16 | (data[2] & 0xFF) << 8 | data[3] & 0xFF;
// String address = new String(data, 4, data.length - 4);
//
// if (logger.isDebug()) {
// logger.info("Transferring client to: " + address + ":" + port);
// }
//
// TransferPacket transferPacket = new TransferPacket();
// transferPacket.setAddress(address);
// transferPacket.setPort(port);
// session.sendUpstreamPacket(transferPacket);
// });
//
// } else if (channel.equals(PluginMessageChannels.PACKET)) {
// session.ensureInEventLoop(() -> {
// logger.debug("A packet has been sent using the Floodgate api");
// byte[] data = packet.getData();
//
// // packet id, packet data
// if (data.length < 2) {
// throw new IllegalStateException("Packet data should be at least 2 bytes long");
// }
//
// int packetId = data[0] & 0xFF;
// ByteBuf packetData = Unpooled.wrappedBuffer(data, 1, data.length - 1);
//
// var toSend = new UnknownPacket();
// toSend.setPacketId(packetId);
// toSend.setPayload(packetData);
//
// session.sendUpstreamPacket(toSend);
// });
// }
}
@Override

View file

@ -29,13 +29,13 @@ import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLog
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TranslatableComponent;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.PlatformType;
import java.util.List;

View file

@ -33,7 +33,6 @@ import org.cloudburstmc.protocol.bedrock.data.GameRuleData;
import org.cloudburstmc.protocol.bedrock.packet.GameRulesChangedPacket;
import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.geysermc.floodgate.pluginmessage.PluginMessageChannels;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler;
@ -141,7 +140,8 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
// }
// register the plugin messaging channels used in Floodgate
if (session.remoteServer().authType() == AuthType.FLOODGATE) {
session.sendDownstreamPacket(new ServerboundCustomPayloadPacket("minecraft:register", PluginMessageChannels.getFloodgateRegisterData()));
//todo
// session.sendDownstreamPacket(new ServerboundCustomPayloadPacket("minecraft:register", PluginMessageChannels.getFloodgateRegisterData()));
}
if (!newDimension.equals(session.getDimension())) {

View file

@ -33,7 +33,6 @@ import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
import org.cloudburstmc.protocol.bedrock.packet.BlockEventPacket;
import it.unimi.dsi.fastutil.objects.Object2IntMaps;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.session.GeyserSession;
@ -41,6 +40,7 @@ import org.geysermc.geyser.session.cache.PistonCache;
import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.PlatformType;
@Translator(packet = ClientboundBlockEventPacket.class)
public class JavaBlockEventTranslator extends PacketTranslator<ClientboundBlockEventPacket> {

View file

@ -29,13 +29,13 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.Clientb
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator;
import org.geysermc.geyser.util.PlatformType;
@Translator(packet = ClientboundBlockUpdatePacket.class)
public class JavaBlockUpdateTranslator extends PacketTranslator<ClientboundBlockUpdatePacket> {

View file

@ -0,0 +1,43 @@
/*
* 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/Geyser
*/
package org.geysermc.geyser.util;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum PlatformType {
ANDROID("Android"),
BUNGEECORD("BungeeCord"),
FABRIC("Fabric"),
SPIGOT("Spigot"),
SPONGE("Sponge"),
STANDALONE("Standalone"),
VELOCITY("Velocity");
private final String platformName;
}

View file

@ -212,12 +212,6 @@ enable-proxy-connections: false
# 1400 is the default.
mtu: 1400
# Whether to connect directly into the Java server without creating a TCP connection.
# This should only be disabled if a plugin that interfaces with packets or the network does not work correctly with Geyser.
# If enabled on plugin versions, the remote address and port sections are ignored
# If disabled on plugin versions, expect performance decrease and latency increase
use-direct-connection: true
# Whether Geyser should attempt to disable compression for Bedrock players. This should be a benefit as there is no need to compress data
# when Java packets aren't being handled over the network.
# This requires use-direct-connection to be true.