9
0
mirror of https://github.com/GeyserExtensionists/GeyserUtils.git synced 2025-12-19 15:09:24 +00:00

custom skin

This commit is contained in:
zimzaza4
2024-03-23 14:57:48 +08:00
parent 4a605fda5c
commit 9a52185ab5
7 changed files with 221 additions and 45 deletions

79
bungee/pom.xml Normal file
View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>me.zimzaza4</groupId>
<artifactId>GeyserUtils</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>geyserutils-bungee</artifactId>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<defaultGoal>clean package</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<repositories>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.20-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.zimzaza4</groupId>
<artifactId>geyserutils-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,20 @@
package me.zimzaza4.geyserutils.bungee;
import me.zimzaza4.geyserutils.common.channel.GeyserUtilsChannels;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
public final class GeyserUtils extends Plugin {
@Override
public void onEnable() {
ProxyServer.getInstance()
.registerChannel(GeyserUtilsChannels.MAIN);
// Plugin startup logic
}
@Override
public void onDisable() {
// Plugin shutdown logic
}
}

View File

@@ -0,0 +1,3 @@
name: GeyserUtils
version: '${project.version}'
main: me.zimzaza4.geyserutils.bungee.GeyserUtils

View File

@@ -0,0 +1,14 @@
package me.zimzaza4.geyserutils.common.packet;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Setter
@Getter
public class CustomSkinPayloadPacket extends CustomPayloadPacket {
private int entityId;
private String skinId;
}

View File

