feat: add local

Signed-off-by: MiaoWoo <admin@yumc.pw>
master
MiaoWoo 2022-06-24 09:08:45 +00:00
parent 20cbb091ee
commit 67336e23f5
4 changed files with 321 additions and 93 deletions

31
pom.xml
View File

@ -7,37 +7,6 @@
<version>1.9.7</version>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<configuration>
<failOnError>false</failOnError>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<ciManagement>
<system>Jenkins</system>

View File

@ -23,67 +23,54 @@ import java.util.UUID;
*/
public class C {
public static boolean init;
private static boolean above_1_16 = false;
private static Class<?> nmsIChatBaseComponent;
private static Constructor<?> packetTypeConstructor;
private static Method chatSerializer;
private static Method getHandle;
private static Method nmsChatMessageTypeClassValueOf;
private static String version;
private static boolean newversion;
private static Field playerConnection;
private static Method sendPacket;
private static Object[] chatMessageTypes;
static {
try {
version = getNMSVersion();
Integer subVersion = Integer.parseInt(version.split("_")[1]);
newversion = subVersion > 7;
Class<?> nmsChatSerializer = subVersion < 17 ?
Class.forName(a(newversion ? "IChatBaseComponent$ChatSerializer" : "ChatSerializer")) :
Class.forName("net.minecraft.network.chat.IChatBaseComponent$ChatSerializer");
chatSerializer = nmsChatSerializer.getMethod("a", String.class);
nmsIChatBaseComponent = subVersion < 17 ?
Class.forName(a("IChatBaseComponent")) :
Class.forName("net.minecraft.network.chat.IChatBaseComponent");
Class<?> packetType = subVersion < 17 ?
Class.forName(a("PacketPlayOutChat")) :
Class.forName("net.minecraft.network.protocol.game.PacketPlayOutChat");
Arrays.stream(packetType.getConstructors()).forEach(c -> {
if (c.getParameterTypes().length == 2) {
packetTypeConstructor = c;
try {
version = getNMSVersion();
Integer subVersion = Integer.parseInt(version.split("_")[1]);
newversion = subVersion > 7;
Class<?> nmsChatSerializer = subVersion < 17 ?
Class.forName(a(newversion ? "IChatBaseComponent$ChatSerializer" : "ChatSerializer")) :
Class.forName("net.minecraft.network.chat.IChatBaseComponent$ChatSerializer");
chatSerializer = nmsChatSerializer.getMethod("a", String.class);
nmsIChatBaseComponent = subVersion < 17 ?
Class.forName(a("IChatBaseComponent")) :
Class.forName("net.minecraft.network.chat.IChatBaseComponent");
Class<?> packetType = subVersion < 17 ?
Class.forName(a("PacketPlayOutChat")) :
Class.forName("net.minecraft.network.protocol.game.PacketPlayOutChat");
Arrays.stream(packetType.getConstructors()).forEach(c -> {
if (c.getParameterTypes().length == 2) {
packetTypeConstructor = c;
}
if (c.getParameterTypes().length == 3) {
packetTypeConstructor = c;
}
});
Class<?> typeCraftPlayer = Class.forName(b("entity.CraftPlayer"));
Class<?> typeNMSPlayer = subVersion < 17 ? Class.forName(a("EntityPlayer")) : Class.forName("net.minecraft.server.level.EntityPlayer");
Class<?> typePlayerConnection = subVersion < 17 ? Class.forName(a("PlayerConnection")) : Class.forName("net.minecraft.server.network.PlayerConnection");
getHandle = typeCraftPlayer.getMethod("getHandle");
playerConnection = subVersion < 17 ? typeNMSPlayer.getField("playerConnection") : typeNMSPlayer.getField("b");
if (subVersion < 17) {
sendPacket = typePlayerConnection.getMethod("sendPacket", Class.forName(a("Packet")));
} else if (subVersion == 17) {
sendPacket = typePlayerConnection.getMethod("sendPacket", Class.forName("net.minecraft.network.protocol.Packet"));
} else {
sendPacket = typePlayerConnection.getMethod("a", Class.forName("net.minecraft.network.protocol.Packet"));
}
if (c.getParameterTypes().length == 3) {
packetTypeConstructor = c;
above_1_16 = true;
}
});
Class<?> nmsChatMessageTypeClass = packetTypeConstructor.getParameterTypes()[1];
if (nmsChatMessageTypeClass.isEnum()) {
chatMessageTypes = nmsChatMessageTypeClass.getEnumConstants();
} else {
switch (nmsChatMessageTypeClass.getName()) {
case "int":
nmsChatMessageTypeClass = Integer.class;
break;
case "byte":
nmsChatMessageTypeClass = Byte.class;
break;
}
nmsChatMessageTypeClassValueOf = nmsChatMessageTypeClass.getDeclaredMethod("valueOf", String.class);
}
Class<?> typeCraftPlayer = Class.forName(b("entity.CraftPlayer"));
Class<?> typeNMSPlayer = subVersion < 17 ? Class.forName(a("EntityPlayer")) : Class.forName("net.minecraft.server.level.EntityPlayer");
Class<?> typePlayerConnection = subVersion < 17 ? Class.forName(a("PlayerConnection")) : Class.forName("net.minecraft.server.network.PlayerConnection");
getHandle = typeCraftPlayer.getMethod("getHandle");
playerConnection = subVersion < 17 ? typeNMSPlayer.getField("playerConnection") : typeNMSPlayer.getField("b");
if (subVersion < 17) {
sendPacket = typePlayerConnection.getMethod("sendPacket", Class.forName(a("Packet")));
} else if (subVersion == 17) {
sendPacket = typePlayerConnection.getMethod("sendPacket", Class.forName("net.minecraft.network.protocol.Packet"));
} else {
sendPacket = typePlayerConnection.getMethod("a", Class.forName("net.minecraft.network.protocol.Packet"));
} catch (Exception ex) {
Log.d(ex);
Chat.getBukkitChatInvoke();
}
init = true;
} catch (Exception e) {
@ -122,17 +109,7 @@ public class C {
* 2. ActionBar
*/
public static void sendJson(org.bukkit.entity.Player receivingPacket, String json, int type) {
try {
Object serialized = chatSerializer.invoke(null, json);
Object player = getHandle.invoke(receivingPacket);
Object connection = playerConnection.get(player);
Object typeObj = chatMessageTypes == null ? nmsChatMessageTypeClassValueOf.invoke(null, String.valueOf(type)) : chatMessageTypes[type];
sendPacket.invoke(connection, above_1_16
? packetTypeConstructor.newInstance(serialized, typeObj, receivingPacket.getUniqueId())
: packetTypeConstructor.newInstance(serialized, typeObj));
} catch (Exception ex) {
Log.d("Json发包错误 " + version, ex);
}
Chat.getBukkitChatInvoke().send(receivingPacket, json, type);
}
public static class ActionBar {

View File

@ -0,0 +1,272 @@
package pw.yumc.YumCore.bukkit.compatible;
import lombok.SneakyThrows;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Chat {
private static final String version;
private static final BukkitChatInvoke bukkitChatInvoke;
static {
version = getNMSVersion();
int subVersion = Integer.parseInt(version.split("_")[1]);
if (subVersion >= 19) {
bukkitChatInvoke = new BukkitChatInvoke_1_19();
} else if (subVersion >= 17) {
bukkitChatInvoke = new BukkitChatInvoke_1_17_1();
} else if (subVersion >= 16) {
bukkitChatInvoke = new BukkitChatInvoke_1_16_5();
} else if (subVersion >= 8) {
bukkitChatInvoke = new BukkitChatInvoke_1_8();
} else {
bukkitChatInvoke = new BukkitChatInvoke_1_7_10();
}
bukkitChatInvoke.init();
}
public static BukkitChatInvoke getBukkitChatInvoke() {
return bukkitChatInvoke;
}
/**
* NMS
*
* @return NMS
*/
public static String getNMSVersion() {
return Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
}
public static Class<?> nmsCls(String str) throws ClassNotFoundException {
return Class.forName("net.minecraft.server." + version + "." + str);
}
public static Class<?> obcCls(String str) throws ClassNotFoundException {
return Class.forName("org.bukkit.craftbukkit." + version + "." + str);
}
public static abstract class BukkitChatInvoke {
protected boolean downgrade = false;
protected Method chatSerializer;
protected Constructor<?> packetTypeConstructor;
protected Method getHandle;
protected Field playerConnection;
protected Method sendPacket;
protected Object[] chatMessageTypes;
protected Method componentSerializer;
BukkitChatInvoke() {
init();
}
public void init() {
try {
Class<?> nmsChatSerializerClass = this.getNmsChatSerializerClass();
this.chatSerializer = this.getNmsChatSerializerMethod(nmsChatSerializerClass);
Constructor<?>[] constructors = this.getPacketPlayOutChatClass().getConstructors();
for (Constructor<?> constructor : constructors) {
if (constructor.getParameterCount() == 2 || constructor.getParameterCount() == 3) {
this.packetTypeConstructor = constructor;
if (this.isMatchPacketPlayOutChatClassConstructor(constructor)) {
break;
}
}
}
this.getHandle = this.getGetHandleMethod();
this.playerConnection = this.getPlayerConnectionField(this.getHandle.getReturnType());
this.sendPacket = this.getSendPacketMethod(this.playerConnection.getType(), this.getPacketClass());
} catch (Throwable ex) {
this.downgrade = true;
try {
this.componentSerializer = Class.forName("net.md_5.bungee.chat.ComponentSerializer").getMethod("parse", String.class);
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
}
}
}
@SneakyThrows
void json(Player receivingPacket, String json) {
if (this.downgrade) {
receivingPacket.spigot().sendMessage((BaseComponent[]) this.componentSerializer.invoke(null, json));
} else {
this.send(receivingPacket, json, 0);
}
}
@SneakyThrows
void send(Player receivingPacket, String json, int type) {
this.sendPacket(receivingPacket, this.getPacketPlayOutChat(receivingPacket, json, type));
}
@SneakyThrows
void sendPacket(Player receivingPacket, Object packet) {
this.sendPacket.invoke(playerConnection.get(getHandle.invoke(receivingPacket)), packet);
}
abstract boolean isMatchPacketPlayOutChatClassConstructor(Constructor<?> constructor);
abstract Class<?> getNmsChatSerializerClass();
abstract Method getNmsChatSerializerMethod(Class<?> nmsChatSerializerClass);
abstract Class<?> getPacketPlayOutChatClass();
abstract Field getPlayerConnectionField(Class<?> nmsEntityPlayerClass);
abstract Method getGetHandleMethod();
abstract Class<?> getPacketClass();
abstract Method getSendPacketMethod(Class<?> playerConnectionClass, Class<?> packetClass);
abstract Object getPacketPlayOutChat(Player player, String json, int type);
}
public static class BukkitChatInvokeBase extends BukkitChatInvoke {
@Override
protected boolean isMatchPacketPlayOutChatClassConstructor(Constructor<?> constructor) {
Class<?>[] types = constructor.getParameterTypes();
if (types[1].isEnum()) {
this.chatMessageTypes = types[1].getEnumConstants();
return true;
}
return types[1].getName().equals("int");
}
@Override
@SneakyThrows
Class<?> getNmsChatSerializerClass() {
return nmsCls("ChatSerializer");
}
@Override
@SneakyThrows
Method getNmsChatSerializerMethod(Class<?> nmsChatSerializerClass) {
return nmsChatSerializerClass.getMethod("a", String.class);
}
@Override
@SneakyThrows
Class<?> getPacketPlayOutChatClass() {
return nmsCls("PacketPlayOutChat");
}
@Override
@SneakyThrows
Field getPlayerConnectionField(Class<?> nmsEntityPlayerClass) {
return nmsEntityPlayerClass.getField("playerConnection");
}
@Override
@SneakyThrows
Method getGetHandleMethod() {
return obcCls("entity.CraftPlayer").getMethod("getHandle");
}
@Override
@SneakyThrows
Class<?> getPacketClass() {
return nmsCls("Packet");
}
@Override
@SneakyThrows
Method getSendPacketMethod(Class<?> playerConnectionClass, Class<?> packetClass) {
return playerConnectionClass.getMethod("sendPacket", packetClass);
}
@Override
@SneakyThrows
Object getPacketPlayOutChat(Player player, String json, int type) {
return packetTypeConstructor.newInstance(this.chatSerializer.invoke(null, json), type);
}
}
public static class BukkitChatInvoke_1_7_10 extends BukkitChatInvokeBase {
}
public static class BukkitChatInvoke_1_8 extends BukkitChatInvoke_1_7_10 {
@Override
@SneakyThrows
Object getPacketPlayOutChat(Player player, String json, int type) {
return packetTypeConstructor.newInstance(this.chatSerializer.invoke(null, json), this.chatMessageTypes[type]);
}
@Override
@SneakyThrows
Class<?> getNmsChatSerializerClass() {
return nmsCls("IChatBaseComponent$ChatSerializer");
}
}
public static class BukkitChatInvoke_1_16_5 extends BukkitChatInvoke_1_8 {
@Override
@SneakyThrows
Object getPacketPlayOutChat(Player player, String json, int type) {
return packetTypeConstructor.newInstance(this.chatSerializer.invoke(null, json), this.chatMessageTypes[type], player.getUniqueId());
}
}
public static class BukkitChatInvoke_1_17_1 extends BukkitChatInvoke_1_16_5 {
@Override
@SneakyThrows
Class<?> getPacketPlayOutChatClass() {
return Class.forName("net.minecraft.network.protocol.game.PacketPlayOutChat");
}
@Override
@SneakyThrows
Class<?> getNmsChatSerializerClass() {
return Class.forName("net.minecraft.network.chat.IChatBaseComponent$ChatSerializer");
}
@Override
@SneakyThrows
Field getPlayerConnectionField(Class<?> nmsEntityPlayerClass) {
return nmsEntityPlayerClass.getField("b");
}
@Override
@SneakyThrows
Class<?> getPacketClass() {
return Class.forName("net.minecraft.network.protocol.Packet");
}
}
public static class BukkitChatInvoke_1_19 extends BukkitChatInvoke_1_17_1 {
@Override
protected boolean isMatchPacketPlayOutChatClassConstructor(Constructor<?> constructor) {
Class<?>[] types = constructor.getParameterTypes();
return types[0] == String.class && types[1] == int.class;
}
@Override
@SneakyThrows
Method getSendPacketMethod(Class<?> playerConnectionClass, Class<?> packetClass) {
return playerConnectionClass.getMethod("a", packetClass);
}
@Override
@SneakyThrows
Class<?> getPacketPlayOutChatClass() {
return Class.forName("net.minecraft.network.protocol.game.ClientboundSystemChatPacket");
}
@Override
@SneakyThrows
Object getPacketPlayOutChat(Player player, String json, int type) {
Object component = this.chatSerializer.invoke(null, json);
return this.packetTypeConstructor.newInstance(component, type == 0 ? 1 : type);
}
}
}

View File

@ -108,7 +108,7 @@ public class SubscribeTask implements Runnable, Listener {
@EventHandler
public void onJoin(PlayerJoinEvent e) {
final Player player = e.getPlayer();
if (player.isOp() && updateFile.isUpdated()) {
if (player.isOp() && versionInfo.hasNewVersion() && updateFile.isUpdated()) {
Bukkit.getScheduler().runTaskLater(instance, () -> versionInfo.notify(player), 10);
}
}
@ -255,10 +255,13 @@ public class SubscribeTask implements Runnable, Listener {
*/
private Document document;
private boolean hasNewVersion;
public VersionInfo(Plugin plugin, String branch, boolean isSecret) {
this.name = plugin.getName();
this.version = plugin.getDescription().getVersion().split("-")[0];
this.info = String.format(isSecret ? pom : url, name, branch);
this.hasNewVersion = false;
}
/**
@ -372,7 +375,10 @@ public class SubscribeTask implements Runnable, Listener {
Log.console("§4注意: §c当前版本为开发版本 且未开启全局调试 已自动下载最新稳定版!");
return result;
}
if (needUpdate(result, version)) {return result;}
if (needUpdate(result, version)) {
this.hasNewVersion = true;
return result;
}
} catch (Exception e) {
Log.d(e);
}
@ -382,5 +388,9 @@ public class SubscribeTask implements Runnable, Listener {
public void update() throws ParserConfigurationException, IOException, SAXException {
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(info);
}
public boolean hasNewVersion() {
return hasNewVersion;
}
}
}