mirror of
https://github.com/GeyserExtensionists/GeyserUtils.git
synced 2025-12-19 14:59:18 +00:00
custom skin
This commit is contained in:
79
bungee/pom.xml
Normal file
79
bungee/pom.xml
Normal 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>
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
3
bungee/src/main/resources/bungee.yml
Normal file
3
bungee/src/main/resources/bungee.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
name: GeyserUtils
|
||||||
|
version: '${project.version}'
|
||||||
|
main: me.zimzaza4.geyserutils.bungee.GeyserUtils
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()));
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user