mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Updated Gradle to 8.3 and made Geyser work with latest Floodgate
This commit is contained in:
parent
a4ee73d1ef
commit
a894ce9824
52 changed files with 206 additions and 1656 deletions
|
@ -23,11 +23,7 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
<<<<<<<< HEAD:core/src/main/java/org/geysermc/geyser/util/PlatformType.java
|
||||
package org.geysermc.geyser.util;
|
||||
========
|
||||
package org.geysermc.geyser.api.bedrock.camera;
|
||||
>>>>>>>> origin/master:api/src/main/java/org/geysermc/geyser/api/bedrock/camera/CameraShake.java
|
||||
|
||||
public enum CameraShake {
|
||||
POSITIONAL,
|
||||
|
|
|
@ -31,8 +31,6 @@ import net.md_5.bungee.api.config.ListenerInfo;
|
|||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.floodgate.bungee.BungeePlatform;
|
||||
import org.geysermc.floodgate.bungee.pluginmessage.BungeeSkinApplier;
|
||||
import org.geysermc.floodgate.core.skin.SkinApplier;
|
||||
import org.geysermc.geyser.api.util.PlatformType;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
|
@ -43,8 +41,6 @@ import org.geysermc.geyser.api.network.AuthType;
|
|||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.hybrid.HybridProvider;
|
||||
import org.geysermc.geyser.hybrid.ProxyHybridProvider;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.platform.bungeecord.command.GeyserBungeeCommandExecutor;
|
||||
|
@ -280,11 +276,6 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
.findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HybridProvider createHybridProvider(GeyserImpl geyser) {
|
||||
return new ProxyHybridProvider(geyser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkinApplier createSkinApplier() {
|
||||
// new BungeePlatform(this); // TODO hack to ensure ReflectionUtils prefix is applied and I don't forget about dealing with it
|
||||
|
|
|
@ -54,7 +54,6 @@ import org.geysermc.geyser.platform.fabric.command.GeyserFabricCommandExecutor;
|
|||
import org.geysermc.geyser.platform.fabric.world.GeyserFabricWorldManager;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.geysermc.geyser.util.PlatformType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
|
|
@ -53,8 +53,6 @@ import org.geysermc.geyser.api.extension.Extension;
|
|||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.hybrid.HybridProvider;
|
||||
import org.geysermc.geyser.hybrid.IntegratedHybridProvider;
|
||||
import org.geysermc.geyser.level.WorldManager;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
|
@ -414,11 +412,6 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||
return this.geyserInjector.getServerSocketAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HybridProvider createHybridProvider(GeyserImpl geyser) {
|
||||
return new IntegratedHybridProvider(geyser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkinApplier createSkinApplier() {
|
||||
// return new SpigotSkinApplier(new SpigotVersionSpecificMethods(this), this);
|
||||
|
|
|
@ -30,7 +30,7 @@ import io.netty.channel.ChannelHandler;
|
|||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import org.geysermc.floodgate.spigot.util.ClassNames;
|
||||
import org.geysermc.geyser.hybrid.IntegratedHybridProvider;
|
||||
import org.geysermc.geyser.floodgate.IntegratedFloodgateProvider;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
@ -42,7 +42,7 @@ public final class SpigotHybridChannelHandler extends ChannelInboundHandlerAdapt
|
|||
|
||||
@Override
|
||||
public void channelRead(@Nonnull ChannelHandlerContext ctx, @Nonnull Object packet) throws Exception {
|
||||
GeyserSession session = ctx.channel().attr(IntegratedHybridProvider.SESSION_KEY).get();
|
||||
GeyserSession session = ctx.channel().attr(IntegratedFloodgateProvider.SESSION_KEY).get();
|
||||
// TODO generify this code within Floodgate
|
||||
if (ClassNames.LOGIN_START_PACKET.isInstance(packet)) {
|
||||
Object networkManager = ctx.channel().pipeline().get("packet_handler");
|
||||
|
|
|
@ -296,7 +296,7 @@ public class GeyserStandaloneGUI {
|
|||
|
||||
for (GeyserSession player : GeyserImpl.getInstance().getSessionManager().getSessions().values()) {
|
||||
Vector<String> row = new Vector<>();
|
||||
row.add(player.socketAddress().getHostName());
|
||||
row.add(player.getUpstream().getAddress().getHostName());
|
||||
row.add(player.getPlayerEntity().getUsername());
|
||||
|
||||
playerTableModel.addRow(row);
|
||||
|
|
|
@ -2,11 +2,17 @@ dependencies {
|
|||
annotationProcessor(libs.velocity.api)
|
||||
implementation(libs.floodgate.velocity)
|
||||
api(projects.core)
|
||||
|
||||
compileOnlyApi(libs.velocity.api) {
|
||||
exclude(module = "org.yaml:snakeyaml")
|
||||
}
|
||||
}
|
||||
|
||||
platformRelocate("com.fasterxml.jackson")
|
||||
platformRelocate("it.unimi.dsi.fastutil")
|
||||
platformRelocate("net.kyori.adventure.text.serializer.gson.legacyimpl")
|
||||
platformRelocate("org.yaml.snakeyaml")
|
||||
platformRelocate("org.bstats") //todo
|
||||
|
||||
exclude("com.google.*:*")
|
||||
|
||||
|
@ -32,9 +38,6 @@ exclude("net.kyori:adventure-text-serializer-gson:*")
|
|||
exclude("net.kyori:adventure-text-serializer-legacy:*")
|
||||
exclude("net.kyori:adventure-nbt:*")
|
||||
|
||||
// These dependencies are already present on the platform
|
||||
provided(libs.velocity.api)
|
||||
|
||||
application {
|
||||
mainClass.set("org.geysermc.geyser.platform.velocity.GeyserVelocityMain")
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
|||
import lombok.Getter;
|
||||
import net.kyori.adventure.util.Codec;
|
||||
import org.geysermc.floodgate.core.FloodgatePlatform;
|
||||
import org.geysermc.floodgate.velocity.VelocityPlatform;
|
||||
import org.geysermc.geyser.api.util.PlatformType;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
|
@ -50,7 +51,7 @@ import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
|||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.platform.velocity.command.GeyserVelocityCommandExecutor;
|
||||
import org.geysermc.geyser.platform.velocity.floodgate.FloodgateVelocityPlatform;
|
||||
import org.geysermc.geyser.platform.velocity.floodgate.FloodgateModule;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -122,7 +123,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
|
||||
FloodgatePlatform platform = null;
|
||||
if (geyserConfig.getRemote().authType() == AuthType.FLOODGATE) {
|
||||
platform = guice.getInstance(FloodgateVelocityPlatform.class);
|
||||
platform = guice.createChildInjector(new FloodgateModule(configFolder)).getInstance(VelocityPlatform.class);
|
||||
}
|
||||
|
||||
this.geyser = GeyserImpl.load(PlatformType.VELOCITY, this, platform);
|
||||
|
|
|
@ -25,21 +25,20 @@
|
|||
|
||||
package org.geysermc.geyser.platform.velocity.floodgate;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import java.nio.file.Path;
|
||||
import org.geysermc.floodgate.isolation.library.LibraryManager;
|
||||
import org.geysermc.floodgate.velocity.VelocityPlatform;
|
||||
|
||||
public class FloodgateVelocityPlatform extends VelocityPlatform {
|
||||
public FloodgateVelocityPlatform(LibraryManager manager) {
|
||||
super(manager);
|
||||
public class FloodgateModule extends AbstractModule {
|
||||
private final Path dataDirectory;
|
||||
|
||||
public FloodgateModule(Path dataDirectory) {
|
||||
this.dataDirectory = dataDirectory;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// protected List<Module> loadStageModules() {
|
||||
// // Geyser being a dumb dumb
|
||||
// super.dataDirectory = Paths.get("plugins/" + GeyserImpl.NAME + "-Velocity/");
|
||||
//
|
||||
// var loaded = super.loadStageModules();
|
||||
// loaded.add(new GeyserLoadStage());
|
||||
// return loaded;
|
||||
// }
|
||||
@Override
|
||||
protected void configure() {
|
||||
var libsDirectory = dataDirectory.resolve("libs");
|
||||
bind(LibraryManager.class).toInstance(new LibraryManager(getClass().getClassLoader(), libsDirectory, true));
|
||||
}
|
||||
}
|
|
@ -8,8 +8,8 @@ repositories {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation("net.kyori", "indra-common", "3.1.1")
|
||||
implementation("com.github.johnrengelman", "shadow", "7.1.3-SNAPSHOT")
|
||||
implementation("net.kyori", "indra-common", "3.1.3")
|
||||
implementation("com.github.johnrengelman", "shadow", "8.1.1")
|
||||
|
||||
// Within the gradle plugin classpath, there is a version conflict between loom and some other
|
||||
// plugin for databind. This fixes it: minimum 2.13.2 is required by loom.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
plugins {
|
||||
`java-library`
|
||||
id("geyser.build-logic")
|
||||
id("io.freefair.lombok") version "6.3.0" apply false
|
||||
id("io.freefair.lombok") version "8.3" apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
plugins {
|
||||
id("geyser.publish-conventions")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.cumulus)
|
||||
api(libs.gson)
|
||||
}
|
||||
|
||||
indra {
|
||||
javaVersions {
|
||||
target(8)
|
||||
}
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.crypto;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.Key;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public final class AesCipher implements FloodgateCipher {
|
||||
public static final int IV_LENGTH = 12;
|
||||
private static final int TAG_BIT_LENGTH = 128;
|
||||
private static final String CIPHER_NAME = "AES/GCM/NoPadding";
|
||||
|
||||
private final SecureRandom secureRandom = new SecureRandom();
|
||||
private final Topping topping;
|
||||
private SecretKey secretKey;
|
||||
|
||||
public void init(Key key) {
|
||||
if (!"AES".equals(key.getAlgorithm())) {
|
||||
throw new RuntimeException(
|
||||
"Algorithm was expected to be AES, but got " + key.getAlgorithm()
|
||||
);
|
||||
}
|
||||
secretKey = (SecretKey) key;
|
||||
}
|
||||
|
||||
public byte[] encrypt(byte[] data) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance(CIPHER_NAME);
|
||||
|
||||
byte[] iv = new byte[IV_LENGTH];
|
||||
secureRandom.nextBytes(iv);
|
||||
|
||||
GCMParameterSpec spec = new GCMParameterSpec(TAG_BIT_LENGTH, iv);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, spec);
|
||||
byte[] cipherText = cipher.doFinal(data);
|
||||
|
||||
if (topping != null) {
|
||||
iv = topping.encode(iv);
|
||||
cipherText = topping.encode(cipherText);
|
||||
}
|
||||
|
||||
return ByteBuffer.allocate(HEADER.length + iv.length + cipherText.length + 1)
|
||||
.put(HEADER)
|
||||
.put(iv)
|
||||
.put((byte) 0x21)
|
||||
.put(cipherText)
|
||||
.array();
|
||||
}
|
||||
|
||||
public byte[] decrypt(byte[] cipherTextWithIv) throws Exception {
|
||||
checkHeader(cipherTextWithIv);
|
||||
|
||||
Cipher cipher = Cipher.getInstance(CIPHER_NAME);
|
||||
|
||||
int bufferLength = cipherTextWithIv.length - HEADER.length;
|
||||
ByteBuffer buffer = ByteBuffer.wrap(cipherTextWithIv, HEADER.length, bufferLength);
|
||||
|
||||
int ivLength = IV_LENGTH;
|
||||
|
||||
if (topping != null) {
|
||||
int mark = buffer.position();
|
||||
|
||||
// we need the first index, the second is for the actual data
|
||||
boolean found = false;
|
||||
while (buffer.hasRemaining() && !found) {
|
||||
if (buffer.get() == 0x21) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
ivLength = buffer.position() - mark - 1; // don't include the splitter itself
|
||||
// don't remove this cast, it'll cause problems if you remove it
|
||||
((Buffer) buffer).position(mark); // reset to the pre-while index
|
||||
}
|
||||
|
||||
byte[] iv = new byte[ivLength];
|
||||
buffer.get(iv);
|
||||
|
||||
// don't remove this cast, it'll cause problems if you remove it
|
||||
((Buffer) buffer).position(buffer.position() + 1); // skip splitter
|
||||
|
||||
byte[] cipherText = new byte[buffer.remaining()];
|
||||
buffer.get(cipherText);
|
||||
|
||||
if (topping != null) {
|
||||
iv = topping.decode(iv);
|
||||
cipherText = topping.decode(cipherText);
|
||||
}
|
||||
|
||||
GCMParameterSpec spec = new GCMParameterSpec(TAG_BIT_LENGTH, iv);
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
|
||||
return cipher.doFinal(cipherText);
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.crypto;
|
||||
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
public final class AesKeyProducer implements KeyProducer {
|
||||
public static int KEY_SIZE = 128;
|
||||
|
||||
@Override
|
||||
public SecretKey produce() {
|
||||
try {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||
keyGenerator.init(KEY_SIZE, secureRandom());
|
||||
return keyGenerator.generateKey();
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecretKey produceFrom(byte[] keyFileData) {
|
||||
try {
|
||||
return new SecretKeySpec(keyFileData, "AES");
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private SecureRandom secureRandom() throws NoSuchAlgorithmException {
|
||||
// use Windows-PRNG for windows (default impl is SHA1PRNG)
|
||||
if (System.getProperty("os.name").startsWith("Windows")) {
|
||||
return SecureRandom.getInstance("Windows-PRNG");
|
||||
} else {
|
||||
try {
|
||||
// NativePRNG (which should be the default on unix-systems) can still block your
|
||||
// system. Even though it isn't as bad as NativePRNGBlocking, we still try to
|
||||
// prevent that if possible
|
||||
return SecureRandom.getInstance("NativePRNGNonBlocking");
|
||||
} catch (NoSuchAlgorithmException ignored) {
|
||||
// at this point we just have to go with the default impl even if it blocks
|
||||
return new SecureRandom();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.crypto;
|
||||
|
||||
import org.geysermc.floodgate.util.InvalidFormatException;
|
||||
|
||||
import java.security.Key;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
/**
|
||||
* Responsible for both encrypting and decrypting data
|
||||
*/
|
||||
public interface FloodgateCipher {
|
||||
int VERSION = 0;
|
||||
byte[] IDENTIFIER = "^Floodgate^".getBytes(UTF_8);
|
||||
byte[] HEADER = (new String(IDENTIFIER, UTF_8) + (char) (VERSION + 0x3E)).getBytes(UTF_8);
|
||||
|
||||
static int version(String data) {
|
||||
if (data.length() <= HEADER.length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < IDENTIFIER.length; i++) {
|
||||
if (IDENTIFIER[i] != data.charAt(i)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return data.charAt(IDENTIFIER.length) - 0x3E;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the instance by giving it the key it needs to encrypt or decrypt data
|
||||
*
|
||||
* @param key the key used to encrypt and decrypt data
|
||||
*/
|
||||
void init(Key key);
|
||||
|
||||
/**
|
||||
* Encrypts the given data using the Key provided in {@link #init(Key)}
|
||||
*
|
||||
* @param data the data to encrypt
|
||||
* @return the encrypted data
|
||||
* @throws Exception when the encryption failed
|
||||
*/
|
||||
byte[] encrypt(byte[] data) throws Exception;
|
||||
|
||||
/**
|
||||
* Encrypts data from a String.<br> This method internally calls {@link #encrypt(byte[])}
|
||||
*
|
||||
* @param data the data to encrypt
|
||||
* @return the encrypted data
|
||||
* @throws Exception when the encryption failed
|
||||
*/
|
||||
default byte[] encryptFromString(String data) throws Exception {
|
||||
return encrypt(data.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the given data using the Key provided in {@link #init(Key)}
|
||||
*
|
||||
* @param data the data to decrypt
|
||||
* @return the decrypted data
|
||||
* @throws Exception when the decrypting failed
|
||||
*/
|
||||
byte[] decrypt(byte[] data) throws Exception;
|
||||
|
||||
/**
|
||||
* Decrypts a byte[] and turn it into a String.<br> This method internally calls {@link
|
||||
* #decrypt(byte[])} and converts the returned byte[] into a String.
|
||||
*
|
||||
* @param data the data to encrypt
|
||||
* @return the decrypted data in a UTF-8 String
|
||||
* @throws Exception when the decrypting failed
|
||||
*/
|
||||
default String decryptToString(byte[] data) throws Exception {
|
||||
byte[] decrypted = decrypt(data);
|
||||
if (decrypted == null) {
|
||||
return null;
|
||||
}
|
||||
return new String(decrypted, UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a String.<br> This method internally calls {@link #decrypt(byte[])} by converting
|
||||
* the UTF-8 String into a byte[]
|
||||
*
|
||||
* @param data the data to decrypt
|
||||
* @return the decrypted data in a byte[]
|
||||
* @throws Exception when the decrypting failed
|
||||
*/
|
||||
default byte[] decryptFromString(String data) throws Exception {
|
||||
return decrypt(data.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the header is valid. This method will throw an InvalidFormatException when the
|
||||
* header is invalid.
|
||||
*
|
||||
* @param data the data to check
|
||||
* @throws InvalidFormatException when the header is invalid
|
||||
*/
|
||||
default void checkHeader(byte[] data) throws InvalidFormatException {
|
||||
if (data.length <= HEADER.length) {
|
||||
throw new InvalidFormatException(
|
||||
"Data length is smaller then header." +
|
||||
"Needed " + HEADER.length + ", got " + data.length
|
||||
);
|
||||
}
|
||||
|
||||
for (int i = 0; i < IDENTIFIER.length; i++) {
|
||||
if (IDENTIFIER[i] != data[i]) {
|
||||
String identifier = new String(IDENTIFIER, UTF_8);
|
||||
String received = new String(data, 0, IDENTIFIER.length, UTF_8);
|
||||
throw new InvalidFormatException(
|
||||
"Expected identifier " + identifier + ", got " + received
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.crypto;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.Key;
|
||||
|
||||
public interface KeyProducer {
|
||||
Key produce();
|
||||
Key produceFrom(byte[] keyFileData);
|
||||
|
||||
default Key produceFrom(Path keyFileLocation) throws IOException {
|
||||
return produceFrom(Files.readAllBytes(keyFileLocation));
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.crypto;
|
||||
|
||||
public interface Topping {
|
||||
byte[] encode(byte[] data);
|
||||
byte[] decode(byte[] data);
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.news;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.geysermc.floodgate.news.data.ItemData;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class NewsItem {
|
||||
private final int id;
|
||||
private final boolean active;
|
||||
private final NewsType type;
|
||||
private final ItemData data;
|
||||
private final String message;
|
||||
private final Set<NewsItemAction> actions;
|
||||
private final String url;
|
||||
|
||||
private NewsItem(
|
||||
int id, boolean active, NewsType type, ItemData data,
|
||||
String message, Set<NewsItemAction> actions, String url) {
|
||||
|
||||
this.id = id;
|
||||
this.active = active;
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
this.message = message;
|
||||
this.actions = Collections.unmodifiableSet(actions);
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public static NewsItem readItem(JsonObject newsItem) {
|
||||
NewsType newsType = NewsType.getByName(newsItem.get("type").getAsString());
|
||||
if (newsType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JsonObject messageObject = newsItem.getAsJsonObject("message");
|
||||
NewsItemMessage itemMessage = NewsItemMessage.getById(messageObject.get("id").getAsInt());
|
||||
|
||||
String message = "Received an unknown news message type. Please update";
|
||||
if (itemMessage != null) {
|
||||
message = itemMessage.getFormattedMessage(messageObject.getAsJsonArray("args"));
|
||||
}
|
||||
|
||||
Set<NewsItemAction> actions = new HashSet<>();
|
||||
for (JsonElement actionElement : newsItem.getAsJsonArray("actions")) {
|
||||
NewsItemAction action = NewsItemAction.getByName(actionElement.getAsString());
|
||||
if (action != null) {
|
||||
actions.add(action);
|
||||
}
|
||||
}
|
||||
|
||||
return new NewsItem(
|
||||
newsItem.get("id").getAsInt(),
|
||||
newsItem.get("active").getAsBoolean(),
|
||||
newsType,
|
||||
newsType.read(newsItem.getAsJsonObject("data")),
|
||||
message,
|
||||
actions,
|
||||
newsItem.get("url").getAsString()
|
||||
);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public NewsType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public ItemData getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ItemData> T getDataAs(Class<T> type) {
|
||||
return (T) data;
|
||||
}
|
||||
|
||||
public String getRawMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message + " See " + getUrl() + " for more information.";
|
||||
}
|
||||
|
||||
public Set<NewsItemAction> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.news;
|
||||
|
||||
public enum NewsItemAction {
|
||||
ON_SERVER_STARTED,
|
||||
ON_OPERATOR_JOIN,
|
||||
BROADCAST_TO_CONSOLE,
|
||||
BROADCAST_TO_OPERATORS;
|
||||
|
||||
private static final NewsItemAction[] VALUES = values();
|
||||
|
||||
public static NewsItemAction getByName(String actionName) {
|
||||
for (NewsItemAction type : VALUES) {
|
||||
if (type.name().equalsIgnoreCase(actionName)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.news;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
|
||||
// {} is used for things that have to be filled in by the server,
|
||||
// {@} is for things that have to be filled in by us
|
||||
public enum NewsItemMessage {
|
||||
UPDATE_AVAILABLE("There is an update available for {}. The newest version is: {}"),
|
||||
UPDATE_RECOMMENDED(UPDATE_AVAILABLE + ". Your version is quite old, updating is recommend."),
|
||||
UPDATE_HIGHLY_RECOMMENDED(UPDATE_AVAILABLE + ". We highly recommend updating because some important changes have been made."),
|
||||
UPDATE_ANCIENT_VERSION(UPDATE_AVAILABLE + ". You are running an ancient version, updating is recommended."),
|
||||
|
||||
DOWNTIME_GENERIC("The {} is temporarily going down for maintenance soon."),
|
||||
DOWNTIME_WITH_START("The {} is temporarily going down for maintenance on {}."),
|
||||
DOWNTIME_TIMEFRAME(DOWNTIME_WITH_START + " The maintenance is expected to last till {}.");
|
||||
|
||||
private static final NewsItemMessage[] VALUES = values();
|
||||
|
||||
private final String messageFormat;
|
||||
private final String[] messageSplitted;
|
||||
|
||||
NewsItemMessage(String messageFormat) {
|
||||
this.messageFormat = messageFormat;
|
||||
this.messageSplitted = messageFormat.split(" ");
|
||||
}
|
||||
|
||||
public static NewsItemMessage getById(int id) {
|
||||
return VALUES.length > id ? VALUES[id] : null;
|
||||
}
|
||||
|
||||
public String getMessageFormat() {
|
||||
return messageFormat;
|
||||
}
|
||||
|
||||
public String getFormattedMessage(JsonArray serverArguments) {
|
||||
int serverArgumentsIndex = 0;
|
||||
|
||||
StringBuilder message = new StringBuilder();
|
||||
for (String split : messageSplitted) {
|
||||
if (message.length() > 0) {
|
||||
message.append(' ');
|
||||
}
|
||||
|
||||
String result = split;
|
||||
|
||||
if (serverArgumentsIndex < serverArguments.size()) {
|
||||
String argument = serverArguments.get(serverArgumentsIndex).getAsString();
|
||||
result = result.replace("{}", argument);
|
||||
if (!result.equals(split)) {
|
||||
serverArgumentsIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
message.append(result);
|
||||
}
|
||||
return message.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getMessageFormat();
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.news;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.geysermc.floodgate.news.data.*;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public enum NewsType {
|
||||
BUILD_SPECIFIC(BuildSpecificData::read),
|
||||
CHECK_AFTER(CheckAfterData::read),
|
||||
ANNOUNCEMENT(AnnouncementData::read),
|
||||
CONFIG_SPECIFIC(ConfigSpecificData::read);
|
||||
|
||||
private static final NewsType[] VALUES = values();
|
||||
|
||||
private final Function<JsonObject, ? extends ItemData> readFunction;
|
||||
|
||||
NewsType(Function<JsonObject, ? extends ItemData> readFunction) {
|
||||
this.readFunction = readFunction;
|
||||
}
|
||||
|
||||
public static NewsType getByName(String newsType) {
|
||||
for (NewsType type : VALUES) {
|
||||
if (type.name().equalsIgnoreCase(newsType)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ItemData read(JsonObject data) {
|
||||
return readFunction.apply(data);
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.news.data;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class AnnouncementData implements ItemData {
|
||||
private final Set<String> including = new HashSet<>();
|
||||
private final Set<String> excluding = new HashSet<>();
|
||||
|
||||
private AnnouncementData() {}
|
||||
|
||||
public static AnnouncementData read(JsonObject data) {
|
||||
AnnouncementData announcementData = new AnnouncementData();
|
||||
|
||||
if (data.has("including")) {
|
||||
JsonArray including = data.getAsJsonArray("including");
|
||||
for (JsonElement element : including) {
|
||||
announcementData.including.add(element.getAsString());
|
||||
}
|
||||
}
|
||||
|
||||
if (data.has("excluding")) {
|
||||
JsonArray including = data.getAsJsonArray("excluding");
|
||||
for (JsonElement element : including) {
|
||||
announcementData.excluding.add(element.getAsString());
|
||||
}
|
||||
}
|
||||
return announcementData;
|
||||
}
|
||||
|
||||
public boolean isAffected(String project) {
|
||||
return !excluding.contains(project) && (including.isEmpty() || including.contains(project));
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.news.data;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public final class BuildSpecificData implements ItemData {
|
||||
private String branch;
|
||||
|
||||
private boolean allAffected;
|
||||
private int affectedGreaterThan;
|
||||
private int affectedLessThan;
|
||||
|
||||
private BuildSpecificData() {}
|
||||
|
||||
public static BuildSpecificData read(JsonObject data) {
|
||||
BuildSpecificData updateData = new BuildSpecificData();
|
||||
updateData.branch = data.get("branch").getAsString();
|
||||
|
||||
JsonObject affectedBuilds = data.getAsJsonObject("affected_builds");
|
||||
if (affectedBuilds.has("all")) {
|
||||
updateData.allAffected = affectedBuilds.get("all").getAsBoolean();
|
||||
}
|
||||
if (!updateData.allAffected) {
|
||||
updateData.affectedGreaterThan = affectedBuilds.get("gt").getAsInt();
|
||||
updateData.affectedLessThan = affectedBuilds.get("lt").getAsInt();
|
||||
}
|
||||
return updateData;
|
||||
}
|
||||
|
||||
public boolean isAffected(String branch, int buildId) {
|
||||
return this.branch.equals(branch) &&
|
||||
(allAffected || buildId > affectedGreaterThan && buildId < affectedLessThan);
|
||||
}
|
||||
|
||||
public String getBranch() {
|
||||
return branch;
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.news.data;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public final class CheckAfterData implements ItemData {
|
||||
private long checkAfter;
|
||||
|
||||
private CheckAfterData() {}
|
||||
|
||||
public static CheckAfterData read(JsonObject data) {
|
||||
CheckAfterData checkAfterData = new CheckAfterData();
|
||||
checkAfterData.checkAfter = data.get("check_after").getAsLong();
|
||||
return checkAfterData;
|
||||
}
|
||||
|
||||
public long getCheckAfter() {
|
||||
return checkAfter;
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.news.data;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class ConfigSpecificData implements ItemData {
|
||||
private final Map<String, Pattern> affectedKeys = new HashMap<>();
|
||||
|
||||
private ConfigSpecificData() {}
|
||||
|
||||
public static ConfigSpecificData read(JsonObject data) {
|
||||
ConfigSpecificData configSpecificData = new ConfigSpecificData();
|
||||
|
||||
JsonArray entries = data.getAsJsonArray("entries");
|
||||
for (JsonElement element : entries) {
|
||||
JsonObject entry = element.getAsJsonObject();
|
||||
String key = entry.get("key").getAsString();
|
||||
String pattern = entry.get("pattern").getAsString();
|
||||
configSpecificData.affectedKeys.put(key, Pattern.compile(pattern));
|
||||
}
|
||||
return configSpecificData;
|
||||
}
|
||||
|
||||
public boolean isAffected(Map<String, String> config) {
|
||||
for (Map.Entry<String, Pattern> entry : affectedKeys.entrySet()) {
|
||||
if (config.containsKey(entry.getKey())) {
|
||||
String value = config.get(entry.getKey());
|
||||
if (entry.getValue().matcher(value).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.news.data;
|
||||
|
||||
public interface ItemData {
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.pluginmessage;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public final class PluginMessageChannels {
|
||||
public static final String SKIN = "floodgate:skin";
|
||||
public static final String FORM = "floodgate:form";
|
||||
public static final String TRANSFER = "floodgate:transfer";
|
||||
public static final String PACKET = "floodgate:packet";
|
||||
|
||||
private static final byte[] FLOODGATE_REGISTER_DATA =
|
||||
String.join("\0", SKIN, FORM, TRANSFER, PACKET)
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
/**
|
||||
* Get the prebuilt register data as a byte array
|
||||
*
|
||||
* @return the register data of the Floodgate channels
|
||||
*/
|
||||
public static byte[] getFloodgateRegisterData() {
|
||||
return FLOODGATE_REGISTER_DATA;
|
||||
}
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.util;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* This class contains the raw data send by Geyser to Floodgate or from Floodgate to Floodgate. This
|
||||
* class is only used internally, and you should look at FloodgatePlayer instead (FloodgatePlayer is
|
||||
* present in the API module of the Floodgate repo)
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class BedrockData implements Cloneable {
|
||||
public static final int EXPECTED_LENGTH = 12;
|
||||
|
||||
private final String version;
|
||||
private final String username;
|
||||
private final String xuid;
|
||||
private final int deviceOs;
|
||||
private final String languageCode;
|
||||
private final int uiProfile;
|
||||
private final int inputMode;
|
||||
private final String ip;
|
||||
private final LinkedPlayer linkedPlayer;
|
||||
private final boolean fromProxy;
|
||||
|
||||
private final int subscribeId;
|
||||
private final String verifyCode;
|
||||
|
||||
private final int dataLength;
|
||||
|
||||
public static BedrockData of(
|
||||
String version, String username, String xuid, int deviceOs,
|
||||
String languageCode, int uiProfile, int inputMode, String ip,
|
||||
LinkedPlayer linkedPlayer, boolean fromProxy, int subscribeId,
|
||||
String verifyCode) {
|
||||
return new BedrockData(version, username, xuid, deviceOs, languageCode, inputMode,
|
||||
uiProfile, ip, linkedPlayer, fromProxy, subscribeId, verifyCode, EXPECTED_LENGTH);
|
||||
}
|
||||
|
||||
public static BedrockData of(
|
||||
String version, String username, String xuid, int deviceOs,
|
||||
String languageCode, int uiProfile, int inputMode, String ip,
|
||||
int subscribeId, String verifyCode) {
|
||||
return of(version, username, xuid, deviceOs, languageCode, uiProfile, inputMode, ip, null,
|
||||
false, subscribeId, verifyCode);
|
||||
}
|
||||
|
||||
public static BedrockData fromString(String data) {
|
||||
String[] split = data.split("\0");
|
||||
if (split.length != EXPECTED_LENGTH) {
|
||||
return emptyData(split.length);
|
||||
}
|
||||
|
||||
LinkedPlayer linkedPlayer = LinkedPlayer.fromString(split[8]);
|
||||
// The format is the same as the order of the fields in this class
|
||||
return new BedrockData(
|
||||
split[0], split[1], split[2], Integer.parseInt(split[3]), split[4],
|
||||
Integer.parseInt(split[5]), Integer.parseInt(split[6]), split[7], linkedPlayer,
|
||||
"1".equals(split[9]), Integer.parseInt(split[10]), split[11], split.length
|
||||
);
|
||||
}
|
||||
|
||||
private static BedrockData emptyData(int dataLength) {
|
||||
return new BedrockData(null, null, null, -1, null, -1, -1, null, null, false, -1, null,
|
||||
dataLength);
|
||||
}
|
||||
|
||||
public boolean hasPlayerLink() {
|
||||
return linkedPlayer != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// The format is the same as the order of the fields in this class
|
||||
return version + '\0' + username + '\0' + xuid + '\0' + deviceOs + '\0' +
|
||||
languageCode + '\0' + uiProfile + '\0' + inputMode + '\0' + ip + '\0' +
|
||||
(linkedPlayer != null ? linkedPlayer.toString() : "null") + '\0' +
|
||||
(fromProxy ? 1 : 0) + '\0' + subscribeId + '\0' + verifyCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BedrockData clone() throws CloneNotSupportedException {
|
||||
return (BedrockData) super.clone();
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.util;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public final class FloodgateInfoHolder {
|
||||
@Getter
|
||||
@Setter
|
||||
private static Object config;
|
||||
@Getter
|
||||
@Setter
|
||||
private static Properties gitProperties;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.util;
|
||||
|
||||
public class InvalidFormatException extends Exception {
|
||||
public InvalidFormatException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.util;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class LinkedPlayer implements Cloneable {
|
||||
/**
|
||||
* The Java username of the linked player
|
||||
*/
|
||||
private final String javaUsername;
|
||||
/**
|
||||
* The Java UUID of the linked player
|
||||
*/
|
||||
private final UUID javaUniqueId;
|
||||
/**
|
||||
* The UUID of the Bedrock player
|
||||
*/
|
||||
private final UUID bedrockId;
|
||||
/**
|
||||
* If the LinkedPlayer is sent from a different platform. For example the LinkedPlayer is from
|
||||
* Bungee but the data has been sent to the Bukkit server.
|
||||
*/
|
||||
private boolean fromDifferentPlatform = false;
|
||||
|
||||
public static LinkedPlayer of(String javaUsername, UUID javaUniqueId, UUID bedrockId) {
|
||||
return new LinkedPlayer(javaUsername, javaUniqueId, bedrockId);
|
||||
}
|
||||
|
||||
public static LinkedPlayer fromString(String data) {
|
||||
String[] split = data.split(";");
|
||||
if (split.length != 3) {
|
||||
return null;
|
||||
}
|
||||
|
||||
LinkedPlayer player = new LinkedPlayer(
|
||||
split[0], UUID.fromString(split[1]), UUID.fromString(split[2])
|
||||
);
|
||||
player.fromDifferentPlatform = true;
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return javaUsername + ';' + javaUniqueId.toString() + ';' + bedrockId.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedPlayer clone() throws CloneNotSupportedException {
|
||||
return (LinkedPlayer) super.clone();
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* 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.floodgate.util;
|
||||
|
||||
public enum WebsocketEventType {
|
||||
/**
|
||||
* Sent once we successfully connected to the server
|
||||
*/
|
||||
SUBSCRIBER_CREATED(0),
|
||||
/**
|
||||
* Sent every time a subscriber got added or disconnected
|
||||
*/
|
||||
SUBSCRIBER_COUNT(1),
|
||||
/**
|
||||
* Sent once the creator disconnected. After this packet the server will automatically close the
|
||||
* connection once the queue size (sent in {@link #ADDED_TO_QUEUE} and {@link #SKIN_UPLOADED}
|
||||
* reaches 0.
|
||||
*/
|
||||
CREATOR_DISCONNECTED(4),
|
||||
|
||||
/**
|
||||
* Sent every time a skin got added to the upload queue
|
||||
*/
|
||||
ADDED_TO_QUEUE(2),
|
||||
/**
|
||||
* Sent every time a skin got successfully uploaded
|
||||
*/
|
||||
SKIN_UPLOADED(3),
|
||||
|
||||
/**
|
||||
* Sent every time a news item was added
|
||||
*/
|
||||
NEWS_ADDED(6),
|
||||
|
||||
/**
|
||||
* Sent when the server wants you to know something. Currently used for violations that aren't
|
||||
* bad enough to close the connection
|
||||
*/
|
||||
LOG_MESSAGE(5);
|
||||
|
||||
private static final WebsocketEventType[] VALUES;
|
||||
|
||||
static {
|
||||
WebsocketEventType[] values = values();
|
||||
VALUES = new WebsocketEventType[values.length];
|
||||
for (WebsocketEventType value : values) {
|
||||
VALUES[value.id] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID is based of the time it got added. However, to keep the enum organized as time goes on,
|
||||
* it looks nicer to sort the events based of categories.
|
||||
*/
|
||||
private final int id;
|
||||
|
||||
WebsocketEventType(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static WebsocketEventType fromId(int id) {
|
||||
return VALUES.length > id ? VALUES[id] : null;
|
||||
}
|
||||
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ plugins {
|
|||
|
||||
dependencies {
|
||||
api(libs.floodgate.core)
|
||||
api(libs.floodgate.isolation)
|
||||
annotationProcessor(libs.floodgate.core)
|
||||
api(projects.api)
|
||||
|
||||
|
|
|
@ -29,8 +29,6 @@ import org.geysermc.floodgate.core.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;
|
||||
|
@ -137,13 +135,6 @@ 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.
|
||||
*/
|
||||
|
|
|
@ -64,12 +64,13 @@ 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.floodgate.FloodgateProvider;
|
||||
import org.geysermc.geyser.floodgate.NoFloodgateProvider;
|
||||
import org.geysermc.geyser.floodgate.ProxyFloodgateProvider;
|
||||
import org.geysermc.geyser.level.WorldManager;
|
||||
import org.geysermc.geyser.network.netty.GeyserServer;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoaders;
|
||||
import org.geysermc.geyser.scoreboard.ScoreboardUpdater;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
|
||||
|
@ -131,7 +132,7 @@ public class GeyserImpl implements GeyserApi {
|
|||
@Setter
|
||||
private static boolean shouldStartListener = true;
|
||||
|
||||
private HybridProvider hybridProvider;
|
||||
private final FloodgateProvider floodgateProvider;
|
||||
private BedrockSkinUploader skinUploader;
|
||||
private NewsHandler newsHandler;
|
||||
|
||||
|
@ -156,16 +157,18 @@ public class GeyserImpl implements GeyserApi {
|
|||
|
||||
private static GeyserImpl instance;
|
||||
|
||||
private final FloodgatePlatform floodgatePlatform;
|
||||
|
||||
private GeyserImpl(PlatformType platformType, GeyserBootstrap bootstrap, FloodgatePlatform floodgatePlatform) {
|
||||
instance = this;
|
||||
this.floodgatePlatform = floodgatePlatform;
|
||||
|
||||
if (floodgatePlatform != null) {
|
||||
floodgatePlatform.load();
|
||||
floodgatePlatform.enable();
|
||||
// this.floodgatePlatform = floodgatePlatform.isProxy() ? new ProxyFloodgateProvider(floodgatePlatform) : new IntegratedFloodgateProvider(floodgatePlatform);
|
||||
// this.floodgateProvider = new IntegratedFloodgateProvider(floodgatePlatform);
|
||||
this.floodgateProvider = new ProxyFloodgateProvider(floodgatePlatform);
|
||||
} else {
|
||||
this.floodgateProvider = new NoFloodgateProvider();
|
||||
Geyser.set(this);
|
||||
}
|
||||
|
||||
|
@ -314,7 +317,7 @@ public class GeyserImpl implements GeyserApi {
|
|||
}
|
||||
}
|
||||
|
||||
boolean floodgatePresent = bootstrap.testFloodgatePluginPresent();
|
||||
boolean floodgatePresent = bootstrap.testFloodgatePluginPresent() || floodgateProvider != null; //todo
|
||||
if (config.getRemote().authType() == AuthType.FLOODGATE && !floodgatePresent) {
|
||||
logger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " "
|
||||
+ GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
|
||||
|
@ -383,7 +386,6 @@ public class GeyserImpl implements GeyserApi {
|
|||
}
|
||||
|
||||
if (config.getRemote().authType() == AuthType.FLOODGATE) {
|
||||
hybridProvider = bootstrap.createHybridProvider(this);
|
||||
try {
|
||||
// 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.
|
||||
|
|
|
@ -33,7 +33,6 @@ 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;
|
||||
|
||||
|
|
|
@ -252,6 +252,6 @@ public class SessionPlayerEntity extends PlayerEntity {
|
|||
|
||||
@Override
|
||||
public UUID getTabListUuid() {
|
||||
return session.getAuthData().uuid();
|
||||
return session.identity();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.geysermc.event.subscribe.Subscribe;
|
|||
import org.geysermc.geyser.api.event.EventBus;
|
||||
import org.geysermc.geyser.api.event.EventRegistrar;
|
||||
import org.geysermc.geyser.api.event.EventSubscriber;
|
||||
import org.geysermc.geyser.api.extension.Extension;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
|
@ -67,6 +66,6 @@ public final class GeyserEventBus extends OwnedEventBusImpl<EventRegistrar, Even
|
|||
@Override
|
||||
@NonNull
|
||||
public <T extends Event> Set<? extends EventSubscriber<EventRegistrar, T>> subscribers(@NonNull Class<T> eventClass) {
|
||||
return castGenericSet(super.subscribers(eventClass));
|
||||
return castGenericNullableSet(super.subscribers(eventClass));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2023 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
|
||||
|
@ -23,18 +23,18 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.crypto;
|
||||
package org.geysermc.geyser.floodgate;
|
||||
|
||||
import java.util.Base64;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
public final class Base64Topping implements Topping {
|
||||
@Override
|
||||
public byte[] encode(byte[] data) {
|
||||
return Base64.getEncoder().encode(data);
|
||||
}
|
||||
public interface FloodgateProvider {
|
||||
void onSkinUpload(GeyserSession session, String value, String signature);
|
||||
|
||||
@Override
|
||||
public byte[] decode(byte[] data) {
|
||||
return Base64.getDecoder().decode(data);
|
||||
}
|
||||
/**
|
||||
* Called before Geyser sends the ClientIntention to the Java server.
|
||||
*
|
||||
* @return data to add to the hostname
|
||||
*/
|
||||
@Nullable String onClientIntention(GeyserSession session) throws Exception;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2023 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
|
||||
|
@ -23,23 +23,25 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.hybrid;
|
||||
package org.geysermc.geyser.floodgate;
|
||||
|
||||
import io.netty.util.AttributeKey;
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateCipher;
|
||||
import org.geysermc.floodgate.core.FloodgatePlatform;
|
||||
import org.geysermc.floodgate.core.connection.ConnectionManager;
|
||||
import org.geysermc.floodgate.core.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.core.skin.SkinDataImpl;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
public class IntegratedHybridProvider implements HybridProvider {
|
||||
public class IntegratedFloodgateProvider implements FloodgateProvider {
|
||||
// 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;
|
||||
private final ConnectionManager connectionManager;
|
||||
|
||||
public IntegratedHybridProvider(GeyserImpl geyser) {
|
||||
skinApplier = geyser.getBootstrap().createSkinApplier();
|
||||
public IntegratedFloodgateProvider(FloodgatePlatform platform) {
|
||||
skinApplier = platform.getBean(SkinApplier.class);
|
||||
connectionManager = platform.getBean(ConnectionManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,7 +50,8 @@ public class IntegratedHybridProvider implements HybridProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public FloodgateCipher getCipher() {
|
||||
throw new UnsupportedOperationException();
|
||||
public String onClientIntention(GeyserSession session) {
|
||||
connectionManager.addConnection(session);
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2023 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
|
||||
|
@ -23,13 +23,18 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.hybrid;
|
||||
package org.geysermc.geyser.floodgate;
|
||||
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateCipher;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
public interface HybridProvider {
|
||||
void onSkinUpload(GeyserSession session, String value, String signature);
|
||||
public final class NoFloodgateProvider implements FloodgateProvider {
|
||||
@Override
|
||||
public void onSkinUpload(GeyserSession session, String value, String signature) {
|
||||
|
||||
FloodgateCipher getCipher();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onClientIntention(GeyserSession session) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-2023 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
|
||||
|
@ -23,19 +23,19 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.hybrid;
|
||||
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateCipher;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
package org.geysermc.geyser.floodgate;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.geysermc.floodgate.core.FloodgatePlatform;
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateDataCodec;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
public final class FloodgateHybridProvider implements HybridProvider {
|
||||
private final FloodgateCipher cipher;
|
||||
//todo Floodgate should be responsible for forwarding its messages
|
||||
public final class ProxyFloodgateProvider implements FloodgateProvider {
|
||||
private final FloodgateDataCodec dataCodec;
|
||||
|
||||
public FloodgateHybridProvider(GeyserImpl geyser) {
|
||||
cipher = geyser.getFloodgatePlatform().getBean(FloodgateCipher.class);
|
||||
public ProxyFloodgateProvider(FloodgatePlatform platform) {
|
||||
dataCodec = platform.getBean(FloodgateDataCodec.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -47,7 +47,7 @@ public final class FloodgateHybridProvider implements HybridProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public FloodgateCipher getCipher() {
|
||||
return cipher;
|
||||
public String onClientIntention(GeyserSession session) throws Exception {
|
||||
return dataCodec.encodeToString(session);
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* 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.core.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().getBean(FloodgateCipher.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloodgateCipher getCipher() {
|
||||
return cipher;
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ 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.floodgate.IntegratedFloodgateProvider;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
/**
|
||||
|
@ -44,12 +44,12 @@ public class LocalServerChannelWrapper extends LocalServerChannel {
|
|||
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);
|
||||
if (GeyserImpl.getInstance().getFloodgateProvider() instanceof IntegratedFloodgateProvider) {
|
||||
Attribute<GeyserSession> attribute = peer.attr(IntegratedFloodgateProvider.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);
|
||||
channel.attr(IntegratedFloodgateProvider.SESSION_KEY).set(session);
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ 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.floodgate.IntegratedFloodgateProvider;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -98,8 +98,8 @@ public final class LocalSession extends TcpSession {
|
|||
|
||||
addHAProxySupport(pipeline);
|
||||
|
||||
if (GeyserImpl.getInstance().getHybridProvider() instanceof IntegratedHybridProvider) {
|
||||
Attribute<GeyserSession> attribute = channel.attr(IntegratedHybridProvider.SESSION_KEY);
|
||||
if (GeyserImpl.getInstance().getFloodgateProvider() instanceof IntegratedFloodgateProvider) {
|
||||
Attribute<GeyserSession> attribute = channel.attr(IntegratedFloodgateProvider.SESSION_KEY);
|
||||
attribute.set(session);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ 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;
|
||||
|
|
|
@ -74,6 +74,25 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
|||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
@ -83,16 +102,55 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.checkerframework.common.value.qual.IntRange;
|
||||
import org.cloudburstmc.math.vector.*;
|
||||
import org.cloudburstmc.math.vector.Vector2f;
|
||||
import org.cloudburstmc.math.vector.Vector2i;
|
||||
import org.cloudburstmc.math.vector.Vector3d;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.protocol.bedrock.BedrockDisconnectReasons;
|
||||
import org.cloudburstmc.protocol.bedrock.BedrockServerSession;
|
||||
import org.cloudburstmc.protocol.bedrock.data.*;
|
||||
import org.cloudburstmc.protocol.bedrock.data.Ability;
|
||||
import org.cloudburstmc.protocol.bedrock.data.AbilityLayer;
|
||||
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
|
||||
import org.cloudburstmc.protocol.bedrock.data.AuthoritativeMovementMode;
|
||||
import org.cloudburstmc.protocol.bedrock.data.CameraShakeAction;
|
||||
import org.cloudburstmc.protocol.bedrock.data.CameraShakeType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.ChatRestrictionLevel;
|
||||
import org.cloudburstmc.protocol.bedrock.data.ExperimentData;
|
||||
import org.cloudburstmc.protocol.bedrock.data.GamePublishSetting;
|
||||
import org.cloudburstmc.protocol.bedrock.data.GameRuleData;
|
||||
import org.cloudburstmc.protocol.bedrock.data.GameType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.PlayerPermission;
|
||||
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
|
||||
import org.cloudburstmc.protocol.bedrock.data.SpawnBiomeType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumData;
|
||||
import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
|
||||
import org.cloudburstmc.protocol.bedrock.data.command.SoftEnumUpdateType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.*;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.AvailableEntityIdentifiersPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BiomeDefinitionListPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.CameraShakePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.ChunkRadiusUpdatedPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.ClientboundMapItemDataPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.CreativeContentPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.EmoteListPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.EmotePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.GameRulesChangedPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.ItemComponentPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.PlayStatusPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.PlayerFogPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetTimePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.StartGamePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.TextPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.TransferPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateAbilitiesPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateAdventureSettingsPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateSoftEnumPacket;
|
||||
import org.cloudburstmc.protocol.common.DefinitionRegistry;
|
||||
import org.cloudburstmc.protocol.common.util.OptionalBoolean;
|
||||
import org.geysermc.api.util.BedrockPlatform;
|
||||
|
@ -100,8 +158,8 @@ 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.core.crypto.FloodgateCipher;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.core.connection.FloodgateConnection;
|
||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||
import org.geysermc.geyser.Constants;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.bedrock.camera.CameraShake;
|
||||
|
@ -123,8 +181,7 @@ 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.floodgate.FloodgateProvider;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
||||
|
@ -139,8 +196,20 @@ import org.geysermc.geyser.registry.type.BlockMappings;
|
|||
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.BedrockSkinUploader;
|
||||
import org.geysermc.geyser.session.cache.AdvancementsCache;
|
||||
import org.geysermc.geyser.session.cache.BookEditCache;
|
||||
import org.geysermc.geyser.session.cache.ChunkCache;
|
||||
import org.geysermc.geyser.session.cache.EntityCache;
|
||||
import org.geysermc.geyser.session.cache.EntityEffectCache;
|
||||
import org.geysermc.geyser.session.cache.FormCache;
|
||||
import org.geysermc.geyser.session.cache.LodestoneCache;
|
||||
import org.geysermc.geyser.session.cache.PistonCache;
|
||||
import org.geysermc.geyser.session.cache.PreferencesCache;
|
||||
import org.geysermc.geyser.session.cache.SkullCache;
|
||||
import org.geysermc.geyser.session.cache.TagCache;
|
||||
import org.geysermc.geyser.session.cache.TeleportCache;
|
||||
import org.geysermc.geyser.session.cache.WorldBorder;
|
||||
import org.geysermc.geyser.session.cache.WorldCache;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.text.MinecraftLocale;
|
||||
import org.geysermc.geyser.text.TextDecoration;
|
||||
|
@ -152,19 +221,8 @@ import org.geysermc.geyser.util.EntityUtils;
|
|||
import org.geysermc.geyser.util.LoginEncryptionUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Getter
|
||||
public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
public class GeyserSession extends FloodgateConnection implements GeyserConnection, GeyserCommandSource {
|
||||
|
||||
private final GeyserImpl geyser;
|
||||
private final UpstreamSession upstream;
|
||||
|
@ -343,7 +401,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
|
||||
/**
|
||||
* Tracks the original speed attribute.
|
||||
*
|
||||
* <p>
|
||||
* We need to do this in order to emulate speeds when sneaking under 1.5-blocks-tall areas if the player isn't sneaking,
|
||||
* and when crawling.
|
||||
*/
|
||||
|
@ -961,43 +1019,21 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
public void packetSending(PacketSendingEvent event) {
|
||||
//todo move this somewhere else
|
||||
if (event.getPacket() instanceof ClientIntentionPacket) {
|
||||
String addressSuffix;
|
||||
HybridProvider provider;
|
||||
if (floodgate && (provider = geyser.getHybridProvider()) instanceof FloodgateHybridProvider) {
|
||||
byte[] encryptedData;
|
||||
String addedData;
|
||||
|
||||
FloodgateProvider provider = geyser.getFloodgateProvider();
|
||||
try {
|
||||
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
|
||||
int ipv6ScopeIndex = bedrockAddress.indexOf('%');
|
||||
if (ipv6ScopeIndex != -1) {
|
||||
bedrockAddress = bedrockAddress.substring(0, ipv6ScopeIndex);
|
||||
}
|
||||
|
||||
encryptedData = cipher.encryptFromString(BedrockData.of(
|
||||
clientData.getGameVersion(),
|
||||
authData.name(),
|
||||
authData.xuid(),
|
||||
clientData.getDeviceOs().ordinal(),
|
||||
clientData.getLanguageCode(),
|
||||
clientData.getUiProfile().ordinal(),
|
||||
clientData.getCurrentInputMode().ordinal(),
|
||||
bedrockAddress,
|
||||
skinUploader.getId(),
|
||||
skinUploader.getVerifyCode()
|
||||
).toString());
|
||||
} catch (Exception e) {
|
||||
geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.encrypt_fail"), e);
|
||||
addedData = provider.onClientIntention(GeyserSession.this);
|
||||
} catch (Exception exception) {
|
||||
geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.encrypt_fail"), exception);
|
||||
disconnect(GeyserLocale.getPlayerLocaleString("geyser.auth.floodgate.encryption_fail", getClientData().getLanguageCode()));
|
||||
return;
|
||||
}
|
||||
|
||||
addressSuffix = '\0' + new String(encryptedData, StandardCharsets.UTF_8);
|
||||
if (addedData != null) {
|
||||
addedData = '\0' + addedData;
|
||||
} else {
|
||||
addressSuffix = "";
|
||||
addedData = "";
|
||||
}
|
||||
|
||||
ClientIntentionPacket intentionPacket = event.getPacket();
|
||||
|
@ -1009,7 +1045,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
address = intentionPacket.getHostname();
|
||||
}
|
||||
|
||||
event.setPacket(intentionPacket.withHostname(address + addressSuffix));
|
||||
event.setPacket(intentionPacket.withHostname(address + addedData));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1480,11 +1516,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
upstream.sendPacket(chunkRadiusUpdatedPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress socketAddress() {
|
||||
return this.upstream.getAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(@NonNull Form form) {
|
||||
formCache.showForm(form);
|
||||
|
@ -1497,22 +1528,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Cumulus version 1.1, and will be removed when Cumulus 2.0 releases. Please use the new forms instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void sendForm(org.geysermc.cumulus.Form<?> form) {
|
||||
sendForm(form.newForm());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Cumulus version 1.1, and will be removed when Cumulus 2.0 releases. Please use the new forms instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void sendForm(org.geysermc.cumulus.util.FormBuilder<?, ?> formBuilder) {
|
||||
sendForm(formBuilder.build());
|
||||
}
|
||||
|
||||
private void startGame() {
|
||||
this.upstream.getCodecHelper().setItemDefinitions(this.itemMappings);
|
||||
this.upstream.getCodecHelper().setBlockDefinitions((DefinitionRegistry) this.blockMappings); //FIXME
|
||||
|
@ -1947,8 +1962,18 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isLinked() {
|
||||
return false; //todo
|
||||
public @NonNull UUID identity() {
|
||||
return authData.uuid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull InetAddress ip() {
|
||||
return upstream.getAddress().getAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @MonotonicNonNull LinkedPlayer linkedPlayer() {
|
||||
return null; //todo
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions") // Need to enforce the parameter annotations
|
||||
|
|
|
@ -140,7 +140,7 @@ public class AdvancementsCache {
|
|||
session.sendDownstreamPacket(new ServerboundSeenAdvancementsPacket());
|
||||
|
||||
}).validResultHandler((response) -> {
|
||||
if (response.getClickedButtonId() < visibleAdvancements.size()) {
|
||||
if (response.clickedButtonId() < visibleAdvancements.size()) {
|
||||
GeyserAdvancement advancement = visibleAdvancements.get(response.clickedButtonId());
|
||||
buildAndShowInfoForm(advancement);
|
||||
} else {
|
||||
|
|
|
@ -118,7 +118,7 @@ public final class BedrockSkinUploader {
|
|||
String value = data.get("value").asText();
|
||||
String signature = data.get("signature").asText();
|
||||
|
||||
geyser.getHybridProvider().onSkinUpload(session, value, signature);
|
||||
geyser.getFloodgateProvider().onSkinUpload(session, value, signature);
|
||||
}
|
||||
break;
|
||||
case LOG_MESSAGE:
|
||||
|
|
|
@ -4,7 +4,7 @@ floodgate = "development-2.2.2-SNAPSHOT"
|
|||
cumulus = "1.1.2"
|
||||
erosion = "1.0-20230406.174837-8"
|
||||
events = "1.1-SNAPSHOT"
|
||||
jackson = { strictly = "2.14.0" } # Don't let other dependencies override
|
||||
jackson = "2.14.2"
|
||||
fastutil = "8.5.2"
|
||||
netty = "4.1.80.Final"
|
||||
guava = "29.0-jre"
|
||||
|
@ -27,7 +27,7 @@ folia = "1.19.4-R0.1-SNAPSHOT"
|
|||
viaversion = "4.0.0"
|
||||
adapters = "1.9-SNAPSHOT"
|
||||
commodore = "2.2"
|
||||
bungeecord = "a7c6ede"
|
||||
bungeecord = "master-SNAPSHOT"
|
||||
velocity = "3.1.1"
|
||||
fabric-minecraft = "1.20"
|
||||
fabric-loader = "0.14.21"
|
||||
|
@ -39,6 +39,7 @@ cumulus = { group = "org.geysermc.cumulus", name = "cumulus", version.ref = "cum
|
|||
events = { group = "org.geysermc.event", name = "events", version.ref = "events" }
|
||||
|
||||
floodgate-core = { module = "org.geysermc.floodgate:core", version.ref = "floodgate" }
|
||||
floodgate-isolation = { module = "org.geysermc.floodgate:isolation", version.ref = "floodgate" }
|
||||
floodgate-bungee = { module = "org.geysermc.floodgate:bungee-base", version.ref = "floodgate" }
|
||||
floodgate-spigot = { module = "org.geysermc.floodgate:spigot-base", version.ref = "floodgate" }
|
||||
floodgate-velocity = { module = "org.geysermc.floodgate:velocity-base", version.ref = "floodgate" }
|
||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -64,7 +64,6 @@ include(":fabric")
|
|||
include(":spigot")
|
||||
include(":standalone")
|
||||
include(":velocity")
|
||||
include(":common")
|
||||
include(":core")
|
||||
|
||||
// Specify project dirs
|
||||
|
|
Loading…
Reference in a new issue