update geyser

This commit is contained in:
zimzaza4
2024-05-24 23:46:16 +08:00
parent a44cea571e
commit e5fa64e950
2 changed files with 51 additions and 30 deletions

Binary file not shown.

View File

@@ -1,11 +1,5 @@
package me.zimzaza4.geyserutils.geyser; package me.zimzaza4.geyserutils.geyser;
import org.geysermc.mcprotocollib.network.packet.Packet;
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket;
import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket;
import org.geysermc.mcprotocollib.network.Session;
import org.geysermc.mcprotocollib.network.event.session.PacketSendingEvent;
import org.geysermc.mcprotocollib.network.event.session.SessionAdapter;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
@@ -13,6 +7,7 @@ import com.google.gson.Gson;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import it.unimi.dsi.fastutil.bytes.ByteArrays;
import lombok.Getter; import lombok.Getter;
import me.zimzaza4.geyserutils.common.camera.data.CameraPreset; import me.zimzaza4.geyserutils.common.camera.data.CameraPreset;
import me.zimzaza4.geyserutils.common.camera.instruction.ClearInstruction; import me.zimzaza4.geyserutils.common.camera.instruction.ClearInstruction;
@@ -47,13 +42,22 @@ import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCommandsEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineEntitiesEvent; import org.geysermc.geyser.api.event.lifecycle.GeyserDefineEntitiesEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserPostInitializeEvent; import org.geysermc.geyser.api.event.lifecycle.GeyserPostInitializeEvent;
import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.api.skin.Cape;
import org.geysermc.geyser.api.skin.Skin;
import org.geysermc.geyser.api.skin.SkinData;
import org.geysermc.geyser.api.skin.SkinGeometry;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.skin.SkinProvider; import org.geysermc.geyser.skin.SkinProvider;
import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.mcprotocollib.network.Session;
import org.geysermc.mcprotocollib.network.event.session.PacketSendingEvent; import org.geysermc.mcprotocollib.network.event.session.PacketSendingEvent;
import org.geysermc.mcprotocollib.network.event.session.SessionAdapter;
import org.geysermc.mcprotocollib.network.packet.Packet;
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket;
import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
@@ -74,7 +78,7 @@ public class GeyserUtils implements Extension {
public static PacketManager packetManager; public static PacketManager packetManager;
@Getter @Getter
public static Map<String, SkinProvider.SkinData> LOADED_SKIN_DATA = new HashMap<>(); public static Map<String, SkinData> LOADED_SKIN_DATA = new HashMap<>();
@Getter @Getter
public static Map<String, EntityDefinition> LOADED_ENTITY_DEFINITIONS = new HashMap<>(); public static Map<String, EntityDefinition> LOADED_ENTITY_DEFINITIONS = new HashMap<>();
@@ -85,15 +89,14 @@ public class GeyserUtils implements Extension {
@Getter @Getter
public static Map<GeyserConnection, EntityScoreboard> scoreboards = new ConcurrentHashMap<>(); public static Map<GeyserConnection, EntityScoreboard> scoreboards = new ConcurrentHashMap<>();
static SkinProvider.Cape EMPTY_CAPE = new SkinProvider.Cape("", "no-cape", new byte[0], -1, true); static Cape EMPTY_CAPE = new Cape("", "no-cape", ByteArrays.EMPTY_ARRAY, true);
;
public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2); public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
@Subscribe @Subscribe
public void onEnable(GeyserPostInitializeEvent event) { public void onEnable(GeyserPostInitializeEvent event) {
packetManager = new PacketManager();
Registries.BEDROCK_PACKET_TRANSLATORS.register(NpcRequestPacket.class, new NPCFormResponseTranslator()); Registries.BEDROCK_PACKET_TRANSLATORS.register(NpcRequestPacket.class, new NPCFormResponseTranslator());
loadSkins(); loadSkins();
@@ -118,6 +121,7 @@ public class GeyserUtils implements Extension {
public void loadEntities() { public void loadEntities() {
Gson gson = new Gson(); Gson gson = new Gson();
this.dataFolder().toFile().mkdirs();
File file = this.dataFolder().resolve("entities.json").toFile(); File file = this.dataFolder().resolve("entities.json").toFile();
if (!file.exists()) { if (!file.exists()) {
try { try {
@@ -194,7 +198,7 @@ public class GeyserUtils implements Extension {
public void loadSkin(String skinId, File geometryFile, File textureFile) { public void loadSkin(String skinId, File geometryFile, File textureFile) {
try { try {
SkinProvider.Skin skin = new SkinProvider.Skin(null, skinId, Files.readAllBytes(textureFile.toPath()), -1, false, false); Skin skin = new Skin(skinId, Files.readAllBytes(textureFile.toPath()), false);
String geoId = ""; String geoId = "";
JsonElement json = new JsonParser().parse(new FileReader(geometryFile)); JsonElement json = new JsonParser().parse(new FileReader(geometryFile));
@@ -205,8 +209,8 @@ public class GeyserUtils implements Extension {
} }
} }
String geoName = "{\"geometry\" :{\"default\" :\"" + geoId + "\"}}"; String geoName = "{\"geometry\" :{\"default\" :\"" + geoId + "\"}}";
SkinProvider.SkinGeometry geometry = new SkinProvider.SkinGeometry(geoName, Files.readString(geometryFile.toPath()), false); SkinGeometry geometry = new SkinGeometry(geoName, Files.readString(geometryFile.toPath()));
LOADED_SKIN_DATA.put(skinId, new SkinProvider.SkinData(skin, getEmptyCapeData(), geometry)); LOADED_SKIN_DATA.put(skinId, new SkinData(skin, getEmptyCapeData(), geometry));
this.logger().info("Loaded skin: " + skinId + "| geo:" + geoName); this.logger().info("Loaded skin: " + skinId + "| geo:" + geoName);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -338,7 +342,7 @@ public class GeyserUtils implements Extension {
session.sendUpstreamPacket(spawnParticleEffectPacket); session.sendUpstreamPacket(spawnParticleEffectPacket);
} else if (customPacket instanceof CustomSkinPayloadPacket customSkinPayloadPacket) { } else if (customPacket instanceof CustomSkinPayloadPacket customSkinPayloadPacket) {
if (session.getEntityCache().getEntityByJavaId(customSkinPayloadPacket.getEntityId()) instanceof PlayerEntity player) { if (session.getEntityCache().getEntityByJavaId(customSkinPayloadPacket.getEntityId()) instanceof PlayerEntity player) {
SkinProvider.SkinData data = LOADED_SKIN_DATA.get(customSkinPayloadPacket.getSkinId()); SkinData data = LOADED_SKIN_DATA.get(customSkinPayloadPacket.getSkinId());
if (data != null) { if (data != null) {
sendSkinPacket(session, player, data); sendSkinPacket(session, player, data);
} }
@@ -394,12 +398,23 @@ public class GeyserUtils implements Extension {
return animateEntityPacket; return animateEntityPacket;
} }
public static void sendSkinPacket(GeyserSession session, PlayerEntity entity, SkinProvider.SkinData skinData) { public static void sendSkinPacket(GeyserSession session, PlayerEntity entity, SkinData skinData) {
SkinProvider.Skin skin = skinData.skin(); Skin skin = skinData.skin();
SkinProvider.Cape cape = skinData.cape(); Cape cape = skinData.cape();
SkinProvider.SkinGeometry geometry = skinData.geometry(); SkinGeometry geometry = skinData.geometry();
if (entity.getUuid().equals(session.getPlayerEntity().getUuid())) { if (entity.getUuid().equals(session.getPlayerEntity().getUuid())) {
PlayerListPacket.Entry updatedEntry = buildEntryManually(session, entity.getUuid(), entity.getUsername(), entity.getGeyserId(), skin, cape, geometry); // TODO is this special behavior needed?
PlayerListPacket.Entry updatedEntry = buildEntryManually(
session,
entity.getUuid(),
entity.getUsername(),
entity.getGeyserId(),
skin,
cape,
geometry
);
PlayerListPacket playerAddPacket = new PlayerListPacket(); PlayerListPacket playerAddPacket = new PlayerListPacket();
playerAddPacket.setAction(PlayerListPacket.Action.ADD); playerAddPacket.setAction(PlayerListPacket.Action.ADD);
playerAddPacket.getEntries().add(updatedEntry); playerAddPacket.getEntries().add(updatedEntry);
@@ -408,25 +423,31 @@ public class GeyserUtils implements Extension {
PlayerSkinPacket packet = new PlayerSkinPacket(); PlayerSkinPacket packet = new PlayerSkinPacket();
packet.setUuid(entity.getUuid()); packet.setUuid(entity.getUuid());
packet.setOldSkinName(""); packet.setOldSkinName("");
String skinId = skin.getTextureUrl() + UUID.randomUUID().toString().replace("-", ""); packet.setNewSkinName(skin.textureUrl());
packet.setNewSkinName(skinId); packet.setSkin(getSkin(skin.textureUrl(), skin, cape, geometry));
packet.setSkin(getSkin(skinId, skin, cape, geometry));
packet.setTrustedSkin(true); packet.setTrustedSkin(true);
session.sendUpstreamPacket(packet); session.sendUpstreamPacket(packet);
} }
} }
public static PlayerListPacket.Entry buildEntryManually(GeyserSession session, UUID uuid, String username, long geyserId, SkinProvider.Skin skin, SkinProvider.Cape cape, SkinProvider.SkinGeometry geometry) { public static PlayerListPacket.Entry buildEntryManually(GeyserSession session, UUID uuid, String username, long geyserId,
SerializedSkin serializedSkin = getSkin(skin.getTextureUrl(), skin, cape, geometry); Skin skin,
Cape cape,
SkinGeometry geometry) {
SerializedSkin serializedSkin = getSkin(skin.textureUrl(), skin, cape, geometry);
// This attempts to find the XUID of the player so profile images show up for Xbox accounts
String xuid = ""; String xuid = "";
GeyserSession playerSession = GeyserImpl.getInstance().connectionByUuid(uuid); GeyserSession playerSession = GeyserImpl.getInstance().connectionByUuid(uuid);
if (playerSession != null) { if (playerSession != null) {
xuid = playerSession.getAuthData().xuid(); xuid = playerSession.getAuthData().xuid();
} }
PlayerListPacket.Entry entry; PlayerListPacket.Entry entry;
// If we are building a PlayerListEntry for our own session we use our AuthData UUID instead of the Java UUID
// as Bedrock expects to get back its own provided UUID
if (session.getPlayerEntity().getUuid().equals(uuid)) { if (session.getPlayerEntity().getUuid().equals(uuid)) {
entry = new PlayerListPacket.Entry(session.getAuthData().uuid()); entry = new PlayerListPacket.Entry(session.getAuthData().uuid());
} else { } else {
@@ -440,21 +461,21 @@ public class GeyserUtils implements Extension {
entry.setPlatformChatId(""); entry.setPlatformChatId("");
entry.setTeacher(false); entry.setTeacher(false);
entry.setTrustedSkin(true); entry.setTrustedSkin(true);
return entry; return entry;
} }
private static SerializedSkin getSkin(String skinId, SkinProvider.Skin skin, SkinProvider.Cape cape, SkinProvider.SkinGeometry geometry) {
private static SerializedSkin getSkin(String skinId, Skin skin, Cape cape, SkinGeometry geometry) {
try { try {
ImageData image = ImageData.from(ImageIO.read(new ByteArrayInputStream(skin.getSkinData()))); ImageData image = ImageData.from(ImageIO.read(new ByteArrayInputStream(skin.skinData())));
return SerializedSkin.of(skinId, "", geometry.geometryName(),image , Collections.emptyList(), ImageData.of(cape.capeData()), geometry.geometryData(), "", true, false, false, cape.capeId(), skinId); return SerializedSkin.of(skinId, "", geometry.geometryName(),image , Collections.emptyList(), ImageData.of(cape.capeData()), geometry.geometryData(), "", true, false, false, cape.capeId(), skinId);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public static SkinProvider.Cape getEmptyCapeData() { public static Cape getEmptyCapeData() {
return EMPTY_CAPE; return EMPTY_CAPE;
} }