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

Animation

This commit is contained in:
zimzaza4
2023-09-16 19:34:38 +08:00
parent d8c3feaacf
commit ec8318b7c5
13 changed files with 176 additions and 51 deletions

View File

@@ -16,6 +16,8 @@
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
@@ -23,6 +25,11 @@
<version>1.18.28</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>5.5.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,26 @@
package me.zimzaza4.geyserutils.common.animation;
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
public class Animation {
public static final float DEFAULT_BLEND_OUT_TIME = 0.0f;
public static final String DEFAULT_STOP_EXPRESSION = "query.any_animation_finished";
public static final String DEFAULT_CONTROLLER = "__runtime_controller";
public static final String DEFAULT_NEXT_STATE = "default";
public static final int DEFAULT_STOP_EXPRESSION_VERSION = 16777216;
private String animation;
@Builder.Default
private String nextState = DEFAULT_NEXT_STATE;
@Builder.Default
private float blendOutTime = DEFAULT_BLEND_OUT_TIME;
@Builder.Default
private String stopExpression = DEFAULT_STOP_EXPRESSION;
@Builder.Default
private String controller = DEFAULT_CONTROLLER;
@Builder.Default
private int stopExpressionVersion = DEFAULT_STOP_EXPRESSION_VERSION;
}

View File

@@ -0,0 +1,41 @@
package me.zimzaza4.geyserutils.common.manager;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import me.zimzaza4.geyserutils.common.packet.CameraShakeCustomPayloadPacket;
import me.zimzaza4.geyserutils.common.packet.CustomPayloadPacket;
import me.zimzaza4.geyserutils.common.packet.NpcDialogueFormDataCustomPayloadPacket;
import java.io.*;
public class PacketManager {
private final Kryo kryo = new Kryo();
public PacketManager() {
init();
}
public void init() {
kryo.setRegistrationRequired(false);
}
public void registerPacket(Class<? extends CustomPayloadPacket> clazz) {
kryo.register(clazz);
}
public byte[] encodePacket(CustomPayloadPacket packet) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (Output output = new Output()) {
kryo.writeObject(output, packet);
return byteArrayOutputStream.toByteArray();
}
}
public CustomPayloadPacket decodePacket(byte[] bytes) {
try (Input input = new Input(bytes)) {
return kryo.readObject(input, CustomPayloadPacket.class);
}
}
}

View File

@@ -0,0 +1,30 @@
package me.zimzaza4.geyserutils.common.packet;
import lombok.Getter;
import lombok.Setter;
import me.zimzaza4.geyserutils.common.animation.Animation;
import java.util.ArrayList;
import java.util.List;
@Setter
@Getter
public class AnimateEntityCustomPayloadPacket extends CustomPayloadPacket{
private String animation;
private String nextState;
private String stopExpression;
private int stopExpressionVersion;
private String controller;
private float blendOutTime;
private List<Integer> entityJavaIds = new ArrayList<>();
public void parseFromAnimation(Animation ani) {
this.animation = ani.getAnimation();
this.nextState = ani.getNextState();
this.blendOutTime = ani.getBlendOutTime();
this.stopExpression = ani.getStopExpression();
this.controller = ani.getController();
this.stopExpressionVersion = ani.getStopExpressionVersion();
}
}

View File