@@ -5,6 +5,10 @@ import com.github.steveice10.mc.protocol.packet.common.serverbound.ServerboundCu
import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.Session;
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.google.gson.Gson;
import com.google.gson.JsonElement;
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;
@@ -22,26 +26,32 @@ import me.zimzaza4.geyserutils.geyser.form.NpcDialogueForms;
import me.zimzaza4.geyserutils.geyser.form.element.Button; import me.zimzaza4.geyserutils.geyser.form.element.Button;
import me.zimzaza4.geyserutils.geyser.translator.NPCFormResponseTranslator; import me.zimzaza4.geyserutils.geyser.translator.NPCFormResponseTranslator;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.protocol.bedrock.data.skin.ImageData;
import org.cloudburstmc.protocol.bedrock.data.skin.SerializedSkin;
import org.cloudburstmc.protocol.bedrock.packet.*; import org.cloudburstmc.protocol.bedrock.packet.*;
import org.cloudburstmc.protocol.common.DefinitionRegistry; import org.cloudburstmc.protocol.common.DefinitionRegistry;
import org.cloudburstmc.protocol.common.NamedDefinition; import org.cloudburstmc.protocol.common.NamedDefinition;
import org.geysermc.event.subscribe.Subscribe; import org.geysermc.event.subscribe.Subscribe;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.bedrock.camera.CameraPerspective;
import org.geysermc.geyser.api.bedrock.camera.CameraShake; import org.geysermc.geyser.api.bedrock.camera.CameraShake;
import org.geysermc.geyser.api.event.bedrock.SessionJoinEvent; import org.geysermc.geyser.api.event.bedrock.SessionJoinEvent;
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.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
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.SkinManager;
import org.geysermc.geyser.skin.SkinProvider;
import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.DimensionUtils;
import java.util.ArrayList; import javax.imageio.ImageIO;
import java.util.List; import java.awt.image.BufferedImage;
import java.util.Optional; import java.io.*;
import java.util.concurrent.Executors; import java.nio.file.Files;
import java.util.concurrent.TimeUnit; import java.nio.file.Path;
import java.util.*;
import static org.geysermc.geyser.skin.SkinManager.buildEntryManually;
public class GeyserUtils implements Extension { public class GeyserUtils implements Extension {
@@ -50,27 +60,63 @@ public class GeyserUtils implements Extension {
@Getter @Getter
public static PacketManager packetManager; public static PacketManager packetManager;
@Getter
public static Map<String, SkinProvider.SkinData> LOADED_SKIN_DATA = new HashMap<>();
static final SkinProvider.Cape EMPTY_CAPE = new SkinProvider.Cape("", "no-cape", ByteArrays.EMPTY_ARRAY, -1, true);
@Subscribe @Subscribe
public void onLoad(GeyserPostInitializeEvent event) { public void onLoad(GeyserPostInitializeEvent event) {
packetManager = new PacketManager(); packetManager = new PacketManager();
CameraPreset.load(); CameraPreset.load();
Registries.BEDROCK_PACKET_TRANSLATORS.register(NpcRequestPacket.class, new NPCFormResponseTranslator()); Registries.BEDROCK_PACKET_TRANSLATORS.register(NpcRequestPacket.class, new NPCFormResponseTranslator());
loadSkins();
} }
public void loadSkins() {
LOADED_SKIN_DATA.clear();
File folder = this.dataFolder().resolve("skins").toFile();
if (!folder.exists()) {
folder.mkdirs();
}
for (File file : folder.listFiles()) {
if (file.isDirectory()) {
File textureFile = new File(file, "texture.png");
File geometryFile = new File(file, "geometry.json");
try {
SkinProvider.Skin skin = new SkinProvider.Skin(null, file.getName(), Files.readAllBytes(textureFile.toPath()), -1, false, false);
String geoId = "";
JsonElement json = new JsonParser().parse(new FileReader(geometryFile));
for (JsonElement element : json.getAsJsonObject().get("minecraft:geometry").getAsJsonArray()) {
if (element.isJsonObject() && element.getAsJsonObject().has("description")) {
geoId = element.getAsJsonObject().get("description").getAsJsonObject().get("identifier").getAsString();
break;
}
}
String geoName = "{\"geometry\" :{\"default\" :\"" + geoId + "\"}}";
SkinProvider.SkinGeometry geometry = new SkinProvider.SkinGeometry(geoName, Files.readString(geometryFile.toPath()), false);
LOADED_SKIN_DATA.put(file.getName(), new SkinProvider.SkinData(skin, EMPTY_CAPE, geometry));
this.logger().info("Loaded skin: " + file.getName() + "| geo:" + geoName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@Subscribe @Subscribe
public void onSessionJoin(SessionJoinEvent event) { public void onSessionJoin(SessionJoinEvent event) {
System.out.println("JOINED");
if (event.connection() instanceof GeyserSession session) { if (event.connection() instanceof GeyserSession session) {
// sendCameraPresets(session);
System.out.println("2");
session.getDownstream().getSession().addListener(new SessionAdapter() { session.getDownstream().getSession().addListener(new SessionAdapter() {
@Override @Override
public void packetReceived(Session tcpSession, Packet packet) { public void packetReceived(Session tcpSession, Packet packet) {
if (packet instanceof ClientboundCustomPayloadPacket payloadPacket) { if (packet instanceof ClientboundCustomPayloadPacket payloadPacket) {
if (payloadPacket.getChannel().equals(GeyserUtilsChannels.MAIN)) {; if (payloadPacket.getChannel().equals(GeyserUtilsChannels.MAIN)) {
;
CustomPayloadPacket customPacket = packetManager.decodePacket(payloadPacket.getData()); CustomPayloadPacket customPacket = packetManager.decodePacket(payloadPacket.getData());
if (customPacket instanceof CameraShakeCustomPayloadPacket cameraShakePacket) { if (customPacket instanceof CameraShakeCustomPayloadPacket cameraShakePacket) {
event.connection().shakeCamera(cameraShakePacket.getIntensity(), cameraShakePacket.getDuration(), CameraShake.values()[cameraShakePacket.getType()]); event.connection().shakeCamera(cameraShakePacket.getIntensity(), cameraShakePacket.getDuration(), CameraShake.values()[cameraShakePacket.getType()]);
@@ -141,7 +187,7 @@ public class GeyserUtils implements Extension {
} else if (cameraInstructionPacket.getInstruction() instanceof FadeInstruction instruction) { } else if (cameraInstructionPacket.getInstruction() instanceof FadeInstruction instruction) {
session.camera().sendCameraFade(Converter.serializeFadeInstruction(instruction)); session.camera().sendCameraFade(Converter.serializeFadeInstruction(instruction));
} else if (cameraInstructionPacket.getInstruction() instanceof ClearInstruction){ } else if (cameraInstructionPacket.getInstruction() instanceof ClearInstruction) {
session.camera().clearCameraInstructions(); session.camera().clearCameraInstructions();
} }
@@ -152,6 +198,13 @@ public class GeyserUtils implements Extension {
spawnParticleEffectPacket.setIdentifier(customParticleEffectPacket.getParticle().identifier()); spawnParticleEffectPacket.setIdentifier(customParticleEffectPacket.getParticle().identifier());
spawnParticleEffectPacket.setMolangVariablesJson(Optional.ofNullable(customParticleEffectPacket.getParticle().molangVariablesJson())); spawnParticleEffectPacket.setMolangVariablesJson(Optional.ofNullable(customParticleEffectPacket.getParticle().molangVariablesJson()));
session.sendUpstreamPacket(spawnParticleEffectPacket); session.sendUpstreamPacket(spawnParticleEffectPacket);
} else if (customPacket instanceof CustomSkinPayloadPacket customSkinPayloadPacket) {
if (session.getEntityCache().getEntityByJavaId(customSkinPayloadPacket.getEntityId()) instanceof PlayerEntity player) {
SkinProvider.SkinData data = LOADED_SKIN_DATA.get(customSkinPayloadPacket.getSkinId());
if (data != null) {
sendSkinPacket(session, player, data);
}
}
} }
} }
} }
@@ -163,32 +216,36 @@ public class GeyserUtils implements Extension {
} }
public static void sendCameraPresets(GeyserSession session) { public static void sendSkinPacket(GeyserSession session, PlayerEntity entity, SkinProvider.SkinData skinData) {
if (session.getUpstream().getCodecHelper().getCameraPresetDefinitions() == null) { SkinProvider.Skin skin = skinData.skin();
SkinProvider.Cape cape = skinData.cape();
session.getUpstream().getCodecHelper().setCameraPresetDefinitions(new DefinitionRegistry<>() { SkinProvider.SkinGeometry geometry = skinData.geometry();
@Override if (entity.getUuid().equals(session.getPlayerEntity().getUuid())) {
public NamedDefinition getDefinition(int i) { PlayerListPacket.Entry updatedEntry = buildEntryManually(session, entity.getUuid(), entity.getUsername(), entity.getGeyserId(), skin, cape, geometry);
for (CameraPreset preset : CameraPreset.getPresets().values()) { PlayerListPacket playerAddPacket = new PlayerListPacket();
if (preset.getId() == i) { playerAddPacket.setAction(PlayerListPacket.Action.ADD);
return new CameraPresetDefinition(preset.getIdentifier(), i); playerAddPacket.getEntries().add(updatedEntry);
} session.sendUpstreamPacket(playerAddPacket);
} } else {
PlayerSkinPacket packet = new PlayerSkinPacket();
return null; packet.setUuid(entity.getUuid());
} packet.setOldSkinName("");
packet.setNewSkinName(skin.getTextureUrl());
@Override packet.setSkin(getSkin(skin.getTextureUrl(), skin, cape, geometry));
public boolean isRegistered(NamedDefinition namedDefinition) { packet.setTrustedSkin(true);
return CameraPreset.getPreset(namedDefinition.getIdentifier()) != null; session.sendUpstreamPacket(packet);
}
});
}
CameraPresetsPacket pk = new CameraPresetsPacket();
for (CameraPreset preset : CameraPreset.getPresets().values()) {
pk.getPresets().add(Converter.serializeCameraPreset(preset));
} }
session.sendUpstreamPacket(pk);
} }
private static SerializedSkin getSkin(String skinId, SkinProvider.Skin skin, SkinProvider.Cape cape, SkinProvider.SkinGeometry geometry) {
try {
return SerializedSkin.of(skinId, "", geometry.geometryName(), ImageData.from(ImageIO.read(new ByteArrayInputStream(skin.getSkinData()))), Collections.emptyList(), ImageData.of(cape.capeData()), geometry.geometryData(), "", true, false, false, cape.capeId(), skinId);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} }

View File

@@ -62,7 +62,6 @@ public class Converter {
public static CameraFade serializeFadeInstruction(FadeInstruction instruction) { public static CameraFade serializeFadeInstruction(FadeInstruction instruction) {
CameraFadeInstruction cbInstruction = new CameraFadeInstruction();
CameraFade.Builder builder = CameraFade.builder(); CameraFade.Builder builder = CameraFade.builder();
if (instruction.getColor() != null) { if (instruction.getColor() != null) {
builder.color(serializeColor(instruction.getColor())); builder.color(serializeColor(instruction.getColor()));

View File

@@ -3,10 +3,7 @@ package me.zimzaza4.geyserutils.spigot.api;
import me.zimzaza4.geyserutils.common.animation.Animation; import me.zimzaza4.geyserutils.common.animation.Animation;
import me.zimzaza4.geyserutils.common.camera.instruction.Instruction; import me.zimzaza4.geyserutils.common.camera.instruction.Instruction;
import me.zimzaza4.geyserutils.common.channel.GeyserUtilsChannels; import me.zimzaza4.geyserutils.common.channel.GeyserUtilsChannels;
import me.zimzaza4.geyserutils.common.packet.AnimateEntityCustomPayloadPacket; import me.zimzaza4.geyserutils.common.packet.*;
import me.zimzaza4.geyserutils.common.packet.CameraInstructionCustomPayloadPacket;
import me.zimzaza4.geyserutils.common.packet.CameraShakeCustomPayloadPacket;
import me.zimzaza4.geyserutils.common.packet.CustomParticleEffectPayloadPacket;
import me.zimzaza4.geyserutils.common.particle.CustomParticle; import me.zimzaza4.geyserutils.common.particle.CustomParticle;
import me.zimzaza4.geyserutils.common.util.Pos; import me.zimzaza4.geyserutils.common.util.Pos;
import me.zimzaza4.geyserutils.spigot.GeyserUtils; import me.zimzaza4.geyserutils.spigot.GeyserUtils;
@@ -53,6 +50,13 @@ public class PlayerUtils {
packet.setParticle(particle); packet.setParticle(particle);
packet.setPos(new Pos((float) location.getX(), (float) location.getY(), (float) location.getZ())); packet.setPos(new Pos((float) location.getX(), (float) location.getY(), (float) location.getZ()));
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet)); player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
}
public static void sendCustomSkin(Player player, Entity entity, String skin) {
CustomSkinPayloadPacket skinPayloadPacket = new CustomSkinPayloadPacket();
skinPayloadPacket.setSkinId(skin);
skinPayloadPacket.setEntityId(entity.getEntityId());
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(skinPayloadPacket));
} }
} }