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

Initial commit

This commit is contained in:
zimzaza4
2023-09-10 13:40:49 +08:00
commit d8c3feaacf
28 changed files with 1222 additions and 0 deletions

38
.gitignore vendored Normal file
View File

@@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

3
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# 默认忽略的文件
/shelf/
/workspace.xml

15
.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/geyser/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/geyser/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/spigot/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/spigot/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/velocity/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/velocity/src/main/resources" charset="UTF-8" />
</component>
</project>

24
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<list size="3">
<item index="0" class="java.lang.String" itemvalue="org.bukkit.event.EventHandler" />
<item index="1" class="java.lang.String" itemvalue="com.velocitypowered.api.event.Subscribe" />
<item index="2" class="java.lang.String" itemvalue="com.velocitypowered.api.plugin.Plugin" />
</list>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
<option value="$PROJECT_DIR$/GeyserUtils-spigot/pom.xml" />
<option value="$PROJECT_DIR$/spigot/pom.xml" />
<option value="$PROJECT_DIR$/velocity/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

124
.idea/uiDesigner.xml generated Normal file
View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

28
common/pom.xml Normal file
View File

@@ -0,0 +1,28 @@
<?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-common</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,5 @@
package me.zimzaza4.geyserutils.common.channel;
public class GeyserUtilsChannels {
public static final String MAIN = "geyserutils:main";
}

View File

@@ -0,0 +1,25 @@
package me.zimzaza4.geyserutils.common.form.element;
import lombok.Getter;
import lombok.Setter;
import lombok.Value;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
@Setter
@Getter
@Accessors( fluent = true )
public class NpcDialogueButton implements Serializable {
private String text;
private List<String> commands;
private ButtonMode mode;
public enum ButtonMode {
BUTTON_MODE,
ON_ENTER,
ON_EXIT
}
}

View File

@@ -0,0 +1,14 @@
package me.zimzaza4.geyserutils.common.packet;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class CameraShakePacket extends Packet {
float intensity;
float duration;
int type;
}

View File

@@ -0,0 +1,27 @@
package me.zimzaza4.geyserutils.common.packet;
import lombok.AllArgsConstructor;
import lombok.Getter;
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 {
String formId;
String title;
String dialogue;
String skinData;
int bindEntity;
List<NpcDialogueButton> buttons;
String action;
boolean hasNextForm;
}

View File

@@ -0,0 +1,15 @@
package me.zimzaza4.geyserutils.common.packet;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class NpcFormResponsePacket extends Packet {
String formId;
int buttonId;
}

View File

@@ -0,0 +1,7 @@
package me.zimzaza4.geyserutils.common.packet;
import java.io.Serializable;
public abstract class Packet implements Serializable {
}

View File

@@ -0,0 +1,30 @@
package me.zimzaza4.geyserutils.common.util;
import me.zimzaza4.geyserutils.common.packet.Packet;
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);
}
}
}

99
geyser/pom.xml Normal file
View File

