mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2026-11-04 08:52:09 -05:00
Compare commits
1
Commits
master
...
dmulloy/26.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aca303b228 |
No files matched your search
+1
-1
@@ -12,7 +12,7 @@ plugins {
|
||||
group = "net.dmulloy2"
|
||||
description = "Provides access to the Minecraft protocol"
|
||||
|
||||
val mcVersion = "26.1"
|
||||
val mcVersion = "26.2"
|
||||
val isSnapshot = version.toString().endsWith("-SNAPSHOT")
|
||||
val isJitPack = System.getenv("JITPACK")?.equals("true", ignoreCase = true) ?: false
|
||||
val commitHash = System.getenv("COMMIT_SHA") ?: ""
|
||||
|
||||
@@ -506,7 +506,7 @@ public class PacketType implements Serializable, Cloneable, Comparable<PacketTyp
|
||||
public static final PacketType STRUCT = new PacketType(PROTOCOL, SENDER, 0x3B, "SetStructureBlock", "Struct");
|
||||
public static final PacketType SET_TEST_BLOCK = new PacketType(PROTOCOL, SENDER, 0x3C, "SetTestBlock");
|
||||
public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x3D, "SignUpdate", "UpdateSign", "CPacketUpdateSign");
|
||||
public static final PacketType SPECTATE_ENTITY = new PacketType(PROTOCOL, SENDER, 0x3E, "SpectateEntity");
|
||||
public static final PacketType SPECTATE_ENTITY = new PacketType(PROTOCOL, SENDER, 0x3E, "SpectatorAction", "SpectateEntity");
|
||||
public static final PacketType ARM_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x3F, "Swing", "ArmAnimation", "CPacketAnimation");
|
||||
public static final PacketType SPECTATE = new PacketType(PROTOCOL, SENDER, 0x40, "TeleportToEntity", "Spectate", "CPacketSpectate");
|
||||
public static final PacketType TEST_INSTANCE_BLOCK_ACTION = new PacketType(PROTOCOL, SENDER, 0x41, "TestInstanceBlockAction");
|
||||
|
||||
@@ -35,12 +35,12 @@ public class ProtocolLibrary {
|
||||
/**
|
||||
* The maximum version ProtocolLib has been tested with.
|
||||
*/
|
||||
public static final String MAXIMUM_MINECRAFT_VERSION = "26.1";
|
||||
public static final String MAXIMUM_MINECRAFT_VERSION = "26.2";
|
||||
|
||||
/**
|
||||
* The date (with ISO 8601 or YYYY-MM-DD) when the most recent version (1.21.11) was released.
|
||||
* The date (with ISO 8601 or YYYY-MM-DD) when the most recent version (26.2) was released.
|
||||
*/
|
||||
public static final String MINECRAFT_LAST_RELEASE_DATE = "2026-03-24";
|
||||
public static final String MINECRAFT_LAST_RELEASE_DATE = "2026-06-16";
|
||||
|
||||
private static Plugin plugin;
|
||||
private static ProtocolConfig config;
|
||||
|
||||
@@ -412,8 +412,8 @@ public class PacketRegistry {
|
||||
private static Class<?> searchForPacket(List<String> classNames) {
|
||||
for (String name : classNames) {
|
||||
try {
|
||||
Class<?> clazz = MinecraftReflection.getMinecraftClass(name);
|
||||
if (MinecraftReflection.getPacketClass().isAssignableFrom(clazz)
|
||||
Class<?> clazz = resolvePacketClassName(name);
|
||||
if (clazz != null && MinecraftReflection.getPacketClass().isAssignableFrom(clazz)
|
||||
&& !Modifier.isAbstract(clazz.getModifiers())) {
|
||||
return clazz;
|
||||
}
|
||||
@@ -424,6 +424,22 @@ public class PacketRegistry {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a single packet class name. Fully-qualified names (those already containing their
|
||||
* package, e.g. {@code net.minecraft.network.protocol.game.XPacket}) are loaded directly, since
|
||||
* {@link MinecraftReflection#getMinecraftClass(String)} would otherwise prepend the Minecraft
|
||||
* package and fail to find them. Relative names continue to be resolved against the Minecraft
|
||||
* package.
|
||||
*/
|
||||
private static Class<?> resolvePacketClassName(String name) {
|
||||
Optional<Class<?>> direct = MinecraftReflection.getOptionalClass(name);
|
||||
if (direct.isPresent()) {
|
||||
return direct.get();
|
||||
}
|
||||
|
||||
return MinecraftReflection.getMinecraftClass(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the correct packet class from a given type.
|
||||
*
|
||||
|
||||
@@ -100,6 +100,7 @@ public final class MinecraftProtocolVersion {
|
||||
map.put(new MinecraftVersion(1, 21, 11), 774);
|
||||
|
||||
map.put(new MinecraftVersion(26, 1, 0), 775);
|
||||
map.put(new MinecraftVersion(26, 2, 0), 776);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@@ -1118,6 +1118,15 @@ public final class MinecraftReflection {
|
||||
return getOptionalNMS("network.chat.numbers.StyledFormat");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the NMS TeamColor class, added in 26.2.
|
||||
*
|
||||
* @return The TeamColor class.
|
||||
*/
|
||||
public static Optional<Class<?>> getTeamColorClass() {
|
||||
return getOptionalNMS("world.scores.TeamColor");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Gson class used by Minecraft.
|
||||
*
|
||||
@@ -1480,6 +1489,18 @@ public final class MinecraftReflection {
|
||||
.orElseThrow(() -> new RuntimeException("Cannot find class " + className));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to load a class by its fully-qualified canonical name, without prepending the
|
||||
* Minecraft package. Unlike {@link #getMinecraftClass(String)}, this can resolve names that
|
||||
* already include their package (e.g. {@code net.minecraft.network.protocol.game.XPacket}).
|
||||
*
|
||||
* @param className - the fully-qualified class name.
|
||||
* @return Optional that may contain the class.
|
||||
*/
|
||||
public static Optional<Class<?>> getOptionalClass(String className) {
|
||||
return getClassSource().loadClass(className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the class object of a specific CraftBukkit class.
|
||||
*
|
||||
@@ -1684,7 +1705,7 @@ public final class MinecraftReflection {
|
||||
}
|
||||
|
||||
public static Class<?> getEntityTypes() {
|
||||
return getMinecraftClass("world.entity.EntityTypes", "world.entity.EntityType", "EntityTypes");
|
||||
return getMinecraftClass("world.entity.EntityType", "world.entity.EntityTypes", "EntityTypes");
|
||||
}
|
||||
|
||||
public static Class<?> getParticleParam() {
|
||||
|
||||
@@ -36,6 +36,11 @@ import org.bukkit.Server;
|
||||
* @author Kristian
|
||||
*/
|
||||
public final class MinecraftVersion implements Comparable<MinecraftVersion>, Serializable {
|
||||
/**
|
||||
* Version 26.2 - chaos cubed
|
||||
*/
|
||||
public static final MinecraftVersion v26_2 = new MinecraftVersion("26.2");
|
||||
|
||||
/**
|
||||
* Version 26.1 - tiny takeover
|
||||
*/
|
||||
@@ -189,7 +194,7 @@ public final class MinecraftVersion implements Comparable<MinecraftVersion>, Ser
|
||||
/**
|
||||
* The latest release version of minecraft.
|
||||
*/
|
||||
public static final MinecraftVersion LATEST = v26_1;
|
||||
public static final MinecraftVersion LATEST = v26_2;
|
||||
|
||||
// used when serializing
|
||||
private static final long serialVersionUID = -8695133558996459770L;
|
||||
|
||||
@@ -70,6 +70,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldType;
|
||||
@@ -873,6 +874,13 @@ public class BukkitConverters {
|
||||
return ignoreNull(new EquivalentConverter<EntityType>() {
|
||||
@Override
|
||||
public Object getGeneric(EntityType specific) {
|
||||
if (MinecraftVersion.v26_2.atOrAbove()) {
|
||||
// EntityType.byString was removed in 26.2, resolve through the registry instead
|
||||
WrappedRegistry registry = WrappedRegistry.getRegistry(MinecraftReflection.getEntityTypes());
|
||||
NamespacedKey key = specific.getKey();
|
||||
return registry.get(new MinecraftKey(key.getNamespace(), key.getKey()));
|
||||
}
|
||||
|
||||
if (entityTypeFromName == null) {
|
||||
Class<?> entityTypesClass = MinecraftReflection.getEntityTypes();
|
||||
entityTypeFromName = Accessors.getMethodAccessor(
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.comphenix.protocol.wrappers;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.comphenix.protocol.injector.StructureCache;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
@@ -90,12 +92,26 @@ public class WrappedTeamParameters extends AbstractWrapper {
|
||||
|
||||
@NotNull
|
||||
public EnumWrappers.ChatFormatting getColor() {
|
||||
if (MinecraftVersion.v26_2.atOrAbove()) {
|
||||
Optional<?> optional = modifier.<Optional<?>>withType(Optional.class).read(0);
|
||||
Object teamColor = optional != null ? optional.orElse(null) : null;
|
||||
if (teamColor == null) {
|
||||
return EnumWrappers.ChatFormatting.RESET;
|
||||
}
|
||||
|
||||
return EnumWrappers.ChatFormatting.valueOf(((Enum<?>) teamColor).name());
|
||||
}
|
||||
|
||||
return modifier
|
||||
.withType(EnumWrappers.getChatFormattingClass(), EnumWrappers.getChatFormattingConverter())
|
||||
.read(0);
|
||||
}
|
||||
|
||||
public int getOptions() {
|
||||
if (MinecraftVersion.v26_2.atOrAbove()) {
|
||||
return (byte) modifier.withType(byte.class).read(0);
|
||||
}
|
||||
|
||||
return (int) modifier.withType(int.class).read(0);
|
||||
}
|
||||
|
||||
@@ -210,9 +226,27 @@ public class WrappedTeamParameters extends AbstractWrapper {
|
||||
wrapped.modifier.withType(String.class).writeSafely(1, collisionRule.toString());
|
||||
}
|
||||
|
||||
wrapped.modifier.withType(EnumWrappers.getChatFormattingClass()).write(0, EnumWrappers.getChatFormattingConverter().getGeneric(color));
|
||||
wrapped.modifier.withType(int.class).write(0, options);
|
||||
if (MinecraftVersion.v26_2.atOrAbove()) {
|
||||
wrapped.modifier.withType(Optional.class).write(0, Optional.ofNullable(toNmsTeamColor(color)));
|
||||
wrapped.modifier.withType(byte.class).write(0, (byte) options);
|
||||
} else {
|
||||
wrapped.modifier.withType(EnumWrappers.getChatFormattingClass()).write(0, EnumWrappers.getChatFormattingConverter().getGeneric(color));
|
||||
wrapped.modifier.withType(int.class).write(0, options);
|
||||
}
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private static Object toNmsTeamColor(EnumWrappers.ChatFormatting color) {
|
||||
Class<?> teamColorClass = MinecraftReflection.getTeamColorClass()
|
||||
.orElseThrow(() -> new IllegalStateException("TeamColor class doesn't exist on this server version"));
|
||||
|
||||
try {
|
||||
return Enum.valueOf((Class) teamColorClass, color.name());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// formatting-only values (e.g. RESET) don't map to a team color
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,15 @@ public class BukkitInitialization {
|
||||
private boolean initialized;
|
||||
private boolean packaged;
|
||||
|
||||
private static ServerLevel mockServerLevel;
|
||||
|
||||
/**
|
||||
* @return the mocked NMS server level set up during initialization, usable as a Level for constructing test entities
|
||||
*/
|
||||
public static ServerLevel getMockServerLevel() {
|
||||
return mockServerLevel;
|
||||
}
|
||||
|
||||
private BukkitInitialization() {
|
||||
System.out.println("Created new BukkitInitialization on " + Thread.currentThread().getName());
|
||||
}
|
||||
@@ -246,6 +255,7 @@ public class BukkitInitialization {
|
||||
|
||||
CraftWorld world = mock(CraftWorld.class);
|
||||
when(world.getHandle()).thenReturn(nmsWorld);
|
||||
mockServerLevel = nmsWorld;
|
||||
|
||||
List<World> worlds = Collections.singletonList(world);
|
||||
when(mockedServer.getWorlds()).thenReturn(worlds);
|
||||
|
||||
@@ -46,7 +46,7 @@ public class WrappedDataWatcherTest {
|
||||
public static void prepare() {
|
||||
BukkitInitialization.initializeAll();
|
||||
|
||||
ThrownEgg nmsEgg = new ThrownEgg(null, 0, 0, 0, net.minecraft.world.item.ItemStack.EMPTY);
|
||||
ThrownEgg nmsEgg = new ThrownEgg(BukkitInitialization.getMockServerLevel(), 0, 0, 0, net.minecraft.world.item.ItemStack.EMPTY);
|
||||
mockEntity = new CraftEgg(null, nmsEgg);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.TeamCollisionRule;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.TeamVisibility;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket;
|
||||
import net.minecraft.world.scores.Team;
|
||||
import net.minecraft.world.scores.TeamColor;
|
||||
|
||||
public class WrappedTeamParametersTest {
|
||||
@BeforeAll
|
||||
@@ -47,12 +49,12 @@ public class WrappedTeamParametersTest {
|
||||
assertEquals(1, wrapped.getOptions());
|
||||
|
||||
ClientboundSetPlayerTeamPacket.Parameters handle = (ClientboundSetPlayerTeamPacket.Parameters) wrapped.getHandle();
|
||||
assertEquals(handle.getDisplayName(), displayName);
|
||||
assertEquals(handle.getPlayerPrefix(), prefix);
|
||||
assertEquals(handle.getPlayerSuffix(), suffix);
|
||||
assertEquals(handle.getNametagVisibility(), Team.Visibility.ALWAYS);
|
||||
assertEquals(handle.getCollisionRule(), Team.CollisionRule.NEVER);
|
||||
assertEquals(handle.getColor(), ChatFormatting.RED);
|
||||
assertEquals(handle.getOptions(), 1);
|
||||
assertEquals(handle.displayName(), displayName);
|
||||
assertEquals(handle.playerPrefix(), prefix);
|
||||
assertEquals(handle.playerSuffix(), suffix);
|
||||
assertEquals(handle.nameTagVisibility(), Team.Visibility.ALWAYS);
|
||||
assertEquals(handle.collisionRule(), Team.CollisionRule.NEVER);
|
||||
assertEquals(handle.color(), Optional.of(TeamColor.RED));
|
||||
assertEquals(handle.options(), 1);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user