Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api/src/main/java/org/geysermc/geyser/api/GeyserApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ public interface GeyserApi extends GeyserApiBase {
@NonNull
List<? extends GeyserConnection> onlineConnections();

/**
* Method to determine if the given online player is a linked Bedrock player.
*
* @param uuid the uuid of the online player
* @return true if the given online player is a Bedrock player
*/
boolean isLinkedPlayer(@NonNull UUID uuid);

Comment on lines +69 to +76
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls remove, don't want to introduce this API at the moment until the merge

/**
* Gets the {@link ExtensionManager}.
*
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/org/geysermc/geyser/GeyserImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,12 @@ public boolean isBedrockPlayer(@NonNull UUID uuid) {
return connectionByUuid(uuid) != null;
}

@Override
public boolean isLinkedPlayer(@NonNull UUID uuid) {
GeyserSession session = connectionByUuid(uuid);
return session != null && session.isLinked();
}

@Override
public boolean sendForm(@NonNull UUID uuid, @NonNull Form form) {
Objects.requireNonNull(uuid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,7 @@ public void disconnect(Component reason) {

// Remove from session manager
geyser.getSessionManager().removeSession(this);
SkinManager.removeCachedBedrockSkin(this);
if (authData != null) {
PendingMicrosoftAuthentication.AuthenticationTask task = geyser.getPendingMicrosoftAuthentication().getTask(authData.xuid());
if (task != null) {
Expand Down Expand Up @@ -2314,7 +2315,8 @@ public UUID javaUuid() {

@Override
public boolean isLinked() {
return false; //todo
// Java and linked players' uuid version is 4, while bedrock is 0
return this.javaUuid().version() == 4;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With local linking this isn't necessarily true.. might be easier to check if the uuid isn't version 0?

}

@SuppressWarnings("ConstantConditions") // Need to enforce the parameter annotations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,17 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import org.cloudburstmc.protocol.bedrock.data.skin.AnimatedTextureType;
import org.cloudburstmc.protocol.bedrock.data.skin.AnimationData;
import org.cloudburstmc.protocol.bedrock.data.skin.AnimationExpressionType;
import org.cloudburstmc.protocol.bedrock.data.skin.ImageData;
import org.cloudburstmc.protocol.bedrock.data.skin.PersonaPieceData;
import org.cloudburstmc.protocol.bedrock.data.skin.PersonaPieceTintData;
import org.geysermc.floodgate.util.DeviceOs;
import org.geysermc.floodgate.util.InputMode;
import org.geysermc.floodgate.util.UiProfile;

import java.util.List;
import java.util.UUID;

@JsonIgnoreProperties(ignoreUnknown = true)
Expand All @@ -51,7 +58,7 @@ public final class BedrockClientData {
@JsonProperty(value = "SkinId")
private String skinId;
@JsonProperty(value = "SkinData")
private String skinData;
private byte[] skinData;
@JsonProperty(value = "SkinImageHeight")
private int skinImageHeight;
@JsonProperty(value = "SkinImageWidth")
Expand All @@ -67,13 +74,27 @@ public final class BedrockClientData {
@JsonProperty(value = "CapeOnClassicSkin")
private boolean capeOnClassicSkin;
@JsonProperty(value = "SkinResourcePatch")
private String geometryName;
private byte[] geometryName;
@JsonProperty(value = "SkinGeometryData")
private String geometryData;
private byte[] geometryData;
@JsonProperty(value = "PersonaSkin")
private boolean personaSkin;
@JsonProperty(value = "PremiumSkin")
private boolean premiumSkin;
@JsonIgnore
private List<PersonaPieceData> personaPieces;
@JsonIgnore
private List<PersonaPieceTintData> personaPieceTint;
@JsonIgnore
private List<AnimationData> skinAnimations;
@JsonProperty(value = "SkinAnimationData")
private byte[] skinAnimationData;
@JsonProperty(value = "ArmSize")
private String armSize;
@JsonProperty(value = "SkinColor")
private String skinColor;
@JsonProperty(value = "SkinGeometryDataEngineVersion")
private byte[] geometryDataEngineVersion;

@JsonProperty(value = "DeviceId")
private String deviceId;
Expand All @@ -98,12 +119,6 @@ public final class BedrockClientData {
@JsonProperty(value = "ClientRandomId")
private long clientRandomId;

@JsonProperty(value = "ArmSize")
private String armSize;
@JsonProperty(value = "SkinAnimationData")
private String skinAnimationData;
@JsonProperty(value = "SkinColor")
private String skinColor;
@JsonProperty(value = "ThirdPartyNameOnly")
private boolean thirdPartyNameOnly;
@JsonProperty(value = "PlayFabId")
Expand All @@ -128,4 +143,35 @@ public InputMode getDefaultInputMode() {
public UiProfile getUiProfile() {
return uiProfile != null ? uiProfile : UiProfile.CLASSIC;
}

@JsonProperty(value = "AnimatedImageData")
private void processAnimationData(List<AnimationDataDTO> animationDataDTO) {
this.skinAnimations = animationDataDTO.stream().map(animation -> new AnimationData(ImageData.of(animation.imageWidth, animation.ImageHeight, animation.image), animation.textureType(), animation.frames())).toList();
}

@JsonProperty(value = "PersonaPieces")
private void processPersonaPieceData(List<PersonaPieceDataDTO> personaPieceDataDTO) {
this.personaPieces = personaPieceDataDTO.stream().map(personaPiece -> new PersonaPieceData(personaPiece.id, personaPiece.type, personaPiece.packId, personaPiece.isDefault, personaPiece.productId)).toList();
}

@JsonProperty(value = "PieceTintColors")
private void processPersonaPieceTintData(List<PersonaPieceTintDataDTO> personaPieceTintDataDTO) {
this.personaPieceTint = personaPieceTintDataDTO.stream().map(personaPieceTint -> new PersonaPieceTintData(personaPieceTint.type, personaPieceTint.colors)).toList();
}

private record AnimationDataDTO(@JsonProperty(value = "Type") AnimatedTextureType textureType,
@JsonProperty(value = "Image") byte[] image,
@JsonProperty(value = "ImageWidth") int imageWidth,
@JsonProperty(value = "ImageHeight") int ImageHeight,
@JsonProperty(value = "Frames") float frames,
@JsonProperty(value = "AnimationExpression") AnimationExpressionType expressionType) {}

private record PersonaPieceDataDTO(@JsonProperty(value = "PieceId") String id,
@JsonProperty(value = "PieceType") String type,
@JsonProperty(value = "PackId") String packId,
@JsonProperty(value = "IsDefault") boolean isDefault,
@JsonProperty(value = "ProductId") String productId) {}

private record PersonaPieceTintDataDTO(@JsonProperty(value = "PieceType") String type,
@JsonProperty(value = "Colors") List<String> colors) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ public class FakeHeadProvider {
.build(new CacheLoader<>() {
@Override
public SkinData load(@NonNull FakeHeadEntry fakeHeadEntry) throws Exception {
SkinData skinData = SkinProvider.getOrDefault(SkinProvider.requestSkinData(fakeHeadEntry.getEntity(), fakeHeadEntry.getSession()), null, 5);
SkinData skinData = SkinManager.getSkinData(SkinProvider.getOrDefault(
SkinProvider.requestSkinData(fakeHeadEntry.getEntity(), fakeHeadEntry.getSession()), null, 5));

if (skinData == null) {
throw new Exception("Couldn't load player's original skin");
Expand Down
Loading