@@ -5,7 +5,7 @@ import lombok.Getter;
@Getter
@AllArgsConstructor
public class CameraShakePacket extends Packet {
public class CameraShakeCustomPayloadPacket extends CustomPayloadPacket {
float intensity;
float duration;

View File

@@ -2,6 +2,6 @@ package me.zimzaza4.geyserutils.common.packet;
import java.io.Serializable;
public abstract class Packet implements Serializable {
public abstract class CustomPayloadPacket implements Serializable {
}

View File

@@ -6,14 +6,13 @@ import lombok.Setter;
import lombok.experimental.Accessors;
import me.zimzaza4.geyserutils.common.form.element.NpcDialogueButton;
import java.io.Serializable;
import java.util.List;
@AllArgsConstructor
@Accessors(fluent = true)
@Getter
@Setter
public class NpcDialogueFormDataPacket extends Packet {
public class NpcDialogueFormDataCustomPayloadPacket extends CustomPayloadPacket {
String formId;
String title;

View File

@@ -4,12 +4,10 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class NpcFormResponsePacket extends Packet {
public class NpcFormResponseCustomPayloadPacket extends CustomPayloadPacket {
String formId;
int buttonId;
}

View File

@@ -1,30 +1,12 @@
package me.zimzaza4.geyserutils.common.util;
import me.zimzaza4.geyserutils.common.packet.Packet;
import com.esotericsoftware.kryo.Kryo;
import me.zimzaza4.geyserutils.common.packet.CustomPayloadPacket;
import java.io.*;
public class CustomPayloadPacketUtils {
public static byte[] encodePacket(Packet packet) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream)) {
outputStream.writeObject(packet);
outputStream.flush();
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Packet decodePacket(byte[] bytes) {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
try (ObjectInputStream inputStream = new ObjectInputStream(byteArrayInputStream)) {
return (Packet) inputStream.readObject();
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -5,22 +5,24 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCu
import com.github.steveice10.packetlib.Session;
import com.github.steveice10.packetlib.event.session.SessionAdapter;
import com.github.steveice10.packetlib.packet.Packet;
import lombok.Getter;
import me.zimzaza4.geyserutils.common.channel.GeyserUtilsChannels;
import me.zimzaza4.geyserutils.common.form.element.NpcDialogueButton;
import me.zimzaza4.geyserutils.common.packet.CameraShakePacket;
import me.zimzaza4.geyserutils.common.packet.NpcDialogueFormDataPacket;
import me.zimzaza4.geyserutils.common.packet.NpcFormResponsePacket;
import me.zimzaza4.geyserutils.common.manager.PacketManager;
import me.zimzaza4.geyserutils.common.packet.*;
import me.zimzaza4.geyserutils.common.util.CustomPayloadPacketUtils;
import me.zimzaza4.geyserutils.geyser.form.NpcDialogueForm;
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.protocol.bedrock.packet.AnimateEntityPacket;
import org.cloudburstmc.protocol.bedrock.packet.NpcRequestPacket;
import org.geysermc.event.subscribe.Subscribe;
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.registry.Registries;
import org.geysermc.geyser.session.GeyserSession;
@@ -29,8 +31,12 @@ import java.util.List;
public class GeyserUtils implements Extension {
@Getter
public static PacketManager packetManager;
@Subscribe
public void onLoad(GeyserPostInitializeEvent event) {
packetManager = new PacketManager();
Registries.BEDROCK_PACKET_TRANSLATORS.register(NpcRequestPacket.class, new NPCFormResponseTranslator());
}
@Subscribe
@@ -44,12 +50,12 @@ public class GeyserUtils implements Extension {
System.out.println(payloadPacket.getChannel());
if (payloadPacket.getChannel().equals(GeyserUtilsChannels.MAIN)) {
System.out.println("Received packet");
me.zimzaza4.geyserutils.common.packet.Packet customPacket = CustomPayloadPacketUtils.decodePacket(payloadPacket.getData());
CustomPayloadPacket customPacket = packetManager.decodePacket(payloadPacket.getData());
System.out.println(1);
if (customPacket instanceof CameraShakePacket cameraShakePacket) {
if (customPacket instanceof CameraShakeCustomPayloadPacket cameraShakePacket) {
System.out.println(2);
event.connection().shakeCamera(cameraShakePacket.getIntensity(), cameraShakePacket.getDuration(), CameraShake.values()[cameraShakePacket.getType()]);
} else if (customPacket instanceof NpcDialogueFormDataPacket formData) {
} else if (customPacket instanceof NpcDialogueFormDataCustomPayloadPacket formData) {
if (formData.action().equals("CLOSE")) {
NpcDialogueForm openForm = NpcDialogueForms.getOpenNpcDialogueForms(session);
@@ -82,7 +88,7 @@ public class GeyserUtils implements Extension {
buttons.add(new Button(button.text(), button.commands(),
button.mode(), () -> {
if (button.mode() == NpcDialogueButton.ButtonMode.BUTTON_MODE) {
session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(GeyserUtilsChannels.MAIN, CustomPayloadPacketUtils.encodePacket(new NpcFormResponsePacket(formData.formId(), finalI))));
session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(GeyserUtilsChannels.MAIN, packetManager.encodePacket(new NpcFormResponseCustomPayloadPacket(formData.formId(), finalI))));
}
}
));
@@ -90,11 +96,26 @@ public class GeyserUtils implements Extension {
}
}
form.closeHandler(() -> session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(GeyserUtilsChannels.MAIN, CustomPayloadPacketUtils.encodePacket(new NpcFormResponsePacket(formData.formId(), -1)))));
form.closeHandler(() -> session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(GeyserUtilsChannels.MAIN, packetManager.encodePacket(new NpcFormResponseCustomPayloadPacket(formData.formId(), -1)))));
form.buttons(buttons);
form.createAndSend(session);
} else if (customPacket instanceof AnimateEntityCustomPayloadPacket animateEntityCustomPayloadPacket) {
AnimateEntityPacket animateEntityPacket = new AnimateEntityPacket();
animateEntityPacket.setAnimation(animateEntityCustomPayloadPacket.getAnimation());
animateEntityPacket.setController(animateEntityCustomPayloadPacket.getController());
animateEntityPacket.setBlendOutTime(animateEntityCustomPayloadPacket.getBlendOutTime());
animateEntityPacket.setNextState(animateEntityCustomPayloadPacket.getNextState());
animateEntityPacket.setStopExpressionVersion(animateEntityCustomPayloadPacket.getStopExpressionVersion());
animateEntityPacket.setStopExpression(animateEntityCustomPayloadPacket.getStopExpression());
for (int id : animateEntityCustomPayloadPacket.getEntityJavaIds()) {
Entity entity = session.getEntityCache().getEntityByJavaId(id);
if (entity != null) {
animateEntityPacket.getRuntimeEntityIds().add(entity.getGeyserId());
}
}
session.sendUpstreamPacket(animateEntityPacket);
}
}
}

View File

@@ -2,33 +2,35 @@ package me.zimzaza4.geyserutils.spigot;
import lombok.Getter;
import me.zimzaza4.geyserutils.common.channel.GeyserUtilsChannels;
import me.zimzaza4.geyserutils.common.packet.NpcDialogueFormDataPacket;
import me.zimzaza4.geyserutils.common.packet.NpcFormResponsePacket;
import me.zimzaza4.geyserutils.common.packet.Packet;
import me.zimzaza4.geyserutils.common.manager.PacketManager;
import me.zimzaza4.geyserutils.common.packet.NpcFormResponseCustomPayloadPacket;
import me.zimzaza4.geyserutils.common.packet.CustomPayloadPacket;
import me.zimzaza4.geyserutils.common.util.CustomPayloadPacketUtils;
import me.zimzaza4.geyserutils.spigot.api.form.NpcDialogueForm;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.messaging.Messenger;
import java.nio.charset.StandardCharsets;
import java.util.function.BiConsumer;
public final class GeyserUtils extends JavaPlugin {
@Getter
public static GeyserUtils instance;
private static GeyserUtils instance;
@Getter
private static PacketManager packetManager;
@Override
public void onEnable() {
// Plugin startup logic
instance = this;
packetManager = new PacketManager();
Messenger messenger = this.getServer().getMessenger();
messenger.registerOutgoingPluginChannel(this, GeyserUtilsChannels.MAIN);
messenger.registerIncomingPluginChannel(this, GeyserUtilsChannels.MAIN, (channel, player, message) -> {
if (channel.equals(GeyserUtilsChannels.MAIN)) {
Packet packet = CustomPayloadPacketUtils.decodePacket(message);
if (packet instanceof NpcFormResponsePacket) {
NpcFormResponsePacket response = (NpcFormResponsePacket) packet;
CustomPayloadPacket packet = packetManager.decodePacket(message);
if (packet instanceof NpcFormResponseCustomPayloadPacket) {
NpcFormResponseCustomPayloadPacket response = (NpcFormResponseCustomPayloadPacket) packet;
if (NpcDialogueForm.FORMS.containsKey(response.getFormId())) {
BiConsumer<String, Integer> handler = NpcDialogueForm.FORMS.get(response.getFormId()).handler();

View File

@@ -1,18 +1,37 @@
package me.zimzaza4.geyserutils.spigot.api;
import me.zimzaza4.geyserutils.common.animation.Animation;
import me.zimzaza4.geyserutils.common.channel.GeyserUtilsChannels;
import me.zimzaza4.geyserutils.common.packet.CameraShakePacket;
import me.zimzaza4.geyserutils.common.packet.AnimateEntityCustomPayloadPacket;
import me.zimzaza4.geyserutils.common.packet.CameraShakeCustomPayloadPacket;
import me.zimzaza4.geyserutils.common.util.CustomPayloadPacketUtils;
import me.zimzaza4.geyserutils.spigot.GeyserUtils;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import java.util.concurrent.CompletableFuture;
import java.util.ArrayList;
import java.util.List;
public class PlayerUtils {
public static void shakeCamera(Player player, float intensity, float duration, int type) {
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, CustomPayloadPacketUtils.encodePacket(new CameraShakePacket(intensity, duration, type)));
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(new CameraShakeCustomPayloadPacket(intensity, duration, type)));
}
public static void playEntityAnimation(Player player, Animation animation, Entity... entityList) {
List<Integer> idList = new ArrayList<>();
for (Entity entity : entityList) {
idList.add(entity.getEntityId());
}
playEntityAnimation(player, animation, idList);
}
public static void playEntityAnimation(Player player, Animation animation, List<Integer> entityList) {
AnimateEntityCustomPayloadPacket packet = new AnimateEntityCustomPayloadPacket();
packet.parseFromAnimation(animation);
packet.setEntityJavaIds(entityList);
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
}
}

View File

@@ -7,7 +7,7 @@ import lombok.Setter;
import lombok.experimental.Accessors;
import me.zimzaza4.geyserutils.common.channel.GeyserUtilsChannels;
import me.zimzaza4.geyserutils.common.form.element.NpcDialogueButton;
import me.zimzaza4.geyserutils.common.packet.NpcDialogueFormDataPacket;
import me.zimzaza4.geyserutils.common.packet.NpcDialogueFormDataCustomPayloadPacket;
import me.zimzaza4.geyserutils.common.util.CustomPayloadPacketUtils;
import me.zimzaza4.geyserutils.spigot.GeyserUtils;
import org.bukkit.Bukkit;
@@ -41,13 +41,13 @@ public class NpcDialogueForm {
public void send(FloodgatePlayer floodgatePlayer) {
UUID formId = UUID.randomUUID();
NpcDialogueFormDataPacket data = new NpcDialogueFormDataPacket(formId.toString(), title, dialogue, skinData, bindEntity.getEntityId(), buttons, "OPEN", hasNextForm);
NpcDialogueFormDataCustomPayloadPacket data = new NpcDialogueFormDataCustomPayloadPacket(formId.toString(), title, dialogue, skinData, bindEntity.getEntityId(), buttons, "OPEN", hasNextForm);
Player p = Bukkit.getPlayer(floodgatePlayer.getCorrectUniqueId());
if (p!= null) {
FORMS.put(formId.toString(), this);
p.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, CustomPayloadPacketUtils.encodePacket(data));
p.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(data));
new BukkitRunnable() {
@Override
@@ -65,10 +65,10 @@ public class NpcDialogueForm {
}
public static void closeForm(FloodgatePlayer floodgatePlayer) {
NpcDialogueFormDataPacket data = new NpcDialogueFormDataPacket(null, null, null, null, -1, null, "CLOSE", false);
NpcDialogueFormDataCustomPayloadPacket data = new NpcDialogueFormDataCustomPayloadPacket(null, null, null, null, -1, null, "CLOSE", false);
Player p = Bukkit.getPlayer(floodgatePlayer.getCorrectUniqueId());
if (p != null) {
p.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, CustomPayloadPacketUtils.encodePacket(data));
p.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(data));
}
}
}