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.event.session.SessionAdapter;
|
||||
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 me.zimzaza4.geyserutils.common.camera.data.CameraPreset;
|
||||
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.translator.NPCFormResponseTranslator;
|
||||
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.common.DefinitionRegistry;
|
||||
import org.cloudburstmc.protocol.common.NamedDefinition;
|
||||
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.event.bedrock.SessionJoinEvent;
|
||||
import org.geysermc.geyser.api.event.lifecycle.GeyserPostInitializeEvent;
|
||||
import org.geysermc.geyser.api.extension.Extension;
|
||||
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.session.GeyserSession;
|
||||
import org.geysermc.geyser.skin.SkinManager;
|
||||
import org.geysermc.geyser.skin.SkinProvider;
|
||||
import org.geysermc.geyser.util.DimensionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
import static org.geysermc.geyser.skin.SkinManager.buildEntryManually;
|
||||
|
||||
public class GeyserUtils implements Extension {
|
||||
|
||||
@@ -50,27 +60,63 @@ public class GeyserUtils implements Extension {
|
||||
@Getter
|
||||
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
|
||||
public void onLoad(GeyserPostInitializeEvent event) {
|
||||
packetManager = new PacketManager();
|
||||
CameraPreset.load();
|
||||
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
|
||||
public void onSessionJoin(SessionJoinEvent event) {
|
||||
System.out.println("JOINED");
|
||||
if (event.connection() instanceof GeyserSession session) {
|
||||
// sendCameraPresets(session);
|
||||
System.out.println("2");
|
||||
session.getDownstream().getSession().addListener(new SessionAdapter() {
|
||||
@Override
|
||||
public void packetReceived(Session tcpSession, Packet packet) {
|
||||
|
||||
if (packet instanceof ClientboundCustomPayloadPacket payloadPacket) {
|
||||
if (payloadPacket.getChannel().equals(GeyserUtilsChannels.MAIN)) {;
|
||||
if (payloadPacket.getChannel().equals(GeyserUtilsChannels.MAIN)) {
|
||||
;
|
||||
CustomPayloadPacket customPacket = packetManager.decodePacket(payloadPacket.getData());
|
||||
if (customPacket instanceof CameraShakeCustomPayloadPacket cameraShakePacket) {
|
||||
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) {
|
||||
session.camera().sendCameraFade(Converter.serializeFadeInstruction(instruction));
|
||||
} else if (cameraInstructionPacket.getInstruction() instanceof ClearInstruction){
|
||||
} else if (cameraInstructionPacket.getInstruction() instanceof ClearInstruction) {
|
||||
session.camera().clearCameraInstructions();
|
||||
}
|
||||
|
||||
@@ -152,6 +198,13 @@ public class GeyserUtils implements Extension {
|
||||
spawnParticleEffectPacket.setIdentifier(customParticleEffectPacket.getParticle().identifier());
|
||||
spawnParticleEffectPacket.setMolangVariablesJson(Optional.ofNullable(customParticleEffectPacket.getParticle().molangVariablesJson()));
|
||||
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) {
|
||||
if (session.getUpstream().getCodecHelper().getCameraPresetDefinitions() == null) {
|
||||
|
||||
session.getUpstream().getCodecHelper().setCameraPresetDefinitions(new DefinitionRegistry<>() {
|
||||
@Override
|
||||
public NamedDefinition getDefinition(int i) {
|
||||
for (CameraPreset preset : CameraPreset.getPresets().values()) {
|
||||
if (preset.getId() == i) {
|
||||
return new CameraPresetDefinition(preset.getIdentifier(), i);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegistered(NamedDefinition namedDefinition) {
|
||||
return CameraPreset.getPreset(namedDefinition.getIdentifier()) != null;
|
||||
}
|
||||
});
|
||||
}
|
||||
CameraPresetsPacket pk = new CameraPresetsPacket();
|
||||
for (CameraPreset preset : CameraPreset.getPresets().values()) {
|
||||
pk.getPresets().add(Converter.serializeCameraPreset(preset));
|
||||
public static void sendSkinPacket(GeyserSession session, PlayerEntity entity, SkinProvider.SkinData skinData) {
|
||||
SkinProvider.Skin skin = skinData.skin();
|
||||
SkinProvider.Cape cape = skinData.cape();
|
||||
SkinProvider.SkinGeometry geometry = skinData.geometry();
|
||||
if (entity.getUuid().equals(session.getPlayerEntity().getUuid())) {
|
||||
PlayerListPacket.Entry updatedEntry = buildEntryManually(session, entity.getUuid(), entity.getUsername(), entity.getGeyserId(), skin, cape, geometry);
|
||||
PlayerListPacket playerAddPacket = new PlayerListPacket();
|
||||
playerAddPacket.setAction(PlayerListPacket.Action.ADD);
|
||||
playerAddPacket.getEntries().add(updatedEntry);
|
||||
session.sendUpstreamPacket(playerAddPacket);
|
||||
} else {
|
||||
PlayerSkinPacket packet = new PlayerSkinPacket();
|
||||
packet.setUuid(entity.getUuid());
|
||||
packet.setOldSkinName("");
|
||||
packet.setNewSkinName(skin.getTextureUrl());
|
||||
packet.setSkin(getSkin(skin.getTextureUrl(), skin, cape, geometry));
|
||||
packet.setTrustedSkin(true);
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
|
||||
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) {
|
||||
CameraFadeInstruction cbInstruction = new CameraFadeInstruction();
|
||||
CameraFade.Builder builder = CameraFade.builder();
|
||||
if (instruction.getColor() != null) {
|
||||
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.camera.instruction.Instruction;
|
||||
import me.zimzaza4.geyserutils.common.channel.GeyserUtilsChannels;
|
||||
import me.zimzaza4.geyserutils.common.packet.AnimateEntityCustomPayloadPacket;
|
||||
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.packet.*;
|
||||
import me.zimzaza4.geyserutils.common.particle.CustomParticle;
|
||||
import me.zimzaza4.geyserutils.common.util.Pos;
|
||||
import me.zimzaza4.geyserutils.spigot.GeyserUtils;
|
||||
@@ -53,6 +50,13 @@ public class PlayerUtils {
|
||||
packet.setParticle(particle);
|
||||
packet.setPos(new Pos((float) location.getX(), (float) location.getY(), (float) location.getZ()));
|
||||
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