Edited PlayerInit behavior and updated protocol lib to 2.3.0

This commit is contained in:
Tim203 2019-10-09 20:39:38 +02:00
parent a7bd9da644
commit 15506cf5b4
36 changed files with 320 additions and 514 deletions

View file

@ -75,7 +75,7 @@
<dependency> <dependency>
<groupId>com.nukkitx.protocol</groupId> <groupId>com.nukkitx.protocol</groupId>
<artifactId>bedrock-v361</artifactId> <artifactId>bedrock-v361</artifactId>
<version>2.2.0</version> <version>2.3.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>

View file

@ -25,8 +25,8 @@
package org.geysermc.connector.entity; package org.geysermc.connector.entity;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityPropertiesPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityPropertiesPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.EntityData; import com.nukkitx.protocol.bedrock.data.EntityData;
import com.nukkitx.protocol.bedrock.data.EntityDataDictionary; import com.nukkitx.protocol.bedrock.data.EntityDataDictionary;
import com.nukkitx.protocol.bedrock.data.EntityFlag; import com.nukkitx.protocol.bedrock.data.EntityFlag;
@ -116,17 +116,17 @@ public class Entity {
} }
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch) { public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch) {
moveRelative(relX, relY, relZ, new Vector3f(yaw, pitch, yaw)); moveRelative(relX, relY, relZ, Vector3f.from(yaw, pitch, yaw));
} }
public void moveRelative(double relX, double relY, double relZ, Vector3f rotation) { public void moveRelative(double relX, double relY, double relZ, Vector3f rotation) {
setRotation(rotation); setRotation(rotation);
this.position = new Vector3f(position.getX() + relX, position.getY() + relY, position.getZ() + relZ); this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ);
this.movePending = true; this.movePending = true;
} }
public void moveAbsolute(Vector3f position, float yaw, float pitch) { public void moveAbsolute(Vector3f position, float yaw, float pitch) {
moveAbsolute(position, new Vector3f(yaw, pitch, yaw)); moveAbsolute(position, Vector3f.from(yaw, pitch, yaw));
} }
public void moveAbsolute(Vector3f position, Vector3f rotation) { public void moveAbsolute(Vector3f position, Vector3f rotation) {
@ -137,7 +137,7 @@ public class Entity {
public EntityDataDictionary getMetadata() { public EntityDataDictionary getMetadata() {
EntityFlags flags = new EntityFlags(); EntityFlags flags = new EntityFlags();
flags.setFlag(EntityFlag.HAS_GRAVITY, !is(PlayerEntity.class) || as(PlayerEntity.class).isGravity()); flags.setFlag(EntityFlag.HAS_GRAVITY, true);
flags.setFlag(EntityFlag.HAS_COLLISION, true); flags.setFlag(EntityFlag.HAS_COLLISION, true);
flags.setFlag(EntityFlag.CAN_SHOW_NAME, true); flags.setFlag(EntityFlag.CAN_SHOW_NAME, true);
flags.setFlag(EntityFlag.CAN_CLIMB, true); flags.setFlag(EntityFlag.CAN_CLIMB, true);
@ -199,7 +199,7 @@ public class Entity {
* x = Pitch, y = HeadYaw, z = Yaw * x = Pitch, y = HeadYaw, z = Yaw
*/ */
public Vector3f getBedrockRotation() { public Vector3f getBedrockRotation() {
return new Vector3f(rotation.getY(), rotation.getZ(), rotation.getX()); return Vector3f.from(rotation.getY(), rotation.getZ(), rotation.getX());
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View file

@ -25,7 +25,7 @@
package org.geysermc.connector.entity; package org.geysermc.connector.entity;
import com.flowpowered.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.SpawnExperienceOrbPacket; import com.nukkitx.protocol.bedrock.packet.SpawnExperienceOrbPacket;
import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;

View file

@ -1,6 +1,6 @@
package org.geysermc.connector.entity; package org.geysermc.connector.entity;
import com.flowpowered.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.AddPaintingPacket; import com.nukkitx.protocol.bedrock.packet.AddPaintingPacket;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;

View file

@ -25,16 +25,18 @@
package org.geysermc.connector.entity; package org.geysermc.connector.entity;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.auth.data.GameProfile;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.data.ItemData;
import com.nukkitx.protocol.bedrock.packet.AddPlayerPacket; import com.nukkitx.protocol.bedrock.packet.AddPlayerPacket;
import com.nukkitx.protocol.bedrock.packet.MobArmorEquipmentPacket; import com.nukkitx.protocol.bedrock.packet.MobArmorEquipmentPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.PlayerListPacket;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.geysermc.api.Geyser;
import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.utils.SkinUtils;
import java.util.UUID; import java.util.UUID;
@ -45,7 +47,6 @@ public class PlayerEntity extends Entity {
private String username; private String username;
private long lastSkinUpdate = -1; private long lastSkinUpdate = -1;
private boolean playerList = true; private boolean playerList = true;
private boolean gravity = false;
private ItemData helmet; private ItemData helmet;
private ItemData chestplate; private ItemData chestplate;
@ -76,17 +77,6 @@ public class PlayerEntity extends Entity {
session.getUpstream().sendPacket(armorEquipmentPacket); session.getUpstream().sendPacket(armorEquipmentPacket);
} }
public void enableGravity(GeyserSession session) {
if (!gravity && session.getPlayerEntity().getGeyserId() == getGeyserId()) {
gravity = true;
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.setRuntimeEntityId(geyserId);
entityDataPacket.getMetadata().putAll(getMetadata());
session.getUpstream().sendPacket(entityDataPacket);
}
}
@Override @Override
public boolean despawnEntity(GeyserSession session) { public boolean despawnEntity(GeyserSession session) {
super.despawnEntity(session); super.despawnEntity(session);
@ -118,4 +108,31 @@ public class PlayerEntity extends Entity {
valid = true; valid = true;
session.getUpstream().sendPacket(addPlayerPacket); session.getUpstream().sendPacket(addPlayerPacket);
} }
public void sendPlayer(GeyserSession session) {
if (getLastSkinUpdate() == -1) {
if (playerList) {
PlayerListPacket playerList = new PlayerListPacket();
playerList.setType(PlayerListPacket.Type.ADD);
playerList.getEntries().add(SkinUtils.buildDefaultEntry(profile, geyserId));
session.getUpstream().sendPacket(playerList);
}
}
if (session.getUpstream().isInitialized() && session.getEntityCache().getEntityByGeyserId(geyserId) == null) {
session.getEntityCache().spawnEntity(this);
} else {
spawnEntity(session);
}
if (!playerList) {
// remove from playerlist if player isn't on playerlist
Geyser.getGeneralThreadPool().execute(() -> {
PlayerListPacket playerList = new PlayerListPacket();
playerList.setType(PlayerListPacket.Type.REMOVE);
playerList.getEntries().add(new PlayerListPacket.Entry(uuid));
session.getUpstream().sendPacket(playerList);
});
}
}
} }

View file

@ -25,10 +25,6 @@
package org.geysermc.connector.network.session; package org.geysermc.connector.network.session;
import com.flowpowered.math.vector.Vector2f;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3f;
import com.flowpowered.math.vector.Vector3i;
import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.auth.exception.request.RequestException; import com.github.steveice10.mc.auth.exception.request.RequestException;
import com.github.steveice10.mc.protocol.MinecraftProtocol; import com.github.steveice10.mc.protocol.MinecraftProtocol;
@ -40,6 +36,10 @@ import com.github.steveice10.packetlib.event.session.PacketReceivedEvent;
import com.github.steveice10.packetlib.event.session.SessionAdapter; import com.github.steveice10.packetlib.event.session.SessionAdapter;
import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.packet.Packet;
import com.github.steveice10.packetlib.tcp.TcpSessionFactory; import com.github.steveice10.packetlib.tcp.TcpSessionFactory;
import com.nukkitx.math.vector.Vector2f;
import com.nukkitx.math.vector.Vector2i;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.BedrockServerSession;
import com.nukkitx.protocol.bedrock.data.GamePublishSetting; import com.nukkitx.protocol.bedrock.data.GamePublishSetting;
import com.nukkitx.protocol.bedrock.data.GameRule; import com.nukkitx.protocol.bedrock.data.GameRule;
@ -257,15 +257,15 @@ public class GeyserSession implements Player {
startGamePacket.setUniqueEntityId(playerEntity.getGeyserId()); startGamePacket.setUniqueEntityId(playerEntity.getGeyserId());
startGamePacket.setRuntimeEntityId(playerEntity.getGeyserId()); startGamePacket.setRuntimeEntityId(playerEntity.getGeyserId());
startGamePacket.setPlayerGamemode(0); startGamePacket.setPlayerGamemode(0);
startGamePacket.setPlayerPosition(new Vector3f(0, 69, 0)); startGamePacket.setPlayerPosition(Vector3f.from(0, 69, 0));
startGamePacket.setRotation(new Vector2f(1, 1)); startGamePacket.setRotation(Vector2f.from(1, 1));
startGamePacket.setSeed(0); startGamePacket.setSeed(0);
startGamePacket.setDimensionId(playerEntity.getDimension()); startGamePacket.setDimensionId(playerEntity.getDimension());
startGamePacket.setGeneratorId(1); startGamePacket.setGeneratorId(1);
startGamePacket.setLevelGamemode(0); startGamePacket.setLevelGamemode(0);
startGamePacket.setDifficulty(1); startGamePacket.setDifficulty(1);
startGamePacket.setDefaultSpawn(new Vector3i(0, 0, 0)); startGamePacket.setDefaultSpawn(Vector3i.ZERO);
startGamePacket.setAcheivementsDisabled(true); startGamePacket.setAcheivementsDisabled(true);
startGamePacket.setTime(0); startGamePacket.setTime(0);
startGamePacket.setEduLevel(false); startGamePacket.setEduLevel(false);
@ -304,7 +304,5 @@ public class GeyserSession implements Player {
PlayStatusPacket playStatusPacket = new PlayStatusPacket(); PlayStatusPacket playStatusPacket = new PlayStatusPacket();
playStatusPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN); playStatusPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN);
upstream.sendPacket(playStatusPacket); upstream.sendPacket(playStatusPacket);
upstream.setFrozen(true); // will freeze until the client decides it is ready
} }
} }

View file

@ -5,46 +5,24 @@ import com.nukkitx.protocol.bedrock.BedrockServerSession;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.geysermc.api.Geyser; import lombok.Setter;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
@RequiredArgsConstructor @RequiredArgsConstructor
public class UpstreamSession { public class UpstreamSession {
@Getter private final BedrockServerSession session; @Getter private final BedrockServerSession session;
private Queue<BedrockPacket> packets = new ConcurrentLinkedQueue<>(); @Getter @Setter
@Getter private boolean frozen = false; private boolean initialized = false;
private boolean queueCleared = true;
public void sendPacket(@NonNull BedrockPacket packet) { public void sendPacket(@NonNull BedrockPacket packet) {
if (frozen || !packets.isEmpty()) { session.sendPacket(packet);
packets.add(packet);
} else {
session.sendPacket(packet);
}
} }
public void sendPacketImmediately(@NonNull BedrockPacket packet) { public void sendPacketImmediately(@NonNull BedrockPacket packet) {
session.sendPacketImmediately(packet); session.sendPacketImmediately(packet);
} }
public void setFrozen(boolean frozen) {
if (this.frozen != frozen) {
this.frozen = frozen;
if (!frozen) {
Geyser.getGeneralThreadPool().execute(() -> {
BedrockPacket packet;
while ((packet = packets.poll()) != null) {
session.sendPacket(packet);
}
});
}
}
}
public void disconnect(String reason) { public void disconnect(String reason) {
session.disconnect(reason); session.disconnect(reason);
} }
@ -56,20 +34,4 @@ public class UpstreamSession {
public InetSocketAddress getAddress() { public InetSocketAddress getAddress() {
return session.getAddress(); return session.getAddress();
} }
public boolean hasQueue() {
return !packets.isEmpty();
}
/**
* @return true the first time this method is called after the queue is empty.<br>
* This will enable gravity because now the client is ready to explore
*/
public boolean isQueueCleared() {
if (!hasQueue() && queueCleared) {
queueCleared = false;
return true;
}
return false;
}
} }

View file

@ -30,9 +30,7 @@ import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.entity.PlayerEntity;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.HashMap; import java.util.*;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
/** /**
@ -84,6 +82,16 @@ public class EntityCache {
return entities.get(entityIdTranslations.get(javaId)); return entities.get(entityIdTranslations.get(javaId));
} }
public <T extends Entity> Set<T> getEntitiesByType(Class<T> entityType) {
Set<T> entitiesOfType = new HashSet<>();
for (Entity entity : (entityType == PlayerEntity.class ? playerEntities : entities).values()) {
if (entity.is(entityType)) {
entitiesOfType.add(entity.as(entityType));
}
}
return entitiesOfType;
}
public void addPlayerEntity(PlayerEntity entity) { public void addPlayerEntity(PlayerEntity entity) {
playerEntities.put(entity.getUuid(), entity); playerEntities.put(entity.getUuid(), entity);
} }

View file

@ -54,10 +54,7 @@ import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.network.translators.item.ItemTranslator;
import org.geysermc.connector.network.translators.java.*; import org.geysermc.connector.network.translators.java.*;
import org.geysermc.connector.network.translators.java.entity.*; import org.geysermc.connector.network.translators.java.entity.*;
import org.geysermc.connector.network.translators.java.entity.player.JavaPlayerActionAckTranslator; import org.geysermc.connector.network.translators.java.entity.player.*;
import org.geysermc.connector.network.translators.java.entity.player.JavaPlayerHealthTranslator;
import org.geysermc.connector.network.translators.java.entity.player.JavaPlayerPositionRotationTranslator;
import org.geysermc.connector.network.translators.java.entity.player.JavaPlayerSetExperienceTranslator;
import org.geysermc.connector.network.translators.java.entity.spawn.*; import org.geysermc.connector.network.translators.java.entity.spawn.*;
import org.geysermc.connector.network.translators.java.scoreboard.JavaDisplayScoreboardTranslator; import org.geysermc.connector.network.translators.java.scoreboard.JavaDisplayScoreboardTranslator;
import org.geysermc.connector.network.translators.java.scoreboard.JavaScoreboardObjectiveTranslator; import org.geysermc.connector.network.translators.java.scoreboard.JavaScoreboardObjectiveTranslator;

View file

@ -25,7 +25,6 @@
package org.geysermc.connector.network.translators.bedrock; package org.geysermc.connector.network.translators.bedrock;
import com.flowpowered.math.vector.Vector3i;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
@ -34,6 +33,7 @@ import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket; import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;

View file

@ -25,21 +25,11 @@
package org.geysermc.connector.network.translators.bedrock; package org.geysermc.connector.network.translators.bedrock;
import com.flowpowered.math.vector.Vector3f;
import com.flowpowered.math.vector.Vector3i;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction; import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState;
import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket; import com.nukkitx.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket;
import com.nukkitx.protocol.bedrock.packet.InteractPacket; import com.nukkitx.protocol.bedrock.packet.InteractPacket;
import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.PacketTranslator;

View file

@ -25,9 +25,10 @@
package org.geysermc.connector.network.translators.bedrock; package org.geysermc.connector.network.translators.bedrock;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket; import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
@ -44,9 +45,15 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
if (entity == null || !session.isSpawned()) return; if (entity == null || !session.isSpawned()) return;
// can cause invalid moves when packet queue is not empty // can cause invalid moves when packet queue is not empty
if (session.getUpstream().hasQueue()) return; if (!session.getUpstream().isInitialized()) {
if (session.getUpstream().isQueueCleared()) { MoveEntityAbsolutePacket moveEntityBack = new MoveEntityAbsolutePacket();
entity.enableGravity(session); moveEntityBack.setRuntimeEntityId(entity.getGeyserId());
moveEntityBack.setPosition(entity.getPosition());
moveEntityBack.setRotation(entity.getBedrockRotation());
moveEntityBack.setTeleported(true);
moveEntityBack.setOnGround(true);
session.getUpstream().sendPacketImmediately(moveEntityBack);
return;
} }
if (!isValidMove(session, packet.getMode(), entity.getPosition(), packet.getPosition())) { if (!isValidMove(session, packet.getMode(), entity.getPosition(), packet.getPosition())) {
@ -62,7 +69,10 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
packet.getPosition().getZ(), packet.getRotation().getY(), packet.getRotation().getX() packet.getPosition().getZ(), packet.getRotation().getY(), packet.getRotation().getX()
); );
entity.moveAbsolute(packet.getPosition().sub(0, EntityType.PLAYER.getOffset(), 0), packet.getRotation()); // head yaw, pitch, head yaw
Vector3f rotation = Vector3f.from(packet.getRotation().getY(), packet.getRotation().getX(), packet.getRotation().getY());
entity.moveAbsolute(packet.getPosition().sub(0, EntityType.PLAYER.getOffset(), 0), rotation);
boolean colliding = false; boolean colliding = false;
Position position = new Position((int) packet.getPosition().getX(), Position position = new Position((int) packet.getPosition().getX(),

View file

@ -1,14 +1,26 @@
package org.geysermc.connector.network.translators.bedrock; package org.geysermc.connector.network.translators.bedrock;
import com.nukkitx.protocol.bedrock.packet.SetLocalPlayerAsInitializedPacket; import com.nukkitx.protocol.bedrock.packet.SetLocalPlayerAsInitializedPacket;
import org.geysermc.connector.entity.PlayerEntity;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.utils.SkinUtils;
public class BedrockPlayerInitializedTranslator extends PacketTranslator<SetLocalPlayerAsInitializedPacket> { public class BedrockPlayerInitializedTranslator extends PacketTranslator<SetLocalPlayerAsInitializedPacket> {
@Override @Override
public void translate(SetLocalPlayerAsInitializedPacket packet, GeyserSession session) { public void translate(SetLocalPlayerAsInitializedPacket packet, GeyserSession session) {
if (session.getPlayerEntity().getGeyserId() == packet.getRuntimeEntityId()) { if (session.getPlayerEntity().getGeyserId() == packet.getRuntimeEntityId()) {
session.getUpstream().setFrozen(false); if (!session.getUpstream().isInitialized()) {
session.getUpstream().setInitialized(true);
for (PlayerEntity entity : session.getEntityCache().getEntitiesByType(PlayerEntity.class)) {
if (!entity.isValid()) {
entity.sendPlayer(session);
// async skin loading
SkinUtils.requestAndHandleSkinAndCape(entity, session, skinAndCape -> entity.sendPlayer(session));
}
}
}
} }
} }
} }

View file

@ -25,7 +25,7 @@
package org.geysermc.connector.network.translators.inventory; package org.geysermc.connector.network.translators.inventory;
import com.flowpowered.math.vector.Vector3i; import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.data.ItemData;
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket;
@ -46,7 +46,7 @@ public class GenericInventoryTranslator extends InventoryTranslator {
ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket();
containerOpenPacket.setWindowId((byte) inventory.getId()); containerOpenPacket.setWindowId((byte) inventory.getId());
containerOpenPacket.setType((byte) 0); containerOpenPacket.setType((byte) 0);
containerOpenPacket.setBlockPosition(new Vector3i(0, 0, 0)); containerOpenPacket.setBlockPosition(Vector3i.ZERO);
session.getUpstream().sendPacket(containerOpenPacket); session.getUpstream().sendPacket(containerOpenPacket);
} }

View file

@ -1,7 +1,7 @@
package org.geysermc.connector.network.translators.java; package org.geysermc.connector.network.translators.java;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerBossBarPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerBossBarPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.EntityData; import com.nukkitx.protocol.bedrock.data.EntityData;
import com.nukkitx.protocol.bedrock.packet.AddEntityPacket; import com.nukkitx.protocol.bedrock.packet.AddEntityPacket;
import com.nukkitx.protocol.bedrock.packet.BossEventPacket; import com.nukkitx.protocol.bedrock.packet.BossEventPacket;

View file

@ -25,8 +25,8 @@
package org.geysermc.connector.network.translators.java.entity; package org.geysermc.connector.network.translators.java.entity;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityHeadLookPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityHeadLookPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket; import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
@ -43,7 +43,7 @@ public class JavaEntityHeadLookTranslator extends PacketTranslator<ServerEntityH
if (entity == null) return; if (entity == null) return;
entity.setRotation(new Vector3f(entity.getRotation().getX(), entity.getRotation().getY(), packet.getHeadYaw())); entity.setRotation(Vector3f.from(entity.getRotation().getX(), entity.getRotation().getY(), packet.getHeadYaw()));
MoveEntityAbsolutePacket moveEntityAbsolutePacket = new MoveEntityAbsolutePacket(); MoveEntityAbsolutePacket moveEntityAbsolutePacket = new MoveEntityAbsolutePacket();
moveEntityAbsolutePacket.setRuntimeEntityId(entity.getGeyserId()); moveEntityAbsolutePacket.setRuntimeEntityId(entity.getGeyserId());

View file

@ -25,8 +25,8 @@
package org.geysermc.connector.network.translators.java.entity; package org.geysermc.connector.network.translators.java.entity;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityTeleportPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityTeleportPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket; import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
@ -42,7 +42,7 @@ public class JavaEntityTeleportTranslator extends PacketTranslator<ServerEntityT
} }
if (entity == null) return; if (entity == null) return;
entity.moveAbsolute(new Vector3f(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch()); entity.moveAbsolute(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch());
if (entity.isMovePending()) { if (entity.isMovePending()) {
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();

View file

@ -25,8 +25,8 @@
package org.geysermc.connector.network.translators.java.entity; package org.geysermc.connector.network.translators.java.entity;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityVelocityPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityVelocityPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
@ -42,7 +42,7 @@ public class JavaEntityVelocityTranslator extends PacketTranslator<ServerEntityV
} }
if (entity == null) return; if (entity == null) return;
entity.setMotion(new Vector3f(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ())); entity.setMotion(Vector3f.from(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ()));
SetEntityMotionPacket entityMotionPacket = new SetEntityMotionPacket(); SetEntityMotionPacket entityMotionPacket = new SetEntityMotionPacket();
entityMotionPacket.setRuntimeEntityId(entity.getGeyserId()); entityMotionPacket.setRuntimeEntityId(entity.getGeyserId());

View file

@ -25,8 +25,8 @@
package org.geysermc.connector.network.translators.java.entity.player; package org.geysermc.connector.network.translators.java.entity.player;
import com.flowpowered.math.vector.Vector3i;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerActionAckPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerActionAckPacket;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.PacketTranslator;

View file

@ -25,10 +25,10 @@
package org.geysermc.connector.network.translators.java.entity.player; package org.geysermc.connector.network.translators.java.entity.player;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.data.game.ClientRequest; import com.github.steveice10.mc.protocol.data.game.ClientRequest;
import com.github.steveice10.mc.protocol.packet.ingame.client.ClientRequestPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.ClientRequestPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerHealthPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerHealthPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.RespawnPacket; import com.nukkitx.protocol.bedrock.packet.RespawnPacket;
import com.nukkitx.protocol.bedrock.packet.SetHealthPacket; import com.nukkitx.protocol.bedrock.packet.SetHealthPacket;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
@ -61,7 +61,7 @@ public class JavaPlayerHealthTranslator extends PacketTranslator<ServerPlayerHea
if (packet.getHealth() <= 0) { if (packet.getHealth() <= 0) {
RespawnPacket respawnPacket = new RespawnPacket(); RespawnPacket respawnPacket = new RespawnPacket();
respawnPacket.setPosition(new Vector3f(0, 72, 0)); respawnPacket.setPosition(Vector3f.from(0, 72, 0));
session.getUpstream().sendPacket(new RespawnPacket()); session.getUpstream().sendPacket(new RespawnPacket());
ClientRequestPacket javaRespawnPacket = new ClientRequestPacket(ClientRequest.RESPAWN); ClientRequestPacket javaRespawnPacket = new ClientRequestPacket(ClientRequest.RESPAWN);

View file

@ -1,14 +1,13 @@
package org.geysermc.connector.network.translators.java.entity.spawn; package org.geysermc.connector.network.translators.java.entity.player;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.data.game.PlayerListEntry; import com.github.steveice10.mc.protocol.data.game.PlayerListEntry;
import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction; import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerPlayerListEntryPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerPlayerListEntryPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.PlayerListPacket; import com.nukkitx.protocol.bedrock.packet.PlayerListPacket;
import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.entity.PlayerEntity;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.utils.SkinProvider;
public class JavaPlayerListEntryTranslator extends PacketTranslator<ServerPlayerListEntryPacket> { public class JavaPlayerListEntryTranslator extends PacketTranslator<ServerPlayerListEntryPacket> {
@Override @Override
@ -16,16 +15,15 @@ public class JavaPlayerListEntryTranslator extends PacketTranslator<ServerPlayer
if (packet.getAction() != PlayerListEntryAction.ADD_PLAYER && packet.getAction() != PlayerListEntryAction.REMOVE_PLAYER) return; if (packet.getAction() != PlayerListEntryAction.ADD_PLAYER && packet.getAction() != PlayerListEntryAction.REMOVE_PLAYER) return;
PlayerListPacket translate = new PlayerListPacket(); PlayerListPacket translate = new PlayerListPacket();
translate.setType(packet.getAction() == PlayerListEntryAction.ADD_PLAYER ? PlayerListPacket.Type.ADD : PlayerListPacket.Type.REMOVE); translate.setType(PlayerListPacket.Type.REMOVE);
for (PlayerListEntry entry : packet.getEntries()) { for (PlayerListEntry entry : packet.getEntries()) {
PlayerListPacket.Entry entry1 = new PlayerListPacket.Entry(entry.getProfile().getId());
if (packet.getAction() == PlayerListEntryAction.ADD_PLAYER) { if (packet.getAction() == PlayerListEntryAction.ADD_PLAYER) {
boolean self = entry.getProfile().getId().equals(session.getPlayerEntity().getUuid()); boolean self = entry.getProfile().getId().equals(session.getPlayerEntity().getUuid());
PlayerEntity playerEntity = session.getPlayerEntity(); PlayerEntity playerEntity = session.getPlayerEntity();
if (!self) { if (self) playerEntity.setProfile(entry.getProfile());
else {
playerEntity = new PlayerEntity( playerEntity = new PlayerEntity(
entry.getProfile(), entry.getProfile(),
-1, -1,
@ -38,16 +36,6 @@ public class JavaPlayerListEntryTranslator extends PacketTranslator<ServerPlayer
session.getEntityCache().addPlayerEntity(playerEntity); session.getEntityCache().addPlayerEntity(playerEntity);
playerEntity.setPlayerList(true); playerEntity.setPlayerList(true);
entry1.setName(entry.getProfile().getName());
entry1.setEntityId(playerEntity.getGeyserId());
entry1.setSkinId(entry.getProfile().getIdAsString());
entry1.setSkinData(SkinProvider.STEVE_SKIN);
entry1.setCapeData(new byte[0]);
entry1.setGeometryName("geometry.humanoid");
entry1.setGeometryData("");
entry1.setXuid("");
entry1.setPlatformChatId("");
} else { } else {
PlayerEntity entity = session.getEntityCache().getPlayerEntity(entry.getProfile().getId()); PlayerEntity entity = session.getEntityCache().getPlayerEntity(entry.getProfile().getId());
if (entity != null && entity.isValid()) { if (entity != null && entity.isValid()) {
@ -57,9 +45,12 @@ public class JavaPlayerListEntryTranslator extends PacketTranslator<ServerPlayer
// just remove it from caching // just remove it from caching
session.getEntityCache().removePlayerEntity(entry.getProfile().getId()); session.getEntityCache().removePlayerEntity(entry.getProfile().getId());
} }
translate.getEntries().add(new PlayerListPacket.Entry(entry.getProfile().getId()));
} }
translate.getEntries().add(entry1);
} }
session.getUpstream().sendPacket(translate);
if (packet.getAction() == PlayerListEntryAction.REMOVE_PLAYER) {
session.getUpstream().sendPacket(translate);
}
} }
} }

View file

@ -25,9 +25,9 @@
package org.geysermc.connector.network.translators.java.entity.player; package org.geysermc.connector.network.translators.java.entity.player;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket; import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.console.GeyserLogger;
@ -48,7 +48,7 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator<Serve
return; return;
if (!session.isSpawned()) { if (!session.isSpawned()) {
entity.moveAbsolute(new Vector3f(packet.getX(), packet.getY() + EntityType.PLAYER.getOffset() + 0.1f, packet.getZ()), packet.getYaw(), packet.getPitch()); entity.moveAbsolute(Vector3f.from(packet.getX(), packet.getY() + EntityType.PLAYER.getOffset() + 0.1f, packet.getZ()), packet.getYaw(), packet.getPitch());
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket(); SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.setRuntimeEntityId(entity.getGeyserId()); entityDataPacket.setRuntimeEntityId(entity.getGeyserId());
@ -57,8 +57,8 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator<Serve
MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(entity.getGeyserId()); movePlayerPacket.setRuntimeEntityId(entity.getGeyserId());
movePlayerPacket.setPosition(new Vector3f(packet.getX(), packet.getY() + EntityType.PLAYER.getOffset() + 0.1f, packet.getZ())); movePlayerPacket.setPosition(Vector3f.from(packet.getX(), packet.getY() + EntityType.PLAYER.getOffset() + 0.1f, packet.getZ()));
movePlayerPacket.setRotation(new Vector3f(packet.getPitch(), packet.getYaw(), 0)); movePlayerPacket.setRotation(Vector3f.from(packet.getPitch(), packet.getYaw(), 0));
movePlayerPacket.setMode(MovePlayerPacket.Mode.RESET); movePlayerPacket.setMode(MovePlayerPacket.Mode.RESET);
movePlayerPacket.setOnGround(true); movePlayerPacket.setOnGround(true);
entity.setMovePending(false); entity.setMovePending(false);
@ -70,12 +70,12 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator<Serve
return; return;
} }
entity.moveAbsolute(new Vector3f(packet.getX(), packet.getY() + EntityType.PLAYER.getOffset() + 0.1f, packet.getZ()), packet.getYaw(), packet.getPitch()); entity.moveAbsolute(Vector3f.from(packet.getX(), packet.getY() + EntityType.PLAYER.getOffset() + 0.1f, packet.getZ()), packet.getYaw(), packet.getPitch());
MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(entity.getGeyserId()); movePlayerPacket.setRuntimeEntityId(entity.getGeyserId());
movePlayerPacket.setPosition(new Vector3f(packet.getX(), packet.getY() + EntityType.PLAYER.getOffset() + 0.01f, packet.getZ())); movePlayerPacket.setPosition(Vector3f.from(packet.getX(), packet.getY() + EntityType.PLAYER.getOffset() + 0.01f, packet.getZ()));
movePlayerPacket.setRotation(new Vector3f(packet.getPitch(), packet.getYaw(), 0)); movePlayerPacket.setRotation(Vector3f.from(packet.getPitch(), packet.getYaw(), 0));
movePlayerPacket.setMode(MovePlayerPacket.Mode.NORMAL); movePlayerPacket.setMode(MovePlayerPacket.Mode.NORMAL);
movePlayerPacket.setOnGround(true); movePlayerPacket.setOnGround(true);
entity.setMovePending(false); entity.setMovePending(false);

View file

@ -25,8 +25,8 @@
package org.geysermc.connector.network.translators.java.entity.spawn; package org.geysermc.connector.network.translators.java.entity.spawn;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnExpOrbPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnExpOrbPacket;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.ExpOrbEntity; import org.geysermc.connector.entity.ExpOrbEntity;
import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.entity.type.EntityType;
@ -37,7 +37,7 @@ public class JavaSpawnExpOrbTranslator extends PacketTranslator<ServerSpawnExpOr
@Override @Override
public void translate(ServerSpawnExpOrbPacket packet, GeyserSession session) { public void translate(ServerSpawnExpOrbPacket packet, GeyserSession session) {
Vector3f position = new Vector3f(packet.getX(), packet.getY(), packet.getZ()); Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
Entity entity = new ExpOrbEntity( Entity entity = new ExpOrbEntity(
packet.getExp(), packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), packet.getExp(), packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(),

View file

@ -25,8 +25,8 @@
package org.geysermc.connector.network.translators.java.entity.spawn; package org.geysermc.connector.network.translators.java.entity.spawn;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnGlobalEntityPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnGlobalEntityPacket;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
@ -36,7 +36,7 @@ public class JavaSpawnGlobalEntityTranslator extends PacketTranslator<ServerSpaw
@Override @Override
public void translate(ServerSpawnGlobalEntityPacket packet, GeyserSession session) { public void translate(ServerSpawnGlobalEntityPacket packet, GeyserSession session) {
Vector3f position = new Vector3f(packet.getX(), packet.getY(), packet.getZ()); Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
// Currently GlobalEntityType only has a lightning bolt // Currently GlobalEntityType only has a lightning bolt
Entity entity = new Entity( Entity entity = new Entity(

View file

@ -25,8 +25,8 @@
package org.geysermc.connector.network.translators.java.entity.spawn; package org.geysermc.connector.network.translators.java.entity.spawn;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnMobPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnMobPacket;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.console.GeyserLogger;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.entity.type.EntityType;
@ -38,9 +38,9 @@ public class JavaSpawnMobTranslator extends PacketTranslator<ServerSpawnMobPacke
@Override @Override
public void translate(ServerSpawnMobPacket packet, GeyserSession session) { public void translate(ServerSpawnMobPacket packet, GeyserSession session) {
Vector3f position = new Vector3f(packet.getX(), packet.getY(), packet.getZ()); Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
Vector3f motion = new Vector3f(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ()); Vector3f motion = Vector3f.from(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ());
Vector3f rotation = new Vector3f(packet.getYaw(), packet.getPitch(), packet.getHeadYaw()); Vector3f rotation = Vector3f.from(packet.getYaw(), packet.getPitch(), packet.getHeadYaw());
EntityType type = EntityUtils.toBedrockEntity(packet.getType()); EntityType type = EntityUtils.toBedrockEntity(packet.getType());
if (type == null) { if (type == null) {

View file

@ -25,9 +25,9 @@
package org.geysermc.connector.network.translators.java.entity.spawn; package org.geysermc.connector.network.translators.java.entity.spawn;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.data.game.entity.type.object.ObjectType; import com.github.steveice10.mc.protocol.data.game.entity.type.object.ObjectType;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnObjectPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnObjectPacket;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.console.GeyserLogger;
import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.entity.type.EntityType;
@ -42,9 +42,9 @@ public class JavaSpawnObjectTranslator extends PacketTranslator<ServerSpawnObjec
if (packet.getType() == ObjectType.ITEM_FRAME) if (packet.getType() == ObjectType.ITEM_FRAME)
return; return;
Vector3f position = new Vector3f(packet.getX(), packet.getY(), packet.getZ()); Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
Vector3f motion = new Vector3f(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ()); Vector3f motion = Vector3f.from(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ());
Vector3f rotation = new Vector3f(packet.getYaw(), packet.getPitch(), 0); Vector3f rotation = Vector3f.from(packet.getYaw(), packet.getPitch(), 0);
EntityType type = EntityUtils.toBedrockEntity(packet.getType()); EntityType type = EntityUtils.toBedrockEntity(packet.getType());
if (type == null) { if (type == null) {

View file

@ -25,8 +25,8 @@
package org.geysermc.connector.network.translators.java.entity.spawn; package org.geysermc.connector.network.translators.java.entity.spawn;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnPaintingPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnPaintingPacket;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.api.Geyser; import org.geysermc.api.Geyser;
import org.geysermc.connector.entity.PaintingEntity; import org.geysermc.connector.entity.PaintingEntity;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
@ -37,7 +37,7 @@ public class JavaSpawnPaintingTranslator extends PacketTranslator<ServerSpawnPai
@Override @Override
public void translate(ServerSpawnPaintingPacket packet, GeyserSession session) { public void translate(ServerSpawnPaintingPacket packet, GeyserSession session) {
Vector3f position = new Vector3f(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()); Vector3f position = Vector3f.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ());
Geyser.getGeneralThreadPool().execute(() -> { // #slowdownbrother, just don't execute it directly Geyser.getGeneralThreadPool().execute(() -> { // #slowdownbrother, just don't execute it directly
PaintingEntity entity = new PaintingEntity( PaintingEntity entity = new PaintingEntity(

View file

@ -25,27 +25,21 @@
package org.geysermc.connector.network.translators.java.entity.spawn; package org.geysermc.connector.network.translators.java.entity.spawn;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnPlayerPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnPlayerPacket;
import com.google.gson.JsonObject; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.PlayerListPacket;
import org.apache.commons.codec.Charsets;
import org.geysermc.api.Geyser; import org.geysermc.api.Geyser;
import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.entity.PlayerEntity;
import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.utils.SkinProvider; import org.geysermc.connector.utils.SkinUtils;
import java.util.Base64;
public class JavaSpawnPlayerTranslator extends PacketTranslator<ServerSpawnPlayerPacket> { public class JavaSpawnPlayerTranslator extends PacketTranslator<ServerSpawnPlayerPacket> {
@Override @Override
public void translate(ServerSpawnPlayerPacket packet, GeyserSession session) { public void translate(ServerSpawnPlayerPacket packet, GeyserSession session) {
Vector3f position = new Vector3f(packet.getX(), packet.getY() - EntityType.PLAYER.getOffset(), packet.getZ()); Vector3f position = Vector3f.from(packet.getX(), packet.getY() - EntityType.PLAYER.getOffset(), packet.getZ());
Vector3f rotation = new Vector3f(packet.getYaw(), packet.getPitch(), packet.getYaw()); Vector3f rotation = Vector3f.from(packet.getYaw(), packet.getPitch(), packet.getYaw());
PlayerEntity entity = session.getEntityCache().getPlayerEntity(packet.getUUID()); PlayerEntity entity = session.getEntityCache().getPlayerEntity(packet.getUUID());
if (entity == null) { if (entity == null) {
@ -57,64 +51,8 @@ public class JavaSpawnPlayerTranslator extends PacketTranslator<ServerSpawnPlaye
entity.setPosition(position); entity.setPosition(position);
entity.setRotation(rotation); entity.setRotation(rotation);
session.getEntityCache().spawnEntity(entity); entity.sendPlayer(session);
// async skin loading
// request skin and cape SkinUtils.requestAndHandleSkinAndCape(entity, session, skinAndCape -> entity.sendPlayer(session));
Geyser.getGeneralThreadPool().execute(() -> {
GameProfile.Property skinProperty = entity.getProfile().getProperty("textures");
JsonObject skinObject = SkinProvider.GSON.fromJson(new String(Base64.getDecoder().decode(skinProperty.getValue()), Charsets.UTF_8), JsonObject.class);
JsonObject textures = skinObject.getAsJsonObject("textures");
JsonObject skinTexture = textures.getAsJsonObject("SKIN");
String skinUrl = skinTexture.get("url").getAsString();
boolean isAlex = skinTexture.has("metadata");
String capeUrl = null;
if (textures.has("CAPE")) {
JsonObject capeTexture = textures.getAsJsonObject("CAPE");
capeUrl = capeTexture.get("url").getAsString();
}
SkinProvider.requestAndHandleSkinAndCape(entity.getUuid(), skinUrl, capeUrl)
.whenCompleteAsync((skinAndCape, throwable) -> {
SkinProvider.Skin skin = skinAndCape.getSkin();
SkinProvider.Cape cape = skinAndCape.getCape();
if (cape.isFailed() && SkinProvider.ALLOW_THIRD_PARTY_CAPES) {
cape = SkinProvider.getOrDefault(SkinProvider.requestAndHandleUnofficialCape(
cape, entity.getUuid(),
entity.getUsername(), false
), SkinProvider.EMPTY_CAPE, SkinProvider.UnofficalCape.VALUES.length * 3);
}
if (entity.getLastSkinUpdate() < skin.getRequestedOn()) {
entity.setLastSkinUpdate(skin.getRequestedOn());
PlayerListPacket.Entry updatedEntry = new PlayerListPacket.Entry(skin.getSkinOwner());
updatedEntry.setName(entity.getUsername());
updatedEntry.setEntityId(entity.getGeyserId());
updatedEntry.setSkinId(entity.getUuid().toString());
updatedEntry.setSkinData(skin.getSkinData());
updatedEntry.setCapeData(cape.getCapeData());
updatedEntry.setGeometryName("geometry.humanoid.custom" + (isAlex ? "Slim" : ""));
updatedEntry.setGeometryData("");
updatedEntry.setXuid("");
updatedEntry.setPlatformChatId("");
PlayerListPacket playerRemovePacket = new PlayerListPacket();
playerRemovePacket.setType(PlayerListPacket.Type.REMOVE);
playerRemovePacket.getEntries().add(updatedEntry);
session.getUpstream().sendPacket(playerRemovePacket);
PlayerListPacket playerAddPacket = new PlayerListPacket();
playerAddPacket.setType(PlayerListPacket.Type.ADD);
playerAddPacket.getEntries().add(updatedEntry);
session.getUpstream().sendPacket(playerAddPacket);
}
}).isCompletedExceptionally();
});
} }
} }

View file

@ -1,8 +1,8 @@
package org.geysermc.connector.network.translators.java.world; package org.geysermc.connector.network.translators.java.world;
import com.flowpowered.math.vector.Vector3i;
import com.github.steveice10.mc.protocol.data.game.world.block.BlockChangeRecord; import com.github.steveice10.mc.protocol.data.game.world.block.BlockChangeRecord;
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerBlockChangePacket; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerBlockChangePacket;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.PacketTranslator;
@ -16,10 +16,11 @@ public class JavaBlockChangeTranslator extends PacketTranslator<ServerBlockChang
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
BlockChangeRecord record = packet.getRecord(); BlockChangeRecord record = packet.getRecord();
updateBlockPacket.setDataLayer(0); updateBlockPacket.setDataLayer(0);
updateBlockPacket.setBlockPosition(new Vector3i( updateBlockPacket.setBlockPosition(Vector3i.from(
record.getPosition().getX(), record.getPosition().getX(),
record.getPosition().getY(), record.getPosition().getY(),
record.getPosition().getZ())); record.getPosition().getZ()
));
BedrockItem bedrockItem = TranslatorsInit.getBlockTranslator().getBedrockBlock(record.getBlock()); BedrockItem bedrockItem = TranslatorsInit.getBlockTranslator().getBedrockBlock(record.getBlock());
updateBlockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(bedrockItem.hashCode())); updateBlockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(bedrockItem.hashCode()));

View file

@ -1,8 +1,8 @@
package org.geysermc.connector.network.translators.java.world; package org.geysermc.connector.network.translators.java.world;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket;
import com.nukkitx.math.vector.Vector2i;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.network.VarInts; import com.nukkitx.network.VarInts;
import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket;
import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket;

View file

@ -25,9 +25,9 @@
package org.geysermc.connector.network.translators.java.world; package org.geysermc.connector.network.translators.java.world;
import com.flowpowered.math.vector.Vector3i;
import com.github.steveice10.mc.protocol.data.game.world.block.BlockChangeRecord; import com.github.steveice10.mc.protocol.data.game.world.block.BlockChangeRecord;
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerMultiBlockChangePacket; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerMultiBlockChangePacket;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.PacketTranslator;
@ -42,10 +42,11 @@ public class JavaMultiBlockChangeTranslator extends PacketTranslator<ServerMulti
for (BlockChangeRecord record : packet.getRecords()) { for (BlockChangeRecord record : packet.getRecords()) {
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
updateBlockPacket.setDataLayer(0); updateBlockPacket.setDataLayer(0);
updateBlockPacket.setBlockPosition(new Vector3i( updateBlockPacket.setBlockPosition(Vector3i.from(
record.getPosition().getX(), record.getPosition().getX(),
record.getPosition().getY(), record.getPosition().getY(),
record.getPosition().getZ())); record.getPosition().getZ()
));
BedrockItem bedrockItem = TranslatorsInit.getBlockTranslator().getBedrockBlock(record.getBlock()); BedrockItem bedrockItem = TranslatorsInit.getBlockTranslator().getBedrockBlock(record.getBlock());
updateBlockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(bedrockItem.hashCode())); updateBlockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(bedrockItem.hashCode()));

View file

@ -25,9 +25,9 @@
package org.geysermc.connector.network.translators.java.world; package org.geysermc.connector.network.translators.java.world;
import com.flowpowered.math.vector.Vector3f;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerNotifyClientPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerNotifyClientPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
import com.nukkitx.protocol.bedrock.packet.SetPlayerGameTypePacket; import com.nukkitx.protocol.bedrock.packet.SetPlayerGameTypePacket;
import com.nukkitx.protocol.bedrock.packet.ShowCreditsPacket; import com.nukkitx.protocol.bedrock.packet.ShowCreditsPacket;
@ -46,14 +46,14 @@ public class JavaNotifyClientTranslator extends PacketTranslator<ServerNotifyCli
LevelEventPacket startRainPacket = new LevelEventPacket(); LevelEventPacket startRainPacket = new LevelEventPacket();
startRainPacket.setEvent(LevelEventPacket.Event.START_RAIN); startRainPacket.setEvent(LevelEventPacket.Event.START_RAIN);
startRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000); startRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000);
startRainPacket.setPosition(new Vector3f(0, 0, 0)); startRainPacket.setPosition(Vector3f.ZERO);
session.getUpstream().sendPacket(startRainPacket); session.getUpstream().sendPacket(startRainPacket);
break; break;
case STOP_RAIN: case STOP_RAIN:
LevelEventPacket stopRainPacket = new LevelEventPacket(); LevelEventPacket stopRainPacket = new LevelEventPacket();
stopRainPacket.setEvent(LevelEventPacket.Event.STOP_RAIN); stopRainPacket.setEvent(LevelEventPacket.Event.STOP_RAIN);
stopRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000); stopRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000);
stopRainPacket.setPosition(new Vector3f(0, 0, 0)); stopRainPacket.setPosition(Vector3f.ZERO);
session.getUpstream().sendPacket(stopRainPacket); session.getUpstream().sendPacket(stopRainPacket);
break; break;
case CHANGE_GAMEMODE: case CHANGE_GAMEMODE:

View file

@ -25,8 +25,8 @@
package org.geysermc.connector.network.translators.java.world; package org.geysermc.connector.network.translators.java.world;
import com.flowpowered.math.vector.Vector3i;
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerSpawnPositionPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerSpawnPositionPacket;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.packet.SetSpawnPositionPacket; import com.nukkitx.protocol.bedrock.packet.SetSpawnPositionPacket;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.PacketTranslator;
@ -36,7 +36,7 @@ public class JavaSpawnPositionTranslator extends PacketTranslator<ServerSpawnPos
@Override @Override
public void translate(ServerSpawnPositionPacket packet, GeyserSession session) { public void translate(ServerSpawnPositionPacket packet, GeyserSession session) {
SetSpawnPositionPacket spawnPositionPacket = new SetSpawnPositionPacket(); SetSpawnPositionPacket spawnPositionPacket = new SetSpawnPositionPacket();
spawnPositionPacket.setBlockPosition(new Vector3i(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ())); spawnPositionPacket.setBlockPosition(Vector3i.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()));
spawnPositionPacket.setSpawnForced(true); spawnPositionPacket.setSpawnForced(true);
spawnPositionPacket.setSpawnType(SetSpawnPositionPacket.Type.PLAYER_SPAWN); spawnPositionPacket.setSpawnType(SetSpawnPositionPacket.Type.PLAYER_SPAWN);
session.getUpstream().sendPacket(spawnPositionPacket); session.getUpstream().sendPacket(spawnPositionPacket);

View file

@ -1,8 +1,8 @@
package org.geysermc.connector.utils; package org.geysermc.connector.utils;
import com.flowpowered.math.vector.Vector2i; import com.nukkitx.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3d; import com.nukkitx.math.vector.Vector3d;
import com.flowpowered.math.vector.Vector3i; import com.nukkitx.math.vector.Vector3i;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.DecoderException; import io.netty.handler.codec.DecoderException;
@ -13,43 +13,28 @@ import java.util.UUID;
import java.util.function.*; import java.util.function.*;
public class GeyserUtils { public class GeyserUtils {
public static final int FLAG_RUNTIME = 1; public static final int FLAG_RUNTIME = 1;
public static final int GLOBAL_PALETTE_BITS_PER_BLOCK = 14; public static final int GLOBAL_PALETTE_BITS_PER_BLOCK = 14;
public static final int SECTION_COUNT_BLOCKS = 16; public static final int SECTION_COUNT_BLOCKS = 16;
public static final int SECTION_COUNT_LIGHT = 18; public static final int SECTION_COUNT_LIGHT = 18;
public static final int BLOCKS_IN_SECTION = 16 * 16 * 16; public static final int BLOCKS_IN_SECTION = 16 * 16 * 16;
public static final int LIGHT_DATA_LENGTH = BLOCKS_IN_SECTION / 2; public static final int LIGHT_DATA_LENGTH = BLOCKS_IN_SECTION / 2;
public static final int EMPTY_SUBCHUNK_BYTES = BLOCKS_IN_SECTION / 8; public static final int EMPTY_SUBCHUNK_BYTES = BLOCKS_IN_SECTION / 8;
public static final int SUBCHUNK_VERSION = 8; public static final int SUBCHUNK_VERSION = 8;
public static void writeEmpty(ByteBuf to) { public static void writeEmpty(ByteBuf to) {
to.writeByte(storageHeader(1)); to.writeByte(storageHeader(1));
to.writeZero(EMPTY_SUBCHUNK_BYTES); to.writeZero(EMPTY_SUBCHUNK_BYTES);
} }
protected static final int storageHeader(int bitsPerBlock) { protected static final int storageHeader(int bitsPerBlock) {
return (bitsPerBlock << 1) | FLAG_RUNTIME; return (bitsPerBlock << 1) | FLAG_RUNTIME;
} }
public static void writeEmptySubChunk(ByteBuf out) { public static void writeEmptySubChunk(ByteBuf out) {
out.writeBytes(new byte[4096 + 4096]); out.writeBytes(new byte[4096 + 4096]);
} }
public static void skipPosition(ByteBuf from) { public static void skipPosition(ByteBuf from) {
@ -58,7 +43,7 @@ public class GeyserUtils {
public static Vector3d readPosition(ByteBuf from) { public static Vector3d readPosition(ByteBuf from) {
long l = from.readLong(); long l = from.readLong();
return new Vector3d( return Vector3d.from(
(int) (l >> 38), (int) (l & 0xFFF), (int) ((l << 26) >> 38) (int) (l >> 38), (int) (l & 0xFFF), (int) ((l << 26) >> 38)
); );
} }
@ -70,7 +55,7 @@ public class GeyserUtils {
} }
public static Vector3d readLegacyPositionI(ByteBuf from) { public static Vector3d readLegacyPositionI(ByteBuf from) {
return new Vector3d(from.readInt(), from.readInt(), from.readInt()); return Vector3d.from(from.readInt(), from.readInt(), from.readInt());
} }
public static void writePosition(ByteBuf to, Vector3i position) { public static void writePosition(ByteBuf to, Vector3i position) {
@ -106,11 +91,11 @@ public class GeyserUtils {
} }
public static Vector2i readIntChunkCoord(ByteBuf from) { public static Vector2i readIntChunkCoord(ByteBuf from) {
return new Vector2i(from.readInt(), from.readInt()); return Vector2i.from(from.readInt(), from.readInt());
} }
public static Vector2i readVarIntChunkCoord(ByteBuf from) { public static Vector2i readVarIntChunkCoord(ByteBuf from) {
return new Vector2i(readVarInt(from), readVarInt(from)); return Vector2i.from(readVarInt(from), readVarInt(from));
} }
public static void writeIntChunkCoord(ByteBuf to, Vector2i chunk) { public static void writeIntChunkCoord(ByteBuf to, Vector2i chunk) {
@ -119,7 +104,7 @@ public class GeyserUtils {
} }
public static Vector2i readPEChunkCoord(ByteBuf from) { public static Vector2i readPEChunkCoord(ByteBuf from) {
return new Vector2i(readSVarInt(from), readSVarInt(from)); return Vector2i.from(readSVarInt(from), readSVarInt(from));
} }
public static void writePEChunkCoord(ByteBuf to, Vector2i chunk) { public static void writePEChunkCoord(ByteBuf to, Vector2i chunk) {
@ -140,513 +125,269 @@ public class GeyserUtils {
writeVarInt(to, chunk.getY()); writeVarInt(to, chunk.getY());
} }
public static final int MAX_VARINT_LENGTH = 5;
public static final int MAX_LENGTH = 5;
public static void writeFixedSizeVarInt(ByteBuf to, int i) { public static void writeFixedSizeVarInt(ByteBuf to, int i) {
int writerIndex = to.writerIndex(); int writerIndex = to.writerIndex();
while ((i & 0xFFFFFF80) != 0x0) { while ((i & 0xFFFFFF80) != 0x0) {
to.writeByte(i | 0x80); to.writeByte(i | 0x80);
i >>>= 7; i >>>= 7;
} }
int paddingBytes = MAX_VARINT_LENGTH - (to.writerIndex() - writerIndex) - 1;
int paddingBytes = MAX_LENGTH - (to.writerIndex() - writerIndex) - 1;
if (paddingBytes == 0) { if (paddingBytes == 0) {
to.writeByte(i); to.writeByte(i);
} else { } else {
to.writeByte(i | 0x80); to.writeByte(i | 0x80);
while (--paddingBytes > 0) { while (--paddingBytes > 0) {
to.writeByte(0x80); to.writeByte(0x80);
} }
to.writeByte(0); to.writeByte(0);
} }
} }
public static int readVarInt(ByteBuf from) { public static int readVarInt(ByteBuf from) {
int value = 0; int value = 0;
int length = 0; int length = 0;
byte part; byte part;
do { do {
part = from.readByte(); part = from.readByte();
value |= (part & 0x7F) << (length++ * 7); value |= (part & 0x7F) << (length++ * 7);
if (length > MAX_VARINT_LENGTH) {
if (length > MAX_LENGTH) {
throw new DecoderException("VarInt too big"); throw new DecoderException("VarInt too big");
} }
} while (part < 0); } while (part < 0);
return value; return value;
} }
public static void writeVarInt(ByteBuf to, int i) { public static void writeVarInt(ByteBuf to, int i) {
while ((i & 0xFFFFFF80) != 0x0) { while ((i & 0xFFFFFF80) != 0x0) {
to.writeByte(i | 0x80); to.writeByte(i | 0x80);
i >>>= 7; i >>>= 7;
} }
to.writeByte(i); to.writeByte(i);
} }
public static int readSVarInt(ByteBuf from) { public static int readSVarInt(ByteBuf from) {
int varint = readVarInt(from); int varint = readVarInt(from);
return (varint >> 1) ^ -(varint & 1); return (varint >> 1) ^ -(varint & 1);
} }
public static void writeSVarInt(ByteBuf to, int varint) { public static void writeSVarInt(ByteBuf to, int varint) {
writeVarInt(to, (varint << 1) ^ (varint >> 31)); writeVarInt(to, (varint << 1) ^ (varint >> 31));
} }
public static long readVarLong(ByteBuf from) { public static long readVarLong(ByteBuf from) {
long varlong = 0L; long varlong = 0L;
int length = 0; int length = 0;
byte part; byte part;
do { do {
part = from.readByte(); part = from.readByte();
varlong |= (part & 0x7F) << (length++ * 7); varlong |= (part & 0x7F) << (length++ * 7);
if (length > 10) { if (length > 10) {
throw new RuntimeException("VarLong too big"); throw new RuntimeException("VarLong too big");
} }
} while ((part & 0x80) == 0x80); } while ((part & 0x80) == 0x80);
return varlong; return varlong;
} }
public static void writeVarLong(ByteBuf to, long varlong) { public static void writeVarLong(ByteBuf to, long varlong) {
while ((varlong & 0xFFFFFFFFFFFFFF80L) != 0x0L) { while ((varlong & 0xFFFFFFFFFFFFFF80L) != 0x0L) {
to.writeByte((int) (varlong & 0x7FL) | 0x80); to.writeByte((int) (varlong & 0x7FL) | 0x80);
varlong >>>= 7; varlong >>>= 7;
} }
to.writeByte((int) varlong); to.writeByte((int) varlong);
} }
public static long readSVarLong(ByteBuf from) { public static long readSVarLong(ByteBuf from) {
long varlong = readVarLong(from); long varlong = readVarLong(from);
return (varlong >> 1) ^ -(varlong & 1); return (varlong >> 1) ^ -(varlong & 1);
} }
public static void writeSVarLong(ByteBuf to, long varlong) { public static void writeSVarLong(ByteBuf to, long varlong) {
writeVarLong(to, (varlong << 1) ^ (varlong >> 63)); writeVarLong(to, (varlong << 1) ^ (varlong >> 63));
} }
public static ByteBuf readShortByteArraySlice(ByteBuf from, int limit) { public static ByteBuf readShortByteArraySlice(ByteBuf from, int limit) {
int length = from.readShort(); int length = from.readShort();
checkLimit(length, limit); checkLimit(length, limit);
return from.readSlice(length); return from.readSlice(length);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T[] readShortTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) { public static <T> T[] readShortTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) {
T[] array = (T[]) Array.newInstance(tclass, from.readShort()); T[] array = (T[]) Array.newInstance(tclass, from.readShort());
for (int i = 0; i < array.length; i++) { for (int i = 0; i < array.length; i++) {
array[i] = elementReader.apply(from); array[i] = elementReader.apply(from);
} }
return array; return array;
} }
public static byte[] readVarIntByteArray(ByteBuf from) { public static byte[] readVarIntByteArray(ByteBuf from) {
return readBytes(from, readVarInt(from)); return readBytes(from, readVarInt(from));
} }
public static ByteBuf readVarIntByteArraySlice(ByteBuf from, int limit) { public static ByteBuf readVarIntByteArraySlice(ByteBuf from, int limit) {
int length = readVarInt(from); int length = readVarInt(from);
checkLimit(length, limit); checkLimit(length, limit);
return from.readSlice(length); return from.readSlice(length);
} }
public static ByteBuf readVarIntByteArraySlice(ByteBuf from) { public static ByteBuf readVarIntByteArraySlice(ByteBuf from) {
return from.readSlice(readVarInt(from)); return from.readSlice(readVarInt(from));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T[] readVarIntTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) { public static <T> T[] readVarIntTArray(ByteBuf from, Class<T> tclass, Function<ByteBuf, T> elementReader) {
T[] array = (T[]) Array.newInstance(tclass, readVarInt(from)); T[] array = (T[]) Array.newInstance(tclass, readVarInt(from));
for (int i = 0; i < array.length; i++) { for (int i = 0; i < array.length; i++) {
array[i] = elementReader.apply(from); array[i] = elementReader.apply(from);
} }
return array; return array;
} }
public static int[] readVarIntVarIntArray(ByteBuf from) { public static int[] readVarIntVarIntArray(ByteBuf from) {
int[] array = new int[readVarInt(from)]; int[] array = new int[readVarInt(from)];
for (int i = 0; i < array.length; i++) { for (int i = 0; i < array.length; i++) {
array[i] = readVarInt(from); array[i] = readVarInt(from);
} }
return array; return array;
} }
public static void writeShortByteArray(ByteBuf to, ByteBuf data) { public static void writeShortByteArray(ByteBuf to, ByteBuf data) {
to.writeShort(data.readableBytes()); to.writeShort(data.readableBytes());
to.writeBytes(data); to.writeBytes(data);
} }
public static void writeShortByteArray(ByteBuf to, byte[] data) { public static void writeShortByteArray(ByteBuf to, byte[] data) {
to.writeShort(data.length); to.writeShort(data.length);
to.writeBytes(data); to.writeBytes(data);
} }
public static void writeShortByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) { public static void writeShortByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) {
writeLengthPrefixedBytes(to, ByteBuf::writeShort, dataWriter);
writeLengthPrefixedBytes(to, (lTo, length) -> lTo.writeShort(length), dataWriter);
} }
public static <T> void writeShortTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) { public static <T> void writeShortTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) {
to.writeShort(array.length); to.writeShort(array.length);
for (T element : array) { for (T element : array) {
elementWriter.accept(to, element); elementWriter.accept(to, element);
} }
} }
public static void writeVarIntByteArray(ByteBuf to, ByteBuf data) { public static void writeVarIntByteArray(ByteBuf to, ByteBuf data) {
writeVarInt(to, data.readableBytes()); writeVarInt(to, data.readableBytes());
to.writeBytes(data); to.writeBytes(data);
} }
public static void writeVarIntByteArray(ByteBuf to, byte[] data) { public static void writeVarIntByteArray(ByteBuf to, byte[] data) {
writeVarInt(to, data.length); writeVarInt(to, data.length);
to.writeBytes(data); to.writeBytes(data);
} }
public static void writeVarIntByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) { public static void writeVarIntByteArray(ByteBuf to, Consumer<ByteBuf> dataWriter) {
writeLengthPrefixedBytes(to, GeyserUtils::writeFixedSizeVarInt, dataWriter); writeLengthPrefixedBytes(to, GeyserUtils::writeFixedSizeVarInt, dataWriter);
} }
public static void writeVarIntTArray(ByteBuf to, ToIntFunction<ByteBuf> arrayWriter) { public static void writeVarIntTArray(ByteBuf to, ToIntFunction<ByteBuf> arrayWriter) {
writeSizePrefixedData(to, GeyserUtils::writeFixedSizeVarInt, arrayWriter); writeSizePrefixedData(to, GeyserUtils::writeFixedSizeVarInt, arrayWriter);
} }
public static <T> void writeVarIntTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) { public static <T> void writeVarIntTArray(ByteBuf to, T[] array, BiConsumer<ByteBuf, T> elementWriter) {
writeVarInt(to, array.length); writeVarInt(to, array.length);
for (T element : array) { for (T element : array) {
elementWriter.accept(to, element); elementWriter.accept(to, element);
} }
} }
public static <T> void writeVarIntTArray(ByteBuf to, List<T> array, BiConsumer<ByteBuf, T> elementWriter) { public static <T> void writeVarIntTArray(ByteBuf to, List<T> array, BiConsumer<ByteBuf, T> elementWriter) {
writeVarInt(to, array.size()); writeVarInt(to, array.size());
for (T element : array) { for (T element : array) {
elementWriter.accept(to, element); elementWriter.accept(to, element);
} }
} }
public static void writeVarIntEnum(ByteBuf to, Enum<?> e) { public static void writeVarIntEnum(ByteBuf to, Enum<?> e) {
writeVarInt(to, e.ordinal()); writeVarInt(to, e.ordinal());
} }
public static void writeByteEnum(ByteBuf to, Enum<?> e) { public static void writeByteEnum(ByteBuf to, Enum<?> e) {
to.writeByte(e.ordinal()); to.writeByte(e.ordinal());
} }
public static UUID readUUID(ByteBuf from) { public static UUID readUUID(ByteBuf from) {
return new UUID(from.readLong(), from.readLong()); return new UUID(from.readLong(), from.readLong());
} }
public static void writeUUID(ByteBuf to, UUID uuid) { public static void writeUUID(ByteBuf to, UUID uuid) {
to.writeLong(uuid.getMostSignificantBits()); to.writeLong(uuid.getMostSignificantBits());
to.writeLong(uuid.getLeastSignificantBits()); to.writeLong(uuid.getLeastSignificantBits());
} }
public static void writePEUUID(ByteBuf to, UUID uuid) { public static void writePEUUID(ByteBuf to, UUID uuid) {
to.writeLongLE(uuid.getMostSignificantBits()); to.writeLongLE(uuid.getMostSignificantBits());
to.writeLongLE(uuid.getLeastSignificantBits()); to.writeLongLE(uuid.getLeastSignificantBits());
} }
public static byte[] readAllBytes(ByteBuf buf) { public static byte[] readAllBytes(ByteBuf buf) {
return readBytes(buf, buf.readableBytes()); return readBytes(buf, buf.readableBytes());
} }
public static ByteBuf readAllBytesSlice(ByteBuf from) { public static ByteBuf readAllBytesSlice(ByteBuf from) {
return from.readSlice(from.readableBytes()); return from.readSlice(from.readableBytes());
} }
public static ByteBuf readAllBytesSlice(ByteBuf buf, int limit) { public static ByteBuf readAllBytesSlice(ByteBuf buf, int limit) {
checkLimit(buf.readableBytes(), limit); checkLimit(buf.readableBytes(), limit);
return readAllBytesSlice(buf); return readAllBytesSlice(buf);
} }
public static byte[] readBytes(ByteBuf buf, int length) { public static byte[] readBytes(ByteBuf buf, int length) {
byte[] result = new byte[length]; byte[] result = new byte[length];
buf.readBytes(result); buf.readBytes(result);
return result; return result;
} }
protected static void checkLimit(int length, int limit) { protected static void checkLimit(int length, int limit) {
if (length > limit) { if (length > limit) {
throw new DecoderException(MessageFormat.format("Size {0} is bigger than allowed {1}", length, limit)); throw new DecoderException(MessageFormat.format("Size {0} is bigger than allowed {1}", length, limit));
} }
} }
public static void writeLengthPrefixedBytes(ByteBuf to, ObjIntConsumer<ByteBuf> lengthWriter, Consumer<ByteBuf> dataWriter) { public static void writeLengthPrefixedBytes(ByteBuf to, ObjIntConsumer<ByteBuf> lengthWriter, Consumer<ByteBuf> dataWriter) {
int lengthWriterIndex = to.writerIndex(); int lengthWriterIndex = to.writerIndex();
lengthWriter.accept(to, 0); lengthWriter.accept(to, 0);
int writerIndexDataStart = to.writerIndex(); int writerIndexDataStart = to.writerIndex();
dataWriter.accept(to); dataWriter.accept(to);
int writerIndexDataEnd = to.writerIndex(); int writerIndexDataEnd = to.writerIndex();
to.writerIndex(lengthWriterIndex); to.writerIndex(lengthWriterIndex);
lengthWriter.accept(to, writerIndexDataEnd - writerIndexDataStart); lengthWriter.accept(to, writerIndexDataEnd - writerIndexDataStart);
to.writerIndex(writerIndexDataEnd); to.writerIndex(writerIndexDataEnd);
} }
public static void writeSizePrefixedData(ByteBuf to, ObjIntConsumer<ByteBuf> sizeWriter, ToIntFunction<ByteBuf> dataWriter) { public static void writeSizePrefixedData(ByteBuf to, ObjIntConsumer<ByteBuf> sizeWriter, ToIntFunction<ByteBuf> dataWriter) {
int sizeWriterIndex = to.writerIndex(); int sizeWriterIndex = to.writerIndex();
sizeWriter.accept(to, 0); sizeWriter.accept(to, 0);
int size = dataWriter.applyAsInt(to); int size = dataWriter.applyAsInt(to);
int writerIndexDataEnd = to.writerIndex(); int writerIndexDataEnd = to.writerIndex();
to.writerIndex(sizeWriterIndex); to.writerIndex(sizeWriterIndex);
sizeWriter.accept(to, size); sizeWriter.accept(to, size);
to.writerIndex(writerIndexDataEnd); to.writerIndex(writerIndexDataEnd);
} }
private static int getAnvilIndex(int x, int y, int z) { private static int getAnvilIndex(int x, int y, int z) {
return (y << 8) + (z << 4) + x; return (y << 8) + (z << 4) + x;
} }
public static <T> boolean instanceOf(Class<T> clazz, Object o) { public static <T> boolean instanceOf(Class<T> clazz, Object o) {
@ -657,6 +398,4 @@ public class GeyserUtils {
return false; return false;
} }
} }
} }

View file

@ -49,13 +49,13 @@ public class SkinProvider {
return cachedCapes.get(capeUrl); return cachedCapes.get(capeUrl);
} }
public static CompletableFuture<SkinAndCape> requestAndHandleSkinAndCape(UUID playerId, String skinUrl, String capeUrl) { public static CompletableFuture<SkinAndCape> requestSkinAndCape(UUID playerId, String skinUrl, String capeUrl) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
SkinAndCape skinAndCape = new SkinAndCape( SkinAndCape skinAndCape = new SkinAndCape(
getOrDefault(requestAndHandleSkin(playerId, skinUrl, false), EMPTY_SKIN, 5), getOrDefault(requestSkin(playerId, skinUrl, false), EMPTY_SKIN, 5),
getOrDefault(requestAndHandleCape(capeUrl, false), EMPTY_CAPE, 5) getOrDefault(requestCape(capeUrl, false), EMPTY_CAPE, 5)
); );
Geyser.getLogger().debug("Took " + (System.currentTimeMillis() - time) + "ms for " + playerId); Geyser.getLogger().debug("Took " + (System.currentTimeMillis() - time) + "ms for " + playerId);
@ -63,7 +63,7 @@ public class SkinProvider {
}, EXECUTOR_SERVICE); }, EXECUTOR_SERVICE);
} }
public static CompletableFuture<Skin> requestAndHandleSkin(UUID playerId, String textureUrl, boolean newThread) { public static CompletableFuture<Skin> requestSkin(UUID playerId, String textureUrl, boolean newThread) {
if (textureUrl == null || textureUrl.isEmpty()) return CompletableFuture.completedFuture(EMPTY_SKIN); if (textureUrl == null || textureUrl.isEmpty()) return CompletableFuture.completedFuture(EMPTY_SKIN);
if (requestedSkins.containsKey(playerId)) return requestedSkins.get(playerId); // already requested if (requestedSkins.containsKey(playerId)) return requestedSkins.get(playerId); // already requested
@ -91,7 +91,7 @@ public class SkinProvider {
return future; return future;
} }
public static CompletableFuture<Cape> requestAndHandleCape(String capeUrl, boolean newThread) { public static CompletableFuture<Cape> requestCape(String capeUrl, boolean newThread) {
if (capeUrl == null || capeUrl.isEmpty()) return CompletableFuture.completedFuture(EMPTY_CAPE); if (capeUrl == null || capeUrl.isEmpty()) return CompletableFuture.completedFuture(EMPTY_CAPE);
if (requestedCapes.containsKey(capeUrl)) return requestedCapes.get(capeUrl); // already requested if (requestedCapes.containsKey(capeUrl)) return requestedCapes.get(capeUrl); // already requested
@ -119,12 +119,12 @@ public class SkinProvider {
return future; return future;
} }
public static CompletableFuture<Cape> requestAndHandleUnofficialCape(Cape officialCape, UUID playerId, public static CompletableFuture<Cape> requestUnofficialCape(Cape officialCape, UUID playerId,
String username, boolean newThread) { String username, boolean newThread) {
if (officialCape.isFailed() && ALLOW_THIRD_PARTY_CAPES) { if (officialCape.isFailed() && ALLOW_THIRD_PARTY_CAPES) {
for (UnofficalCape cape : UnofficalCape.VALUES) { for (UnofficalCape cape : UnofficalCape.VALUES) {
Cape cape1 = getOrDefault( Cape cape1 = getOrDefault(
requestAndHandleCape(cape.getUrlFor(playerId, username), newThread), requestCape(cape.getUrlFor(playerId, username), newThread),
EMPTY_CAPE, 4 EMPTY_CAPE, 4
); );
if (!cape1.isFailed()) { if (!cape1.isFailed()) {

View file

@ -0,0 +1,142 @@
package org.geysermc.connector.utils;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.google.gson.JsonObject;
import com.nukkitx.protocol.bedrock.packet.PlayerListPacket;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.codec.Charsets;
import org.geysermc.api.Geyser;
import org.geysermc.connector.entity.PlayerEntity;
import org.geysermc.connector.network.session.GeyserSession;
import java.util.Base64;
import java.util.UUID;
import java.util.function.Consumer;
public class SkinUtils {
public static PlayerListPacket.Entry buildCachedEntry(GameProfile profile, long geyserId) {
GameProfileData data = GameProfileData.from(profile);
return buildEntryManually(
profile.getId(),
profile.getName(),
geyserId,
profile.getIdAsString(),
SkinProvider.getCachedSkin(profile.getId()).getSkinData(),
SkinProvider.getCachedCape(data.getCapeUrl()).getCapeData(),
"geometry.humanoid.custom" + (data.isAlex() ? "Slim" : ""),
""
);
}
public static PlayerListPacket.Entry buildDefaultEntry(GameProfile profile, long geyserId) {
return buildEntryManually(
profile.getId(),
profile.getName(),
geyserId,
profile.getIdAsString(),
SkinProvider.STEVE_SKIN,
SkinProvider.EMPTY_CAPE.getCapeData(),
"geometry.humanoid",
""
);
}
public static PlayerListPacket.Entry buildEntryManually(UUID uuid, String username, long geyserId,
String skinId, byte[] skinData, byte[] capeData,
String geometryName, String geometryData) {
PlayerListPacket.Entry entry = new PlayerListPacket.Entry(uuid);
entry.setName(username);
entry.setEntityId(geyserId);
entry.setSkinId(skinId);
entry.setSkinData(skinData != null ? skinData : SkinProvider.STEVE_SKIN);
entry.setCapeData(capeData);
entry.setGeometryName(geometryName);
entry.setGeometryData(geometryData);
entry.setXuid("");
entry.setPlatformChatId("");
return entry;
}
@AllArgsConstructor
@Getter
public static class GameProfileData {
private String skinUrl;
private String capeUrl;
private boolean alex;
public static GameProfileData from(GameProfile profile) {
GameProfile.Property skinProperty = profile.getProperty("textures");
JsonObject skinObject = SkinProvider.GSON.fromJson(new String(Base64.getDecoder().decode(skinProperty.getValue()), Charsets.UTF_8), JsonObject.class);
JsonObject textures = skinObject.getAsJsonObject("textures");
JsonObject skinTexture = textures.getAsJsonObject("SKIN");
String skinUrl = skinTexture.get("url").getAsString();
boolean isAlex = skinTexture.has("metadata");
String capeUrl = null;
if (textures.has("CAPE")) {
JsonObject capeTexture = textures.getAsJsonObject("CAPE");
capeUrl = capeTexture.get("url").getAsString();
}
return new GameProfileData(skinUrl, capeUrl, isAlex);
}
}
public static void requestAndHandleSkinAndCape(PlayerEntity entity, GeyserSession session,
Consumer<SkinProvider.SkinAndCape> skinAndCapeConsumer) {
Geyser.getGeneralThreadPool().execute(() -> {
SkinUtils.GameProfileData data = SkinUtils.GameProfileData.from(entity.getProfile());
SkinProvider.requestSkinAndCape(entity.getUuid(), data.getSkinUrl(), data.getCapeUrl())
.whenCompleteAsync((skinAndCape, throwable) -> {
try {
SkinProvider.Skin skin = skinAndCape.getSkin();
SkinProvider.Cape cape = skinAndCape.getCape();
if (cape.isFailed() && SkinProvider.ALLOW_THIRD_PARTY_CAPES) {
cape = SkinProvider.getOrDefault(SkinProvider.requestUnofficialCape(
cape, entity.getUuid(),
entity.getUsername(), false
), SkinProvider.EMPTY_CAPE, SkinProvider.UnofficalCape.VALUES.length * 3);
}
if (entity.getLastSkinUpdate() < skin.getRequestedOn()) {
entity.setLastSkinUpdate(skin.getRequestedOn());
if (session.getUpstream().isInitialized()) {
PlayerListPacket.Entry updatedEntry = SkinUtils.buildEntryManually(
entity.getUuid(),
entity.getUsername(),
entity.getGeyserId(),
entity.getUuid().toString(),
skin.getSkinData(),
cape.getCapeData(),
"geometry.humanoid.custom" + (data.isAlex() ? "Slim" : ""),
""
);
PlayerListPacket playerRemovePacket = new PlayerListPacket();
playerRemovePacket.setType(PlayerListPacket.Type.REMOVE);
playerRemovePacket.getEntries().add(updatedEntry);
session.getUpstream().sendPacket(playerRemovePacket);
PlayerListPacket playerAddPacket = new PlayerListPacket();
playerAddPacket.setType(PlayerListPacket.Type.ADD);
playerAddPacket.getEntries().add(updatedEntry);
session.getUpstream().sendPacket(playerAddPacket);
}
}
} catch (Exception e) {
Geyser.getLogger().error("Failed getting skin for " + entity.getUuid(), e);
}
if (skinAndCapeConsumer != null) skinAndCapeConsumer.accept(skinAndCape);
});
});
}
}