@@ -0,0 +1,99 @@
<?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-geyser</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</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>opencollab-release-repo</id>
<url>https://repo.opencollab.dev/maven-releases/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>opencollab-snapshot-repo</id>
<url>https://repo.opencollab.dev/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>sonatype-oss-snapshots1</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.geysermc.geyser</groupId>
<artifactId>api</artifactId>
<version>2.1.2-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.geysermc.geyser</groupId>
<artifactId>core</artifactId>
<version>2.1.2-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,105 @@
package me.zimzaza4.geyserutils.geyser;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundCustomPayloadPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCustomPayloadPacket;
import com.github.steveice10.packetlib.Session;
import com.github.steveice10.packetlib.event.session.SessionAdapter;
import com.github.steveice10.packetlib.packet.Packet;
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.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.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.registry.Registries;
import org.geysermc.geyser.session.GeyserSession;
import java.util.ArrayList;
import java.util.List;
public class GeyserUtils implements Extension {
@Subscribe
public void onLoad(GeyserPostInitializeEvent event) {
Registries.BEDROCK_PACKET_TRANSLATORS.register(NpcRequestPacket.class, new NPCFormResponseTranslator());
}
@Subscribe
public void onSessionJoin(SessionJoinEvent event) {
if (event.connection() instanceof GeyserSession session) {
System.out.println("Add");
session.getDownstream().getSession().addListener(new SessionAdapter() {
@Override
public void packetReceived(Session tcpSession, Packet packet) {
if (packet instanceof ClientboundCustomPayloadPacket payloadPacket) {
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());
System.out.println(1);
if (customPacket instanceof CameraShakePacket cameraShakePacket) {
System.out.println(2);
event.connection().shakeCamera(cameraShakePacket.getIntensity(), cameraShakePacket.getDuration(), CameraShake.values()[cameraShakePacket.getType()]);
} else if (customPacket instanceof NpcDialogueFormDataPacket formData) {
if (formData.action().equals("CLOSE")) {
NpcDialogueForm openForm = NpcDialogueForms.getOpenNpcDialogueForms(session);
if (openForm != null) {
openForm.close(session);
}
return;
}
NpcDialogueForm form = new NpcDialogueForm();
form.title(formData.title())
.dialogue(formData.dialogue())
.bindEntity(session.getEntityCache().getEntityByJavaId(formData.bindEntity()))
.hasNextForm(formData.hasNextForm());
if (formData.skinData() != null) {
form.skinData(formData.skinData());
}
List<Button> buttons = new ArrayList<>();
if (formData.buttons() != null) {
int i = 0;
for (NpcDialogueButton button : formData.buttons()) {
int finalI = i;
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))));
}
}
));
i++;
}
}
form.closeHandler(() -> session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(GeyserUtilsChannels.MAIN, CustomPayloadPacketUtils.encodePacket(new NpcFormResponsePacket(formData.formId(), -1)))));
form.buttons(buttons);
form.createAndSend(session);
}
}
}
}
});
}
}
}

View File

