Some more API changes

This commit is contained in:
Tim203 2022-08-12 01:01:26 +02:00
parent 80588a07bd
commit ab6e0d1e16
No known key found for this signature in database
GPG Key ID: 064EE9F5BF7C3EE8
9 changed files with 374 additions and 62 deletions

View File

@ -28,6 +28,7 @@ package org.geysermc.api;
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.geysermc.api.connection.Connection;
import org.geysermc.cumulus.form.Form;
import org.geysermc.cumulus.form.util.FormBuilder;
@ -66,11 +67,34 @@ public interface GeyserApiBase {
*/
boolean isBedrockPlayer(@NonNull UUID uuid);
boolean sendForm(UUID uuid, Form form);
/**
* Sends a form to the given connection and opens it.
*
* @param uuid the uuid of the connection to open it on
* @param form the form to send
* @return whether the form was successfully sent
*/
boolean sendForm(@NonNull UUID uuid, @NonNull Form form);
boolean sendForm(UUID uuid, FormBuilder<?, ?, ?> formBuilder);
/**
* Sends a form to the given connection and opens it.
*
* @param uuid the uuid of the connection to open it on
* @param formBuilder the formBuilder to send
* @return whether the form was successfully sent
*/
boolean sendForm(@NonNull UUID uuid, @NonNull FormBuilder<?, ?, ?> formBuilder);
boolean transfer(UUID uuid, String address, int port);
/**
* Transfer the given connection to a server. A Bedrock player can successfully transfer to the same server they are
* currently playing on.
*
* @param uuid the uuid of the connection
* @param address the address of the server
* @param port the port of the server
* @return true if the transfer was a success
*/
boolean transfer(@NonNull UUID uuid, @NonNull String address, @IntRange(from = 0, to = 65535) int port);
/**

View File

@ -28,6 +28,11 @@ package org.geysermc.api.connection;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.common.value.qual.IntRange;
import org.geysermc.api.util.BedrockPlatform;
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 java.util.UUID;
@ -36,43 +41,80 @@ import java.util.UUID;
*/
public interface Connection {
/**
* Gets the bedrock name of the connection.
*
* @return the bedrock name of the connection
* Returns the bedrock name of the connection.
*/
@NonNull
String bedrockUsername();
@NonNull String bedrockUsername();
/**
* Gets the java name of the connection.
*
* @return the java name of the connection
* Returns the java name of the connection.
*/
@MonotonicNonNull
String javaUsername();
/**
* Gets the {@link UUID} of the connection.
*
* @return the UUID of the connection
* Returns the UUID of the connection.
*/
@MonotonicNonNull
UUID javaUuid();
/**
* Gets the XUID of the connection.
*
* @return the XUID of the connection
* Returns the XUID of the connection.
*/
@NonNull
String xuid();
@NonNull String xuid();
/**
* Returns the version of the Bedrock client.
*/
@NonNull String version();
/**
* Returns the platform that the connection is playing on.
*/
@NonNull BedrockPlatform platform();
/**
* Returns the language code of the connection.
*/
@NonNull String languageCode();
/**
* Returns the User Interface Profile of the connection.
*/
@NonNull UiProfile uiProfile();
/**
* Returns the Input Mode of the Bedrock client.
*/
@NonNull InputMode inputMode();
/**
* Returns whether the connection is linked.
* This will always return false when the auth-type isn't Floodgate.
*/
boolean isLinked();
/**
* Sends a form to the connection and opens it.
*
* @param form the form to send
* @return whether the form was successfully sent
*/
boolean sendForm(@NonNull Form form);
/**
* Sends a form to the connection and opens it.
*
* @param formBuilder the formBuilder to send
* @return whether the form was successfully sent
*/
boolean sendForm(@NonNull FormBuilder<?, ?, ?> formBuilder);
/**
* Transfer the connection to a server. A Bedrock player can successfully transfer to the same server they are
* currently playing on.
*
* @param address The address of the server
* @param port The port of the server
* @param address the address of the server
* @param port the port of the server
* @return true if the transfer was a success
*/
boolean transfer(@NonNull String address, @IntRange(from = 0, to = 65535) int port);

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.api.util;
public enum BedrockPlatform {
UNKNOWN("Unknown"),
GOOGLE("Android"),
IOS("iOS"),
OSX("macOS"),
AMAZON("Amazon"),
GEARVR("Gear VR"),
HOLOLENS("Hololens"),
UWP("Windows 10"),
WIN32("Windows x86"),
DEDICATED("Dedicated"),
TVOS("Apple TV"),
PS4("PS4"),
NX("Switch"),
XBOX("Xbox One"),
WINDOWS_PHONE("Windows Phone");
private static final BedrockPlatform[] VALUES = values();
private final String displayName;
BedrockPlatform(String displayName) {
this.displayName = displayName;
}
/**
* Get the BedrockPlatform from the identifier.
*
* @param id the BedrockPlatform identifier
* @return The BedrockPlatform or {@link #UNKNOWN} if the platform wasn't found
*/
public static BedrockPlatform fromId(int id) {
return id < VALUES.length ? VALUES[id] : VALUES[0];
}
/**
* @return friendly display name of platform.
*/
@Override
public String toString() {
return displayName;
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.api.util;
public enum InputMode {
UNKNOWN,
KEYBOARD_MOUSE,
TOUCH,
CONTROLLER,
VR;
private static final InputMode[] VALUES = values();
/**
* Get the InputMode from the identifier.
*
* @param id the InputMode identifier
* @return The InputMode or {@link #UNKNOWN} if the mode wasn't found
*/
public static InputMode fromId(int id) {
return VALUES.length > id ? VALUES[id] : VALUES[0];
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.api.util;
public enum UiProfile {
CLASSIC, POCKET;
private static final UiProfile[] VALUES = values();
/**
* Get the UiProfile from the identifier.
*
* @param id the UiProfile identifier
* @return The UiProfile or {@link #CLASSIC} if the profile wasn't found
*/
public static UiProfile fromId(int id) {
return VALUES.length > id ? VALUES[id] : VALUES[0];
}
}

View File

@ -41,10 +41,13 @@ import io.netty.util.internal.SystemPropertyUtil;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.api.Geyser;
import org.geysermc.common.PlatformType;
import org.geysermc.cumulus.form.Form;
import org.geysermc.cumulus.form.util.FormBuilder;
import org.geysermc.floodgate.crypto.AesCipher;
import org.geysermc.floodgate.crypto.AesKeyProducer;
import org.geysermc.floodgate.crypto.Base64Topping;
@ -486,6 +489,11 @@ public class GeyserImpl implements GeyserApi {
return sessionManager.size();
}
@Override
public @MonotonicNonNull String usernamePrefix() {
return null;
}
@Override
public @Nullable GeyserSession connectionByUuid(@NonNull UUID uuid) {
return this.sessionManager.getSessions().get(uuid);
@ -493,13 +501,38 @@ public class GeyserImpl implements GeyserApi {
@Override
public @Nullable GeyserSession connectionByXuid(@NonNull String xuid) {
for (GeyserSession session : sessionManager.getAllSessions()) {
if (session.xuid().equals(xuid)) {
return session;
}
}
return sessionManager.sessionByXuid(xuid);
}
return null;
@Override
public boolean isBedrockPlayer(@NonNull UUID uuid) {
return connectionByUuid(uuid) != null;
}
@Override
public boolean sendForm(@NonNull UUID uuid, @NonNull Form form) {
Objects.requireNonNull(uuid);
Objects.requireNonNull(form);
GeyserSession session = connectionByUuid(uuid);
if (session == null) {
return false;
}
return session.sendForm(form);
}
@Override
public boolean sendForm(@NonNull UUID uuid, @NonNull FormBuilder<?, ?, ?> formBuilder) {
return sendForm(uuid, formBuilder.build());
}
@Override
public boolean transfer(@NonNull UUID uuid, @NonNull String address, int port) {
Objects.requireNonNull(uuid);
GeyserSession session = connectionByUuid(uuid);
if (session == null) {
return false;
}
return session.transfer(address, port);
}
public void shutdown() {

View File

@ -73,7 +73,7 @@ public class SessionPlayerEntity extends PlayerEntity {
private int fakeTradeXp;
public SessionPlayerEntity(GeyserSession session) {
super(session, -1, 1, UUID.randomUUID(), Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0, "unknown", null);
super(session, -1, 1, null, Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0, null, null);
valid = true;
}

View File

@ -91,6 +91,9 @@ import lombok.Setter;
import lombok.experimental.Accessors;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.common.value.qual.IntRange;
import org.geysermc.api.util.BedrockPlatform;
import org.geysermc.api.util.InputMode;
import org.geysermc.api.util.UiProfile;
import org.geysermc.common.PlatformType;
import org.geysermc.cumulus.form.Form;
import org.geysermc.cumulus.form.util.FormBuilder;
@ -136,7 +139,6 @@ import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.LoginEncryptionUtils;
import org.geysermc.geyser.util.MathUtils;
import javax.annotation.Nonnull;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@ -151,13 +153,13 @@ import java.util.concurrent.atomic.AtomicInteger;
@Getter
public class GeyserSession implements GeyserConnection, GeyserCommandSource {
private final @Nonnull GeyserImpl geyser;
private final @Nonnull UpstreamSession upstream;
private final @NonNull GeyserImpl geyser;
private final @NonNull UpstreamSession upstream;
/**
* The loop where all packets and ticking is processed to prevent concurrency issues.
* If this is manually called, ensure that any exceptions are properly handled.
*/
private final @Nonnull EventLoop eventLoop;
private final @NonNull EventLoop eventLoop;
private TcpSession downstream;
@Setter
private AuthData authData;
@ -1326,33 +1328,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
}
@Override
public String bedrockUsername() {
return authData.name();
}
@Override
public UUID javaUuid() {
}
@Override
public String xuid() {
return authData.xuid();
}
@SuppressWarnings("ConstantConditions") // Need to enforce the parameter annotations
@Override
public boolean transfer(@NonNull String address, @IntRange(from = 0, to = 65535) int port) {
if (address == null || address.isBlank()) {
throw new IllegalArgumentException("Server address cannot be null or blank");
} else if (port < 0 || port > 65535) {
throw new IllegalArgumentException("Server port must be between 0 and 65535, was " + port);
}
TransferPacket transferPacket = new TransferPacket();
transferPacket.setAddress(address);
transferPacket.setPort(port);
sendUpstreamPacket(transferPacket);
return true;
public String name() {
return null;
}
@Override
@ -1405,12 +1382,14 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
return this.upstream.getAddress();
}
public void sendForm(Form form) {
public boolean sendForm(@NonNull Form form) {
formCache.showForm(form);
return true;
}
public void sendForm(FormBuilder<?, ?, ?> formBuilder) {
public boolean sendForm(@NonNull FormBuilder<?, ?, ?> formBuilder) {
formCache.showForm(formBuilder.build());
return true;
}
/**
@ -1765,7 +1744,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
*
* @param statistics Updated statistics values
*/
public void updateStatistics(@Nonnull Object2IntMap<Statistic> statistics) {
public void updateStatistics(@NonNull Object2IntMap<Statistic> statistics) {
if (this.statistics.isEmpty()) {
// Initialize custom statistics to 0, so that they appear in the form
for (CustomStatistic customStatistic : CustomStatistic.values()) {
@ -1851,4 +1830,69 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
public MinecraftCodecHelper getCodecHelper() {
return (MinecraftCodecHelper) this.downstream.getCodecHelper();
}
@Override
public String bedrockUsername() {
return authData.name();
}
@Override
public @MonotonicNonNull String javaUsername() {
return playerEntity.getUsername();
}
@Override
public UUID javaUuid() {
return playerEntity.getUuid();
}
@Override
public String xuid() {
return authData.xuid();
}
@Override
public @NonNull String version() {
return clientData.getGameVersion();
}
@Override
public @NonNull BedrockPlatform platform() {
return BedrockPlatform.values()[clientData.getDeviceOs().ordinal()]; //todo
}
@Override
public @NonNull String languageCode() {
return locale();
}
@Override
public @NonNull UiProfile uiProfile() {
return UiProfile.values()[clientData.getUiProfile().ordinal()]; //todo
}
@Override
public @NonNull InputMode inputMode() {
return InputMode.values()[clientData.getCurrentInputMode().ordinal()]; //todo
}
@Override
public boolean isLinked() {
return false; //todo
}
@SuppressWarnings("ConstantConditions") // Need to enforce the parameter annotations
@Override
public boolean transfer(@NonNull String address, @IntRange(from = 0, to = 65535) int port) {
if (address == null || address.isBlank()) {
throw new IllegalArgumentException("Server address cannot be null or blank");
} else if (port < 0 || port > 65535) {
throw new IllegalArgumentException("Server port must be between 0 and 65535, was " + port);
}
TransferPacket transferPacket = new TransferPacket();
transferPacket.setAddress(address);
transferPacket.setPort(port);
sendUpstreamPacket(transferPacket);
return true;
}
}

View File

@ -28,6 +28,7 @@ package org.geysermc.geyser.session;
import com.google.common.collect.ImmutableList;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import org.geysermc.geyser.text.GeyserLocale;
import java.util.*;
@ -67,6 +68,16 @@ public final class SessionManager {
}
}
public GeyserSession sessionByXuid(@NonNull String xuid) {
Objects.requireNonNull(xuid);
for (GeyserSession session : sessions.values()) {
if (session.xuid().equals(xuid)) {
return session;
}
}
return null;
}
/**
* Creates a new, immutable list containing all pending and active sessions.
*/