mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Merge remote-tracking branch 'origin/feature/floodgate-data-version' into feature/1.18
This commit is contained in:
commit
7df013daf9
15 changed files with 46 additions and 296 deletions
|
@ -70,8 +70,8 @@ public final class AesCipher implements FloodgateCipher {
|
|||
cipherText = topping.encode(cipherText);
|
||||
}
|
||||
|
||||
return ByteBuffer.allocate(iv.length + cipherText.length + HEADER_LENGTH + 1)
|
||||
.put(IDENTIFIER) // header
|
||||
return ByteBuffer.allocate(HEADER.length + iv.length + cipherText.length + 1)
|
||||
.put(HEADER)
|
||||
.put(iv)
|
||||
.put((byte) 0x21)
|
||||
.put(cipherText)
|
||||
|
@ -83,15 +83,15 @@ public final class AesCipher implements FloodgateCipher {
|
|||
|
||||
Cipher cipher = Cipher.getInstance(CIPHER_NAME);
|
||||
|
||||
int bufferLength = cipherTextWithIv.length - HEADER_LENGTH;
|
||||
ByteBuffer buffer = ByteBuffer.wrap(cipherTextWithIv, HEADER_LENGTH, bufferLength);
|
||||
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 optional RawSkin
|
||||
// we need the first index, the second is for the actual data
|
||||
boolean found = false;
|
||||
while (buffer.hasRemaining() && !found) {
|
||||
if (buffer.get() == 0x21) {
|
||||
|
|
|
@ -39,7 +39,7 @@ public final class AesKeyProducer implements KeyProducer {
|
|||
public SecretKey produce() {
|
||||
try {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||
keyGenerator.init(KEY_SIZE, getSecureRandom());
|
||||
keyGenerator.init(KEY_SIZE, secureRandom());
|
||||
return keyGenerator.generateKey();
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException(exception);
|
||||
|
@ -55,7 +55,7 @@ public final class AesKeyProducer implements KeyProducer {
|
|||
}
|
||||
}
|
||||
|
||||
private SecureRandom getSecureRandom() throws NoSuchAlgorithmException {
|
||||
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");
|
||||
|
|
|
@ -26,33 +26,32 @@
|
|||
|
||||
package org.geysermc.floodgate.crypto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.geysermc.floodgate.util.InvalidFormatException;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.Key;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
/**
|
||||
* Responsible for both encrypting and decrypting data
|
||||
*/
|
||||
public interface FloodgateCipher {
|
||||
// use invalid username characters at the beginning and the end of the identifier,
|
||||
// to make sure that it doesn't get messed up with usernames
|
||||
byte[] IDENTIFIER = "^Floodgate^".getBytes(StandardCharsets.UTF_8);
|
||||
int HEADER_LENGTH = IDENTIFIER.length;
|
||||
int VERSION = 0;
|
||||
byte[] IDENTIFIER = "^Floodgate^".getBytes(UTF_8);
|
||||
byte[] HEADER = (new String(IDENTIFIER, UTF_8) + (char) (VERSION + 0x3E)).getBytes(UTF_8);
|
||||
|
||||
static boolean hasHeader(String data) {
|
||||
if (data.length() < IDENTIFIER.length) {
|
||||
return false;
|
||||
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 false;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
return data.charAt(IDENTIFIER.length) - 0x3E;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,7 +78,7 @@ public interface FloodgateCipher {
|
|||
* @throws Exception when the encryption failed
|
||||
*/
|
||||
default byte[] encryptFromString(String data) throws Exception {
|
||||
return encrypt(data.getBytes(StandardCharsets.UTF_8));
|
||||
return encrypt(data.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,7 +103,7 @@ public interface FloodgateCipher {
|
|||
if (decrypted == null) {
|
||||
return null;
|
||||
}
|
||||
return new String(decrypted, StandardCharsets.UTF_8);
|
||||
return new String(decrypted, UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,7 +115,7 @@ public interface FloodgateCipher {
|
|||
* @throws Exception when the decrypting failed
|
||||
*/
|
||||
default byte[] decryptFromString(String data) throws Exception {
|
||||
return decrypt(data.getBytes(StandardCharsets.UTF_8));
|
||||
return decrypt(data.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,37 +126,21 @@ public interface FloodgateCipher {
|
|||
* @throws InvalidFormatException when the header is invalid
|
||||
*/
|
||||
default void checkHeader(byte[] data) throws InvalidFormatException {
|
||||
final int identifierLength = IDENTIFIER.length;
|
||||
|
||||
if (data.length <= HEADER_LENGTH) {
|
||||
throw new InvalidFormatException("Data length is smaller then header." +
|
||||
"Needed " + HEADER_LENGTH + ", got " + data.length,
|
||||
true
|
||||
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 < identifierLength; i++) {
|
||||
for (int i = 0; i < IDENTIFIER.length; i++) {
|
||||
if (IDENTIFIER[i] != data[i]) {
|
||||
StringBuilder receivedIdentifier = new StringBuilder();
|
||||
for (byte b : IDENTIFIER) {
|
||||
receivedIdentifier.append(b);
|
||||
}
|
||||
|
||||
String identifier = new String(IDENTIFIER, UTF_8);
|
||||
String received = new String(data, 0, IDENTIFIER.length, UTF_8);
|
||||
throw new InvalidFormatException(
|
||||
String.format("Expected identifier %s, got %s",
|
||||
new String(IDENTIFIER, StandardCharsets.UTF_8),
|
||||
receivedIdentifier.toString()
|
||||
),
|
||||
true
|
||||
"Expected identifier " + identifier + ", got " + received
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
class HeaderResult {
|
||||
private int version;
|
||||
private int startIndex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.time;
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/*
|
||||
* Thanks:
|
||||
* https://datatracker.ietf.org/doc/html/rfc1769
|
||||
* https://github.com/jonsagara/SimpleNtpClient
|
||||
* https://stackoverflow.com/a/29138806
|
||||
*/
|
||||
public final class SntpClientUtils {
|
||||
private static final int NTP_PORT = 123;
|
||||
|
||||
private static final int NTP_PACKET_SIZE = 48;
|
||||
private static final int NTP_MODE = 3; // client
|
||||
private static final int NTP_VERSION = 3;
|
||||
private static final int RECEIVE_TIME_POSITION = 32;
|
||||
|
||||
private static final long NTP_TIME_OFFSET = ((365L * 70L) + 17L) * 24L * 60L * 60L;
|
||||
|
||||
public static long requestTimeOffset(String host, int timeout) {
|
||||
try (DatagramSocket socket = new DatagramSocket()) {
|
||||
socket.setSoTimeout(timeout);
|
||||
|
||||
InetAddress address = InetAddress.getByName(host);
|
||||
|
||||
ByteBuffer buff = ByteBuffer.allocate(NTP_PACKET_SIZE);
|
||||
|
||||
DatagramPacket request = new DatagramPacket(
|
||||
buff.array(), NTP_PACKET_SIZE, address, NTP_PORT
|
||||
);
|
||||
|
||||
// mode is in the least signification 3 bits
|
||||
// version is in bits 3-5
|
||||
buff.put((byte) (NTP_MODE | (NTP_VERSION << 3)));
|
||||
|
||||
long originateTime = System.currentTimeMillis();
|
||||
socket.send(request);
|
||||
|
||||
DatagramPacket response = new DatagramPacket(buff.array(), NTP_PACKET_SIZE);
|
||||
socket.receive(response);
|
||||
|
||||
long responseTime = System.currentTimeMillis();
|
||||
|
||||
// everything before isn't important for us
|
||||
buff.position(RECEIVE_TIME_POSITION);
|
||||
|
||||
long receiveTime = readTimestamp(buff);
|
||||
long transmitTime = readTimestamp(buff);
|
||||
|
||||
return ((receiveTime - originateTime) + (transmitTime - responseTime)) / 2;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return Long.MIN_VALUE;
|
||||
}
|
||||
|
||||
private static long readTimestamp(ByteBuffer buffer) {
|
||||
//todo look into the ntp 2036 problem
|
||||
long seconds = buffer.getInt() & 0xffffffffL;
|
||||
long fraction = buffer.getInt() & 0xffffffffL;
|
||||
return ((seconds - NTP_TIME_OFFSET) * 1000) + ((fraction * 1000) / 0x100000000L);
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.time;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class TimeSyncer {
|
||||
private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
|
||||
private long timeOffset = Long.MIN_VALUE; // value when it failed to get the offset
|
||||
|
||||
public TimeSyncer(String timeServer) {
|
||||
executorService.scheduleWithFixedDelay(() -> {
|
||||
// 5 tries to get the time offset, since UDP doesn't guaranty a response
|
||||
for (int i = 0; i < 5; i++) {
|
||||
long offset = SntpClientUtils.requestTimeOffset(timeServer, 3000);
|
||||
if (offset != Long.MIN_VALUE) {
|
||||
timeOffset = offset;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}, 0, 30, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
public long getTimeOffset() {
|
||||
return timeOffset;
|
||||
}
|
||||
|
||||
public long getRealMillis() {
|
||||
if (hasUsefulOffset()) {
|
||||
return System.currentTimeMillis() + getTimeOffset();
|
||||
}
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean hasUsefulOffset() {
|
||||
return timeOffset != Long.MIN_VALUE;
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.util;
|
||||
|
||||
public final class Base64Utils {
|
||||
public static int getEncodedLength(int length) {
|
||||
if (length <= 0) {
|
||||
return -1;
|
||||
}
|
||||
return 4 * ((length + 2) / 3);
|
||||
}
|
||||
}
|
|
@ -28,7 +28,6 @@ package org.geysermc.floodgate.util;
|
|||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.geysermc.floodgate.time.TimeSyncer;
|
||||
|
||||
/**
|
||||
* This class contains the raw data send by Geyser to Floodgate or from Floodgate to Floodgate. This
|
||||
|
@ -38,7 +37,7 @@ import org.geysermc.floodgate.time.TimeSyncer;
|
|||
@Getter
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class BedrockData implements Cloneable {
|
||||
public static final int EXPECTED_LENGTH = 13;
|
||||
public static final int EXPECTED_LENGTH = 12;
|
||||
|
||||
private final String version;
|
||||
private final String username;
|
||||
|
@ -54,25 +53,23 @@ public final class BedrockData implements Cloneable {
|
|||
private final int subscribeId;
|
||||
private final String verifyCode;
|
||||
|
||||
private final long timestamp;
|
||||
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, TimeSyncer timeSyncer) {
|
||||
String verifyCode) {
|
||||
return new BedrockData(version, username, xuid, deviceOs, languageCode, inputMode,
|
||||
uiProfile, ip, linkedPlayer, fromProxy, subscribeId, verifyCode,
|
||||
timeSyncer.getRealMillis(), EXPECTED_LENGTH);
|
||||
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, TimeSyncer timeSyncer) {
|
||||
int subscribeId, String verifyCode) {
|
||||
return of(version, username, xuid, deviceOs, languageCode, uiProfile, inputMode, ip, null,
|
||||
false, subscribeId, verifyCode, timeSyncer);
|
||||
false, subscribeId, verifyCode);
|
||||
}
|
||||
|
||||
public static BedrockData fromString(String data) {
|
||||
|
@ -86,12 +83,12 @@ public final class BedrockData implements Cloneable {
|
|||
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], Long.parseLong(split[12]), split.length
|
||||
"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, -1,
|
||||
return new BedrockData(null, null, null, -1, null, -1, -1, null, null, false, -1, null,
|
||||
dataLength);
|
||||
}
|
||||
|
||||
|
@ -105,7 +102,7 @@ public final class BedrockData implements Cloneable {
|
|||
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 + '\0' + timestamp;
|
||||
(fromProxy ? 1 : 0) + '\0' + subscribeId + '\0' + verifyCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -59,7 +59,7 @@ public enum DeviceOs {
|
|||
* @param id the DeviceOs identifier
|
||||
* @return The DeviceOs or {@link #UNKNOWN} if the DeviceOs wasn't found
|
||||
*/
|
||||
public static DeviceOs getById(int id) {
|
||||
public static DeviceOs fromId(int id) {
|
||||
return id < VALUES.length ? VALUES[id] : VALUES[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public enum InputMode {
|
|||
* @param id the InputMode identifier
|
||||
* @return The InputMode or {@link #UNKNOWN} if the DeviceOs wasn't found
|
||||
*/
|
||||
public static InputMode getById(int id) {
|
||||
public static InputMode fromId(int id) {
|
||||
return VALUES.length > id ? VALUES[id] : VALUES[0];
|
||||
}
|
||||
}
|
|
@ -26,26 +26,8 @@
|
|||
|
||||
package org.geysermc.floodgate.util;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class InvalidFormatException extends Exception {
|
||||
private boolean header = false;
|
||||
|
||||
public InvalidFormatException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public InvalidFormatException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InvalidFormatException(String message, boolean header) {
|
||||
super(message);
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public InvalidFormatException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ public enum UiProfile {
|
|||
* @param id the UiProfile identifier
|
||||
* @return The UiProfile or {@link #CLASSIC} if the UiProfile wasn't found
|
||||
*/
|
||||
public static UiProfile getById(int id) {
|
||||
public static UiProfile fromId(int id) {
|
||||
return VALUES.length > id ? VALUES[id] : VALUES[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,11 +81,11 @@ public enum WebsocketEventType {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
public static WebsocketEventType getById(int id) {
|
||||
public static WebsocketEventType fromId(int id) {
|
||||
return VALUES.length > id ? VALUES[id] : null;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ import org.geysermc.floodgate.crypto.AesKeyProducer;
|
|||
import org.geysermc.floodgate.crypto.Base64Topping;
|
||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||
import org.geysermc.floodgate.news.NewsItemAction;
|
||||
import org.geysermc.floodgate.time.TimeSyncer;
|
||||
import org.geysermc.geyser.api.GeyserApi;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
|
@ -110,7 +109,6 @@ public class GeyserImpl implements GeyserApi {
|
|||
@Setter
|
||||
private static boolean shouldStartListener = true;
|
||||
|
||||
private final TimeSyncer timeSyncer;
|
||||
private FloodgateCipher cipher;
|
||||
private FloodgateSkinUploader skinUploader;
|
||||
private final NewsHandler newsHandler;
|
||||
|
@ -201,9 +199,7 @@ public class GeyserImpl implements GeyserApi {
|
|||
// Ensure that PacketLib does not create an event loop for handling packets; we'll do that ourselves
|
||||
TcpSession.USE_EVENT_LOOP_FOR_PACKETS = false;
|
||||
|
||||
TimeSyncer timeSyncer = null;
|
||||
if (config.getRemote().getAuthType() == AuthType.FLOODGATE) {
|
||||
timeSyncer = new TimeSyncer(Constants.NTP_SERVER);
|
||||
try {
|
||||
Key key = new AesKeyProducer().produceFrom(config.getFloodgateKeyPath());
|
||||
cipher = new AesCipher(new Base64Topping());
|
||||
|
@ -214,7 +210,6 @@ public class GeyserImpl implements GeyserApi {
|
|||
logger.severe(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.bad_key"), exception);
|
||||
}
|
||||
}
|
||||
this.timeSyncer = timeSyncer;
|
||||
|
||||
String branch = "unknown";
|
||||
int buildNumber = -1;
|
||||
|
@ -441,9 +436,6 @@ public class GeyserImpl implements GeyserApi {
|
|||
|
||||
scheduledThread.shutdown();
|
||||
bedrockServer.close();
|
||||
if (timeSyncer != null) {
|
||||
timeSyncer.shutdown();
|
||||
}
|
||||
if (skinUploader != null) {
|
||||
skinUploader.close();
|
||||
}
|
||||
|
@ -491,10 +483,6 @@ public class GeyserImpl implements GeyserApi {
|
|||
return bootstrap.getWorldManager();
|
||||
}
|
||||
|
||||
public TimeSyncer getTimeSyncer() {
|
||||
return timeSyncer;
|
||||
}
|
||||
|
||||
public static GeyserImpl getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
|
|
@ -787,6 +787,8 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
|||
FloodgateSkinUploader skinUploader = geyser.getSkinUploader();
|
||||
FloodgateCipher cipher = geyser.getCipher();
|
||||
|
||||
System.out.println(new String(FloodgateCipher.HEADER, StandardCharsets.UTF_8));
|
||||
|
||||
encryptedData = cipher.encryptFromString(BedrockData.of(
|
||||
clientData.getGameVersion(),
|
||||
authData.name(),
|
||||
|
@ -797,17 +799,8 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
|||
clientData.getCurrentInputMode().ordinal(),
|
||||
upstream.getAddress().getAddress().getHostAddress(),
|
||||
skinUploader.getId(),
|
||||
skinUploader.getVerifyCode(),
|
||||
geyser.getTimeSyncer()
|
||||
skinUploader.getVerifyCode()
|
||||
).toString());
|
||||
|
||||
if (!geyser.getTimeSyncer().hasUsefulOffset()) {
|
||||
geyser.getLogger().warning(
|
||||
"We couldn't make sure that your system clock is accurate. " +
|
||||
"This can cause issues with logging in."
|
||||
);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.encrypt_fail"), e);
|
||||
disconnect(GeyserLocale.getPlayerLocaleString("geyser.auth.floodgate.encryption_fail", getClientData().getLanguageCode()));
|
||||
|
|
|
@ -87,7 +87,7 @@ public final class FloodgateSkinUploader {
|
|||
}
|
||||
|
||||
int typeId = node.get("event_id").asInt();
|
||||
WebsocketEventType type = WebsocketEventType.getById(typeId);
|
||||
WebsocketEventType type = WebsocketEventType.fromId(typeId);
|
||||
if (type == null) {
|
||||
logger.warning(String.format(
|
||||
"Got (unknown) type %s. Ensure that Geyser is on the latest version and report this issue!",
|
||||
|
|
Loading…
Reference in a new issue