@@ -0,0 +1,143 @@
package me.zimzaza4.geyserutils.geyser.form;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import me.zimzaza4.geyserutils.geyser.form.element.Button;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.packet.NpcDialoguePacket;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.entity.GeyserDirtyMetadata;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.session.GeyserSession;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Accessors(fluent = true, chain = true)
public class NpcDialogueForm {
public static final Gson GSON = new Gson();
@Getter
private final String sceneName = UUID.randomUUID().toString();
@Getter
@Setter
private String title;
@Getter
@Setter
private String dialogue;
@Getter
@Setter
private Entity bindEntity;
private String actionJson = "";
@Getter
@Setter
private String skinData = "{\"picker_offsets\":{\"scale\":[1.70,1.70,1.70],\"translate\":[0,20,0]},\"portrait_offsets\":{\"scale\":[1.750,1.750,1.750],\"translate\":[-7,50,0]},\"skin_list\":[{\"variant\":0},{\"variant\":1},{\"variant\":2},{\"variant\":3},{\"variant\":4},{\"variant\":5},{\"variant\":6},{\"variant\":7},{\"variant\":8},{\"variant\":9},{\"variant\":10},{\"variant\":11},{\"variant\":12},{\"variant\":13},{\"variant\":14},{\"variant\":15},{\"variant\":16},{\"variant\":17},{\"variant\":18},{\"variant\":19},{\"variant\":20},{\"variant\":21},{\"variant\":22},{\"variant\":23},{\"variant\":24},{\"variant\":25},{\"variant\":26},{\"variant\":27},{\"variant\":28},{\"variant\":29},{\"variant\":30},{\"variant\":31},{\"variant\":32},{\"variant\":33},{\"variant\":34}]}";
@Getter
private final ObjectArrayList<Button> dialogueButtons = new ObjectArrayList<>();
@Getter
@Setter
private Runnable closeHandler = () -> { };
@Getter
@Setter
private boolean hasNextForm;
public NpcDialogueForm buttons(Button... buttons) {
List<JsonObject> objects = new ArrayList<>();
for (Button button : buttons) {
objects.add(button.toJsonObject());
}
this.actionJson = GSON.toJson(objects);
this.dialogueButtons.addAll(Arrays.asList(buttons));
return this;
}
public NpcDialogueForm buttons(List<Button> buttons) {
List<JsonObject> objects = new ArrayList<>();
for (Button button : buttons) {
objects.add(button.toJsonObject());
}
this.actionJson = GSON.toJson(objects);
this.dialogueButtons.addAll(buttons);
return this;
}
public void createAndSend(GeyserSession player) {
SetEntityDataPacket setEntityDataPacket = new SetEntityDataPacket();
setEntityDataPacket.setRuntimeEntityId(this.bindEntity.getGeyserId());
GeyserDirtyMetadata data = this.bindEntity.getDirtyMetadata();
GeyserDirtyMetadata cloneData = GSON.fromJson(GSON.toJson(data), GeyserDirtyMetadata.class);
cloneData.put(EntityDataTypes.NAME, this.title);
cloneData.put(EntityDataTypes.NPC_DATA, skinData);
cloneData.put(EntityDataTypes.ACTIONS, actionJson);
cloneData.put(EntityDataTypes.HAS_NPC, true);
cloneData.put(EntityDataTypes.INTERACT_TEXT, this.dialogue);
cloneData.apply(setEntityDataPacket.getMetadata());
player.sendUpstreamPacket(setEntityDataPacket);
NpcDialoguePacket npcDialoguePacket = new NpcDialoguePacket();
npcDialoguePacket.setUniqueEntityId(this.bindEntity.getGeyserId());
npcDialoguePacket.setAction(NpcDialoguePacket.Action.OPEN);
npcDialoguePacket.setDialogue(this.dialogue);
npcDialoguePacket.setNpcName(this.title);
npcDialoguePacket.setSceneName(this.sceneName);
player.sendUpstreamPacket(setEntityDataPacket);
npcDialoguePacket.setActionJson(this.actionJson);
player.sendUpstreamPacket(npcDialoguePacket);
NpcDialogueForms.addNpcDialogueForm(player, this);
}
public void close(GeyserSession player) {
NpcDialoguePacket npcDialoguePacket = new NpcDialoguePacket();
npcDialoguePacket.setUniqueEntityId(this.bindEntity.getGeyserId());
npcDialoguePacket.setAction(NpcDialoguePacket.Action.CLOSE);
npcDialoguePacket.setDialogue(this.dialogue);
npcDialoguePacket.setNpcName(this.title);
npcDialoguePacket.setSceneName(this.sceneName);
npcDialoguePacket.setActionJson(this.actionJson);
player.sendUpstreamPacket(npcDialoguePacket);
SetEntityDataPacket setEntityDataPacket = new SetEntityDataPacket();
setEntityDataPacket.setRuntimeEntityId(this.bindEntity.getGeyserId());
GeyserDirtyMetadata data = this.bindEntity.getDirtyMetadata();
GeyserDirtyMetadata cloneData = GSON.fromJson(GSON.toJson(data), GeyserDirtyMetadata.class);
cloneData.apply(setEntityDataPacket.getMetadata());
NpcDialogueForms.removeNpcDialogueForm(player, this);
}
}

View File

@@ -0,0 +1,29 @@
package me.zimzaza4.geyserutils.geyser.form;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.geysermc.geyser.session.GeyserSession;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class NpcDialogueForms {
private static final Map<GeyserSession, NpcDialogueForm> npcDialogueForms = new HashMap<>();
public static void removeNpcDialogueForm(GeyserSession session, NpcDialogueForm form) {
form.closeHandler().run();
npcDialogueForms.remove(session);
}
public static NpcDialogueForm getOpenNpcDialogueForms(GeyserSession session) {
return npcDialogueForms.get(session);
}
public static void addNpcDialogueForm(GeyserSession session, NpcDialogueForm form) {
npcDialogueForms.put(session, form);
}
}

View File

