mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-19 15:09:25 +00:00
533 lines
24 KiB
Diff
533 lines
24 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: violetc <58360096+s-yh-china@users.noreply.github.com>
|
|
Date: Tue, 26 Sep 2023 19:00:41 +0800
|
|
Subject: [PATCH] Leaves Protocol Core
|
|
|
|
Original license: GPLv3
|
|
Original project: https://github.com/LeavesMC/Leaves
|
|
|
|
diff --git a/src/main/java/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java b/src/main/java/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java
|
|
index 975da2529d18391ed4ecc7359a2d7319129bd872..ae5590b015a2b018188bd7a45b44ec4d4af048a5 100644
|
|
--- a/src/main/java/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java
|
|
+++ b/src/main/java/net/minecraft/network/protocol/common/ServerboundCustomPayloadPacket.java
|
|
@@ -20,7 +20,12 @@ public record ServerboundCustomPayloadPacket(CustomPacketPayload payload) implem
|
|
|
|
private static CustomPacketPayload readPayload(ResourceLocation id, FriendlyByteBuf buf) {
|
|
FriendlyByteBuf.Reader<? extends CustomPacketPayload> packetdataserializer_a = (FriendlyByteBuf.Reader) ServerboundCustomPayloadPacket.KNOWN_TYPES.get(id);
|
|
-
|
|
+ // Leaves start - protocol
|
|
+ CustomPacketPayload leavesPayload = top.leavesmc.leaves.protocol.core.LeavesProtocolManager.getPayload(id, buf);
|
|
+ if (leavesPayload != null) {
|
|
+ return leavesPayload;
|
|
+ }
|
|
+ // Leaves end - protocol
|
|
return (CustomPacketPayload) (packetdataserializer_a != null ? (CustomPacketPayload) packetdataserializer_a.apply(buf) : readUnknownPayload(id, buf));
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
index dfe06a0f0d3c6ed0ce89c632a8b2cd050cc2e6a7..32cbb5a838152616e049f9a0e2623aab9a01c55a 100644
|
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
@@ -1558,6 +1558,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
|
GameTestTicker.SINGLETON.tick();
|
|
}
|
|
|
|
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleTick(); // Leaves - protocol
|
|
+
|
|
for (int i = 0; i < this.tickables.size(); ++i) {
|
|
((Runnable) this.tickables.get(i)).run();
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
|
index 1eef67ca260434e8627dba35792a7c5d97df891f..69be29fcd38876e70db9df440869bee1b3c75f00 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
|
@@ -135,6 +135,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
|
|
|
@Override
|
|
public void handleCustomPayload(ServerboundCustomPayloadPacket packet) {
|
|
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePayload(player, packet.payload()); // Leaves - protocol
|
|
// Paper start - handle brand payload packet
|
|
if (packet.payload() instanceof net.minecraft.network.protocol.common.custom.BrandPayload brandPayload) {
|
|
this.player.clientBrandName = brandPayload.brand();
|
|
@@ -152,6 +153,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
|
String channels = payload.toString(com.google.common.base.Charsets.UTF_8);
|
|
for (String channel : channels.split("\0")) {
|
|
this.getCraftPlayer().addChannel(channel);
|
|
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleMinecraftRegister(channel, player); // Leaves - protocol
|
|
}
|
|
} catch (Exception ex) {
|
|
ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex);
|
|
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
index d20eed35c85cf5118206dbf9ca2c706b51d4460e..963d5b4d2bc44c32d23da0f45480e0b0bd293ec2 100644
|
|
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
@@ -342,6 +342,7 @@ public abstract class PlayerList {
|
|
}
|
|
|
|
player.didPlayerJoinEvent = true; // Gale - EMC - do not process chat/commands before player has joined
|
|
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol
|
|
|
|
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
|
|
|
|
@@ -601,6 +602,7 @@ public abstract class PlayerList {
|
|
return this.remove(entityplayer, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? entityplayer.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(entityplayer.getDisplayName())));
|
|
}
|
|
public net.kyori.adventure.text.Component remove(ServerPlayer entityplayer, net.kyori.adventure.text.Component leaveMessage) {
|
|
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerLeave(entityplayer); // Leaves - protocol
|
|
// Paper end
|
|
org.purpurmc.purpur.task.BossBarTask.removeFromAll(entityplayer.getBukkitEntity()); // Purpur
|
|
ServerLevel worldserver = entityplayer.serverLevel();
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
index 76621b258b2d63099959e77d113f279aa71d7d4f..c5308e8104fe16d1c529e220e9714770a470fdbd 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
@@ -487,6 +487,7 @@ public final class CraftServer implements Server {
|
|
MapPalette.setMapColorCache(new CraftMapColorCache(this.logger));
|
|
}
|
|
datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
|
|
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.init(); // Leaves - protocol
|
|
}
|
|
|
|
public boolean getCommandBlockOverride(String command) {
|
|
@@ -1092,6 +1093,7 @@ public final class CraftServer implements Server {
|
|
org.purpurmc.purpur.PurpurConfig.registerCommands(); // Purpur
|
|
this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*");
|
|
this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions");
|
|
+ top.leavesmc.leaves.protocol.core.LeavesProtocolManager.handleServerReload(); // Leaves - protocol
|
|
|
|
int pollCount = 0;
|
|
|
|
diff --git a/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocol.java b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocol.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..64a1d25973b032e8cab64bbffa6824a131676773
|
|
--- /dev/null
|
|
+++ b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocol.java
|
|
@@ -0,0 +1,16 @@
|
|
+package top.leavesmc.leaves.protocol.core;
|
|
+
|
|
+import java.lang.annotation.ElementType;
|
|
+import java.lang.annotation.Retention;
|
|
+import java.lang.annotation.RetentionPolicy;
|
|
+import java.lang.annotation.Target;
|
|
+
|
|
+@Target(ElementType.TYPE)
|
|
+@Retention(RetentionPolicy.RUNTIME)
|
|
+public @interface LeavesProtocol {
|
|
+
|
|
+ String namespace() default "minecraft";
|
|
+
|
|
+ String[] namespaces() default {};
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocolManager.java b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocolManager.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..eb8bec80870bbe8a6b6aea324376485875a30d00
|
|
--- /dev/null
|
|
+++ b/src/main/java/top/leavesmc/leaves/protocol/core/LeavesProtocolManager.java
|
|
@@ -0,0 +1,292 @@
|
|
+package top.leavesmc.leaves.protocol.core;
|
|
+
|
|
+import net.minecraft.network.FriendlyByteBuf;
|
|
+import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
|
+import net.minecraft.resources.ResourceLocation;
|
|
+import net.minecraft.server.level.ServerPlayer;
|
|
+import org.apache.commons.lang.ArrayUtils;
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+
|
|
+import java.io.File;
|
|
+import java.io.IOException;
|
|
+import java.lang.reflect.Constructor;
|
|
+import java.lang.reflect.InvocationTargetException;
|
|
+import java.lang.reflect.Method;
|
|
+import java.lang.reflect.Modifier;
|
|
+import java.net.URL;
|
|
+import java.net.URLDecoder;
|
|
+import java.nio.charset.StandardCharsets;
|
|
+import java.util.ArrayList;
|
|
+import java.util.Collections;
|
|
+import java.util.Enumeration;
|
|
+import java.util.HashMap;
|
|
+import java.util.HashSet;
|
|
+import java.util.List;
|
|
+import java.util.Map;
|
|
+import java.util.Set;
|
|
+
|
|
+public class LeavesProtocolManager {
|
|
+
|
|
+ private static final Map<LeavesProtocol, Map<ProtocolHandler.PayloadReceiver, Constructor<? extends CustomPacketPayload>>> KNOWN_TYPES = new HashMap<>();
|
|
+ private static final Map<LeavesProtocol, Map<ProtocolHandler.PayloadReceiver, Method>> KNOW_RECEIVERS = new HashMap<>();
|
|
+
|
|
+ private static final List<Method> TICKERS = new ArrayList<>();
|
|
+ private static final List<Method> PLAYER_JOIN = new ArrayList<>();
|
|
+ private static final List<Method> PLAYER_LEAVE = new ArrayList<>();
|
|
+ private static final List<Method> RELOAD_SERVER = new ArrayList<>();
|
|
+ private static final Map<ProtocolHandler.MinecraftRegister, Method> MINECRAFT_REGISTER = new HashMap<>();
|
|
+
|
|
+ public static void init() {
|
|
+ for (Class<?> clazz : getClasses("top.leavesmc.leaves.protocol")) {
|
|
+ final LeavesProtocol protocol = clazz.getAnnotation(LeavesProtocol.class);
|
|
+ if (protocol != null) {
|
|
+ Set<Method> methods;
|
|
+ try {
|
|
+ Method[] publicMethods = clazz.getMethods();
|
|
+ Method[] privateMethods = clazz.getDeclaredMethods();
|
|
+ methods = new HashSet<>(publicMethods.length + privateMethods.length, 1.0f);
|
|
+ Collections.addAll(methods, publicMethods);
|
|
+ Collections.addAll(methods, privateMethods);
|
|
+ } catch (NoClassDefFoundError e) {
|
|
+ e.printStackTrace();
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ Map<ProtocolHandler.PayloadReceiver, Constructor<? extends CustomPacketPayload>> map = new HashMap<>();
|
|
+ for (final Method method : methods) {
|
|
+ if (method.isBridge() || method.isSynthetic() || !Modifier.isStatic(method.getModifiers())) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ method.setAccessible(true);
|
|
+
|
|
+ final ProtocolHandler.Init init = method.getAnnotation(ProtocolHandler.Init.class);
|
|
+ if (init != null) {
|
|
+ try {
|
|
+ method.invoke(null);
|
|
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ final ProtocolHandler.PayloadReceiver receiver = method.getAnnotation(ProtocolHandler.PayloadReceiver.class);
|
|
+ if (receiver != null) {
|
|
+ try {
|
|
+ map.put(receiver, receiver.payload().getConstructor(ResourceLocation.class, FriendlyByteBuf.class));
|
|
+ } catch (NoSuchMethodException e) {
|
|
+ e.printStackTrace();
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (!KNOW_RECEIVERS.containsKey(protocol)) {
|
|
+ KNOW_RECEIVERS.put(protocol, new HashMap<>());
|
|
+ }
|
|
+
|
|
+ KNOW_RECEIVERS.get(protocol).put(receiver, method);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ final ProtocolHandler.Ticker ticker = method.getAnnotation(ProtocolHandler.Ticker.class);
|
|
+ if (ticker != null) {
|
|
+ TICKERS.add(method);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ final ProtocolHandler.PlayerJoin playerJoin = method.getAnnotation(ProtocolHandler.PlayerJoin.class);
|
|
+ if (playerJoin != null) {
|
|
+ PLAYER_JOIN.add(method);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ final ProtocolHandler.PlayerLeave playerLeave = method.getAnnotation(ProtocolHandler.PlayerLeave.class);
|
|
+ if (playerLeave != null) {
|
|
+ PLAYER_LEAVE.add(method);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ final ProtocolHandler.ReloadServer reloadServer = method.getAnnotation(ProtocolHandler.ReloadServer.class);
|
|
+ if (reloadServer != null) {
|
|
+ RELOAD_SERVER.add(method);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ final ProtocolHandler.MinecraftRegister minecraftRegister = method.getAnnotation(ProtocolHandler.MinecraftRegister.class);
|
|
+ if (minecraftRegister != null) {
|
|
+ MINECRAFT_REGISTER.put(minecraftRegister, method);
|
|
+ }
|
|
+ }
|
|
+ KNOWN_TYPES.put(protocol, map);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static CustomPacketPayload getPayload(ResourceLocation id, FriendlyByteBuf buf) {
|
|
+ for (LeavesProtocol protocol : KNOWN_TYPES.keySet()) {
|
|
+ if (!protocol.namespace().equals(id.getNamespace()) && !ArrayUtils.contains(protocol.namespaces(), id.getNamespace())) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ Map<ProtocolHandler.PayloadReceiver, Constructor<? extends CustomPacketPayload>> map = KNOWN_TYPES.get(protocol);
|
|
+ for (ProtocolHandler.PayloadReceiver receiver : map.keySet()) {
|
|
+ if (receiver.ignoreId() || receiver.payloadId().equals(id.getPath()) || ArrayUtils.contains(receiver.payloadIds(), id.getPath())) {
|
|
+ try {
|
|
+ return map.get(receiver).newInstance(id, buf);
|
|
+ } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ public static void handlePayload(ServerPlayer player, CustomPacketPayload payload) {
|
|
+ for (LeavesProtocol protocol : KNOW_RECEIVERS.keySet()) {
|
|
+ if (!protocol.namespace().equals(payload.id().getNamespace()) && !ArrayUtils.contains(protocol.namespaces(), payload.id().getNamespace())) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ Map<ProtocolHandler.PayloadReceiver, Method> map = KNOW_RECEIVERS.get(protocol);
|
|
+ for (ProtocolHandler.PayloadReceiver receiver : map.keySet()) {
|
|
+ if (payload.getClass() == receiver.payload()) {
|
|
+ if (receiver.ignoreId() || receiver.payloadId().equals(payload.id().getPath()) ||
|
|
+ ArrayUtils.contains(receiver.payloadIds(), payload.id().getPath())) {
|
|
+ try {
|
|
+ map.get(receiver).invoke(player, payload);
|
|
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void handleTick() {
|
|
+ if (!TICKERS.isEmpty()) {
|
|
+ try {
|
|
+ for (Method method : TICKERS) {
|
|
+ method.invoke(null);
|
|
+ }
|
|
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void handlePlayerJoin(ServerPlayer player) {
|
|
+ if (!PLAYER_JOIN.isEmpty()) {
|
|
+ try {
|
|
+ for (Method method : PLAYER_JOIN) {
|
|
+ method.invoke(player);
|
|
+ }
|
|
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void handlePlayerLeave(ServerPlayer player) {
|
|
+ if (!PLAYER_LEAVE.isEmpty()) {
|
|
+ try {
|
|
+ for (Method method : PLAYER_LEAVE) {
|
|
+ method.invoke(player);
|
|
+ }
|
|
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void handleServerReload() {
|
|
+ if (!RELOAD_SERVER.isEmpty()) {
|
|
+ try {
|
|
+ for (Method method : RELOAD_SERVER) {
|
|
+ method.invoke(null);
|
|
+ }
|
|
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void handleMinecraftRegister(String channel, ServerPlayer player) {
|
|
+ if (!MINECRAFT_REGISTER.isEmpty()) {
|
|
+ for (ProtocolHandler.MinecraftRegister register : MINECRAFT_REGISTER.keySet()) {
|
|
+ if (register.ignoreId() || register.channelId().equals(channel) ||
|
|
+ ArrayUtils.contains(register.channelIds(), channel)) {
|
|
+ try {
|
|
+ MINECRAFT_REGISTER.get(register).invoke(player);
|
|
+ } catch (InvocationTargetException | IllegalAccessException e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static List<Class<?>> getClasses(String packageName) {
|
|
+ List<Class<?>> classes = new ArrayList<>();
|
|
+ String packageDirName = packageName.replace('.', '/');
|
|
+ Enumeration<URL> dirs;
|
|
+ try {
|
|
+ dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
|
|
+ while (dirs.hasMoreElements()) {
|
|
+ URL url = dirs.nextElement();
|
|
+ findClassInPackageByFile(packageName, URLDecoder.decode(url.getFile(), StandardCharsets.UTF_8), classes);
|
|
+ }
|
|
+ } catch (IOException e) {
|
|
+ throw new RuntimeException(e);
|
|
+ }
|
|
+ return classes;
|
|
+ }
|
|
+
|
|
+ private static void findClassInPackageByFile(String packageName, String filePath, List<Class<?>> classes) {
|
|
+ File dir = new File(filePath);
|
|
+ if (!dir.exists() || !dir.isDirectory()) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ File[] dirFiles = dir.listFiles(file -> file.getName().endsWith("class") || file.isDirectory());
|
|
+ if (dirFiles != null) {
|
|
+ for (File file : dirFiles) {
|
|
+ if (file.isDirectory()) {
|
|
+ if (!file.getName().equals("core")) {
|
|
+ findClassInPackageByFile(packageName + "." + file.getName(), file.getPath(), classes);
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+ String className = file.getName().substring(0, file.getName().length() - 6);
|
|
+ try {
|
|
+ classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
|
|
+ } catch (ClassNotFoundException e) {
|
|
+ throw new RuntimeException(e);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public record EmptyPayload(ResourceLocation id) implements CustomPacketPayload {
|
|
+
|
|
+ public EmptyPayload(ResourceLocation location, FriendlyByteBuf buf) {
|
|
+ this(location);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void write(@NotNull FriendlyByteBuf buf) {
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public record LeavesPayload(FriendlyByteBuf data, ResourceLocation id) implements CustomPacketPayload {
|
|
+
|
|
+ public LeavesPayload(ResourceLocation location, FriendlyByteBuf buf) {
|
|
+ this(new FriendlyByteBuf(buf.readBytes(buf.readableBytes())), location);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void write(FriendlyByteBuf buf) {
|
|
+ buf.writeBytes(data);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolHandler.java b/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolHandler.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..d696f001d2576d1b61cc732c81f22eb52205072b
|
|
--- /dev/null
|
|
+++ b/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolHandler.java
|
|
@@ -0,0 +1,65 @@
|
|
+package top.leavesmc.leaves.protocol.core;
|
|
+
|
|
+import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
|
+
|
|
+import java.lang.annotation.ElementType;
|
|
+import java.lang.annotation.Retention;
|
|
+import java.lang.annotation.RetentionPolicy;
|
|
+import java.lang.annotation.Target;
|
|
+
|
|
+public class ProtocolHandler {
|
|
+
|
|
+ @Target(ElementType.METHOD)
|
|
+ @Retention(RetentionPolicy.RUNTIME)
|
|
+ public @interface Init {
|
|
+
|
|
+ }
|
|
+
|
|
+ @Target(ElementType.METHOD)
|
|
+ @Retention(RetentionPolicy.RUNTIME)
|
|
+ public @interface PayloadReceiver {
|
|
+
|
|
+ Class<? extends CustomPacketPayload> payload();
|
|
+
|
|
+ String[] payloadIds() default {};
|
|
+
|
|
+ String payloadId() default "";
|
|
+
|
|
+ boolean ignoreId() default false;
|
|
+ }
|
|
+
|
|
+ @Target(ElementType.METHOD)
|
|
+ @Retention(RetentionPolicy.RUNTIME)
|
|
+ public @interface Ticker {
|
|
+ int delay() default 0;
|
|
+ }
|
|
+
|
|
+ @Target(ElementType.METHOD)
|
|
+ @Retention(RetentionPolicy.RUNTIME)
|
|
+ public @interface PlayerJoin {
|
|
+
|
|
+ }
|
|
+
|
|
+ @Target(ElementType.METHOD)
|
|
+ @Retention(RetentionPolicy.RUNTIME)
|
|
+ public @interface PlayerLeave {
|
|
+
|
|
+ }
|
|
+
|
|
+ @Target(ElementType.METHOD)
|
|
+ @Retention(RetentionPolicy.RUNTIME)
|
|
+ public @interface ReloadServer {
|
|
+
|
|
+ }
|
|
+
|
|
+ @Target(ElementType.METHOD)
|
|
+ @Retention(RetentionPolicy.RUNTIME)
|
|
+ public @interface MinecraftRegister {
|
|
+
|
|
+ String channelId() default "";
|
|
+
|
|
+ String[] channelIds() default {};
|
|
+
|
|
+ boolean ignoreId() default false;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolUtils.java b/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolUtils.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..5282c5ad3d26d06ab685ddaaf6fd9a4d49559717
|
|
--- /dev/null
|
|
+++ b/src/main/java/top/leavesmc/leaves/protocol/core/ProtocolUtils.java
|
|
@@ -0,0 +1,36 @@
|
|
+package top.leavesmc.leaves.protocol.core;
|
|
+
|
|
+import net.minecraft.network.FriendlyByteBuf;
|
|
+import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket;
|
|
+import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
|
+import net.minecraft.resources.ResourceLocation;
|
|
+import net.minecraft.server.level.ServerPlayer;
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+
|
|
+import java.util.function.Consumer;
|
|
+
|
|
+public class ProtocolUtils {
|
|
+
|
|
+ public static void sendEmptyPayloadPacket(ServerPlayer player, ResourceLocation id) {
|
|
+ player.connection.send(new ClientboundCustomPayloadPacket(new LeavesProtocolManager.EmptyPayload(id)));
|
|
+ }
|
|
+
|
|
+ public static void sendPayloadPacket(ServerPlayer player, ResourceLocation id, Consumer<FriendlyByteBuf> consumer) {
|
|
+ player.connection.send(new ClientboundCustomPayloadPacket(new CustomPacketPayload() {
|
|
+ @Override
|
|
+ public void write(@NotNull FriendlyByteBuf buf) {
|
|
+ consumer.accept(buf);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ @NotNull
|
|
+ public ResourceLocation id() {
|
|
+ return id;
|
|
+ }
|
|
+ }));
|
|
+ }
|
|
+
|
|
+ public static void sendPayloadPacket(ServerPlayer player, CustomPacketPayload payload) {
|
|
+ player.connection.send(new ClientboundCustomPayloadPacket(payload));
|
|
+ }
|
|
+}
|