@@ -0,0 +1,43 @@
package me.zimzaza4.geyserutils.geyser.form.element;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import lombok.Value;
import lombok.experimental.Accessors;
import me.zimzaza4.geyserutils.common.form.element.NpcDialogueButton;
import java.util.List;
@Value
@Accessors( fluent = true )
public class Button {
String text;
List<String> commands;
NpcDialogueButton.ButtonMode mode;
Runnable click;
public JsonObject toJsonObject() {
JsonObject button = new JsonObject();
button.addProperty( "button_name", this.text );
JsonArray data = new JsonArray();
for ( String command : this.commands ) {
JsonObject cmdLine = new JsonObject();
cmdLine.addProperty( "cmd_line", command );
cmdLine.addProperty( "cmd_ver", 19 );
data.add( cmdLine );
}
button.add( "data", data );
button.addProperty( "mode", this.mode.ordinal() );
button.addProperty( "text", "" );
button.addProperty( "type", 1 );
return button;
}
}

View File

@@ -0,0 +1,50 @@
package me.zimzaza4.geyserutils.geyser.translator;
import me.zimzaza4.geyserutils.common.form.element.NpcDialogueButton;
import me.zimzaza4.geyserutils.geyser.form.NpcDialogueForm;
import me.zimzaza4.geyserutils.geyser.form.NpcDialogueForms;
import me.zimzaza4.geyserutils.geyser.form.element.Button;
import org.cloudburstmc.protocol.bedrock.data.NpcRequestType;
import org.cloudburstmc.protocol.bedrock.packet.NpcRequestPacket;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
public class NPCFormResponseTranslator extends PacketTranslator<NpcRequestPacket> {
@Override
public void translate(GeyserSession geyserSession, NpcRequestPacket packet) {
NpcDialogueForm form = NpcDialogueForms.getOpenNpcDialogueForms(geyserSession);
if (form == null) {
return;
}
if (form.dialogueButtons().isEmpty()) {
if (packet.getRequestType().equals(NpcRequestType.EXECUTE_CLOSING_COMMANDS)) {
NpcDialogueForms.removeNpcDialogueForm(geyserSession, form);
}
return;
}
System.out.println(packet);
Button button = form.dialogueButtons().get(packet.getActionType());
if (button == null) {
return;
}
if ((button.mode().equals(NpcDialogueButton.ButtonMode.ON_ENTER) && packet.getRequestType().equals(NpcRequestType.EXECUTE_OPENING_COMMANDS)) ||
(button.mode().equals(NpcDialogueButton.ButtonMode.BUTTON_MODE) && packet.getRequestType().equals(NpcRequestType.EXECUTE_COMMAND_ACTION)) ||
(button.mode().equals(NpcDialogueButton.ButtonMode.ON_EXIT) && packet.getRequestType().equals(NpcRequestType.EXECUTE_CLOSING_COMMANDS))) {
button.click().run();
if (!form.hasNextForm()) {
form.close(geyserSession);
}
}
}
}

View File

@@ -0,0 +1,6 @@
name: GeyserUtils
id: geyserutils
main: me.zimzaza4.geyserutils.geyser.GeyserUtils
api: 1.0.0
version: 1.0.0
authors: [zimzaza4]

24
pom.xml Normal file
View File

@@ -0,0 +1,24 @@
<?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>
<groupId>me.zimzaza4</groupId>
<artifactId>GeyserUtils</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>common</module>
<module>geyser</module>
<module>spigot</module>
<module>velocity</module>
</modules>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

86
spigot/pom.xml Normal file
View File

@@ -0,0 +1,86 @@
<?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>
<groupId>me.zimzaza4</groupId>
<artifactId>geyserutils-spigot</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>geyserutils-spigot</name>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<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>papermc-repo</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.destroystokyo.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.12.2-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>
<dependency>
<groupId>org.geysermc.floodgate</groupId>
<artifactId>api</artifactId>
<version>2.2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,51 @@
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.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;
@Override
public void onEnable() {
// Plugin startup logic
instance = this;
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;
if (NpcDialogueForm.FORMS.containsKey(response.getFormId())) {
BiConsumer<String, Integer> handler = NpcDialogueForm.FORMS.get(response.getFormId()).handler();
if (handler != null) {
handler.accept(response.getFormId(), response.getButtonId());
}
NpcDialogueForm.FORMS.remove(response.getFormId());
}
}
}
});
}
@Override
public void onDisable() {
// Plugin shutdown logic
}
}

View File

@@ -0,0 +1,18 @@
package me.zimzaza4.geyserutils.spigot.api;
import me.zimzaza4.geyserutils.common.channel.GeyserUtilsChannels;
import me.zimzaza4.geyserutils.common.packet.CameraShakePacket;
import me.zimzaza4.geyserutils.common.util.CustomPayloadPacketUtils;
import me.zimzaza4.geyserutils.spigot.GeyserUtils;
import org.bukkit.entity.Player;
import java.util.concurrent.CompletableFuture;
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)));
}
}

View File

@@ -0,0 +1,74 @@
package me.zimzaza4.geyserutils.spigot.api.form;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
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.util.CustomPayloadPacketUtils;
import me.zimzaza4.geyserutils.spigot.GeyserUtils;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.geysermc.floodgate.api.player.FloodgatePlayer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.BiConsumer;
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
@Accessors( fluent = true )
public class NpcDialogueForm {
public static Map<String, NpcDialogueForm> FORMS = new HashMap<>();
String title;
String dialogue;
String skinData;
Entity bindEntity;
boolean hasNextForm = false;
List<NpcDialogueButton> buttons;
BiConsumer<String, Integer> handler;
public void send(FloodgatePlayer floodgatePlayer) {
UUID formId = UUID.randomUUID();
NpcDialogueFormDataPacket data = new NpcDialogueFormDataPacket(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));
new BukkitRunnable() {
@Override
public void run() {
if (!FORMS.containsKey(formId.toString())) {
this.cancel();
}
if (!p.isOnline()) {
FORMS.remove(formId.toString());
}
}
}.runTaskTimerAsynchronously(GeyserUtils.getInstance(), 10, 10);
}
}
public static void closeForm(FloodgatePlayer floodgatePlayer) {
NpcDialogueFormDataPacket data = new NpcDialogueFormDataPacket(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));
}
}
}

View File

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

103
velocity/pom.xml Normal file
View File

@@ -0,0 +1,103 @@
<?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>
<groupId>me.zimzaza4</groupId>
<artifactId>geyserutils-velocity</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>geyserutils-velocity</name>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<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.codehaus.mojo</groupId>
<artifactId>templating-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>filter-src</id>
<goals>
<goal>filter-sources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.9.1</version>
<dependencies>
<dependency>
<groupId>net.trajano.wagon</groupId>
<artifactId>wagon-git</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.maven.doxia</groupId>
<artifactId>doxia-module-markdown</artifactId>
<version>1.9.1</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<tagNameFormat>@{project.version}</tagNameFormat>
<scmCommentPrefix xml:space="preserve">[RELEASE] </scmCommentPrefix>
<goals>install deploy site-deploy
</goals> <!-- install is here to fix javadoc generation in multi-module projects -->
<releaseProfiles>release</releaseProfiles>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>papermc-repo</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId>
<version>3.2.0-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,33 @@
package me.zimzaza4.geyserutils.velocity;
import com.google.inject.Inject;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
import me.zimzaza4.geyserutils.common.channel.GeyserUtilsChannels;
import org.slf4j.Logger;
import java.nio.file.Path;
@Plugin(id = "geyserutils",
name = "GeyserUtils",
version = "1.0.0",
description = "nooo",
authors = {"zimzaza4"}
)
public class GeyserUtils {
private final ProxyServer server;
@Inject
public GeyserUtils(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
this.server = server;
}
@Subscribe
public void onProxyInitialization(ProxyInitializeEvent event) {
server.getChannelRegistrar().register(MinecraftChannelIdentifier.from(GeyserUtilsChannels.MAIN));
}
}