Skip to content

Commit aca303b

Browse files
committed
Update to Minecraft 26.2
1 parent 8eeb82f commit aca303b

12 files changed

Lines changed: 117 additions & 20 deletions

File tree

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ plugins {
1212
group = "net.dmulloy2"
1313
description = "Provides access to the Minecraft protocol"
1414

15-
val mcVersion = "26.1"
15+
val mcVersion = "26.2"
1616
val isSnapshot = version.toString().endsWith("-SNAPSHOT")
1717
val isJitPack = System.getenv("JITPACK")?.equals("true", ignoreCase = true) ?: false
1818
val commitHash = System.getenv("COMMIT_SHA") ?: ""

src/main/java/com/comphenix/protocol/PacketType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ public static class Client extends PacketTypeEnum {
506506
public static final PacketType STRUCT = new PacketType(PROTOCOL, SENDER, 0x3B, "SetStructureBlock", "Struct");
507507
public static final PacketType SET_TEST_BLOCK = new PacketType(PROTOCOL, SENDER, 0x3C, "SetTestBlock");
508508
public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x3D, "SignUpdate", "UpdateSign", "CPacketUpdateSign");
509-
public static final PacketType SPECTATE_ENTITY = new PacketType(PROTOCOL, SENDER, 0x3E, "SpectateEntity");
509+
public static final PacketType SPECTATE_ENTITY = new PacketType(PROTOCOL, SENDER, 0x3E, "SpectatorAction", "SpectateEntity");
510510
public static final PacketType ARM_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x3F, "Swing", "ArmAnimation", "CPacketAnimation");
511511
public static final PacketType SPECTATE = new PacketType(PROTOCOL, SENDER, 0x40, "TeleportToEntity", "Spectate", "CPacketSpectate");
512512
public static final PacketType TEST_INSTANCE_BLOCK_ACTION = new PacketType(PROTOCOL, SENDER, 0x41, "TestInstanceBlockAction");

src/main/java/com/comphenix/protocol/ProtocolLibrary.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ public class ProtocolLibrary {
3535
/**
3636
* The maximum version ProtocolLib has been tested with.
3737
*/
38-
public static final String MAXIMUM_MINECRAFT_VERSION = "26.1";
38+
public static final String MAXIMUM_MINECRAFT_VERSION = "26.2";
3939

4040
/**
41-
* The date (with ISO 8601 or YYYY-MM-DD) when the most recent version (1.21.11) was released.
41+
* The date (with ISO 8601 or YYYY-MM-DD) when the most recent version (26.2) was released.
4242
*/
43-
public static final String MINECRAFT_LAST_RELEASE_DATE = "2026-03-24";
43+
public static final String MINECRAFT_LAST_RELEASE_DATE = "2026-06-16";
4444

4545
private static Plugin plugin;
4646
private static ProtocolConfig config;

src/main/java/com/comphenix/protocol/injector/packet/PacketRegistry.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,8 +412,8 @@ public static Set<PacketType> getClientPacketTypes() {
412412
private static Class<?> searchForPacket(List<String> classNames) {
413413
for (String name : classNames) {
414414
try {
415-
Class<?> clazz = MinecraftReflection.getMinecraftClass(name);
416-
if (MinecraftReflection.getPacketClass().isAssignableFrom(clazz)
415+
Class<?> clazz = resolvePacketClassName(name);
416+
if (clazz != null && MinecraftReflection.getPacketClass().isAssignableFrom(clazz)
417417
&& !Modifier.isAbstract(clazz.getModifiers())) {
418418
return clazz;
419419
}
@@ -424,6 +424,22 @@ private static Class<?> searchForPacket(List<String> classNames) {
424424
return null;
425425
}
426426

427+
/**
428+
* Resolve a single packet class name. Fully-qualified names (those already containing their
429+
* package, e.g. {@code net.minecraft.network.protocol.game.XPacket}) are loaded directly, since
430+
* {@link MinecraftReflection#getMinecraftClass(String)} would otherwise prepend the Minecraft
431+
* package and fail to find them. Relative names continue to be resolved against the Minecraft
432+
* package.
433+
*/
434+
private static Class<?> resolvePacketClassName(String name) {
435+
Optional<Class<?>> direct = MinecraftReflection.getOptionalClass(name);
436+
if (direct.isPresent()) {
437+
return direct.get();
438+
}
439+
440+
return MinecraftReflection.getMinecraftClass(name);
441+
}
442+
427443
/**
428444
* Retrieves the correct packet class from a given type.
429445
*

src/main/java/com/comphenix/protocol/utility/MinecraftProtocolVersion.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ private static NavigableMap<MinecraftVersion, Integer> createLookup() {
100100
map.put(new MinecraftVersion(1, 21, 11), 774);
101101

102102
map.put(new MinecraftVersion(26, 1, 0), 775);
103+
map.put(new MinecraftVersion(26, 2, 0), 776);
103104
return map;
104105
}
105106

src/main/java/com/comphenix/protocol/utility/MinecraftReflection.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,15 @@ public static Optional<Class<?>> getStyledFormatClass() {
11181118
return getOptionalNMS("network.chat.numbers.StyledFormat");
11191119
}
11201120

1121+
/**
1122+
* Retrieve the NMS TeamColor class, added in 26.2.
1123+
*
1124+
* @return The TeamColor class.
1125+
*/
1126+
public static Optional<Class<?>> getTeamColorClass() {
1127+
return getOptionalNMS("world.scores.TeamColor");
1128+
}
1129+
11211130
/**
11221131
* Retrieve the Gson class used by Minecraft.
11231132
*
@@ -1480,6 +1489,18 @@ private static Class<?> getClass(String className) {
14801489
.orElseThrow(() -> new RuntimeException("Cannot find class " + className));
14811490
}
14821491

1492+
/**
1493+
* Attempt to load a class by its fully-qualified canonical name, without prepending the
1494+
* Minecraft package. Unlike {@link #getMinecraftClass(String)}, this can resolve names that
1495+
* already include their package (e.g. {@code net.minecraft.network.protocol.game.XPacket}).
1496+
*
1497+
* @param className - the fully-qualified class name.
1498+
* @return Optional that may contain the class.
1499+
*/
1500+
public static Optional<Class<?>> getOptionalClass(String className) {
1501+
return getClassSource().loadClass(className);
1502+
}
1503+
14831504
/**
14841505
* Retrieve the class object of a specific CraftBukkit class.
14851506
*
@@ -1684,7 +1705,7 @@ public static Class<?> getResourceKey() {
16841705
}
16851706

16861707
public static Class<?> getEntityTypes() {
1687-
return getMinecraftClass("world.entity.EntityTypes", "world.entity.EntityType", "EntityTypes");
1708+
return getMinecraftClass("world.entity.EntityType", "world.entity.EntityTypes", "EntityTypes");
16881709
}
16891710

16901711
public static Class<?> getParticleParam() {

src/main/java/com/comphenix/protocol/utility/MinecraftVersion.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@
3636
* @author Kristian
3737
*/
3838
public final class MinecraftVersion implements Comparable<MinecraftVersion>, Serializable {
39+
/**
40+
* Version 26.2 - chaos cubed
41+
*/
42+
public static final MinecraftVersion v26_2 = new MinecraftVersion("26.2");
43+
3944
/**
4045
* Version 26.1 - tiny takeover
4146
*/
@@ -189,7 +194,7 @@ public final class MinecraftVersion implements Comparable<MinecraftVersion>, Ser
189194
/**
190195
* The latest release version of minecraft.
191196
*/
192-
public static final MinecraftVersion LATEST = v26_1;
197+
public static final MinecraftVersion LATEST = v26_2;
193198

194199
// used when serializing
195200
private static final long serialVersionUID = -8695133558996459770L;

src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import com.google.common.collect.Lists;
7171
import org.bukkit.Bukkit;
7272
import org.bukkit.Material;
73+
import org.bukkit.NamespacedKey;
7374
import org.bukkit.Sound;
7475
import org.bukkit.World;
7576
import org.bukkit.WorldType;
@@ -873,6 +874,13 @@ public static EquivalentConverter<EntityType> getEntityTypeConverter() {
873874
return ignoreNull(new EquivalentConverter<EntityType>() {
874875
@Override
875876
public Object getGeneric(EntityType specific) {
877+
if (MinecraftVersion.v26_2.atOrAbove()) {
878+
// EntityType.byString was removed in 26.2, resolve through the registry instead
879+
WrappedRegistry registry = WrappedRegistry.getRegistry(MinecraftReflection.getEntityTypes());
880+
NamespacedKey key = specific.getKey();
881+
return registry.get(new MinecraftKey(key.getNamespace(), key.getKey()));
882+
}
883+
876884
if (entityTypeFromName == null) {
877885
Class<?> entityTypesClass = MinecraftReflection.getEntityTypes();
878886
entityTypeFromName = Accessors.getMethodAccessor(

src/main/java/com/comphenix/protocol/wrappers/WrappedTeamParameters.java

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import org.jetbrains.annotations.NotNull;
44
import org.jetbrains.annotations.Nullable;
55

6+
import java.util.Optional;
7+
68
import com.comphenix.protocol.injector.StructureCache;
79
import com.comphenix.protocol.reflect.StructureModifier;
810
import com.comphenix.protocol.utility.MinecraftReflection;
@@ -90,12 +92,26 @@ public TeamCollisionRule getCollisionRule() {
9092

9193
@NotNull
9294
public EnumWrappers.ChatFormatting getColor() {
95+
if (MinecraftVersion.v26_2.atOrAbove()) {
96+
Optional<?> optional = modifier.<Optional<?>>withType(Optional.class).read(0);
97+
Object teamColor = optional != null ? optional.orElse(null) : null;
98+
if (teamColor == null) {
99+
return EnumWrappers.ChatFormatting.RESET;
100+
}
101+
102+
return EnumWrappers.ChatFormatting.valueOf(((Enum<?>) teamColor).name());
103+
}
104+
93105
return modifier
94106
.withType(EnumWrappers.getChatFormattingClass(), EnumWrappers.getChatFormattingConverter())
95107
.read(0);
96108
}
97109

98110
public int getOptions() {
111+
if (MinecraftVersion.v26_2.atOrAbove()) {
112+
return (byte) modifier.withType(byte.class).read(0);
113+
}
114+
99115
return (int) modifier.withType(int.class).read(0);
100116
}
101117

@@ -210,9 +226,27 @@ public WrappedTeamParameters build() {
210226
wrapped.modifier.withType(String.class).writeSafely(1, collisionRule.toString());
211227
}
212228

213-
wrapped.modifier.withType(EnumWrappers.getChatFormattingClass()).write(0, EnumWrappers.getChatFormattingConverter().getGeneric(color));
214-
wrapped.modifier.withType(int.class).write(0, options);
229+
if (MinecraftVersion.v26_2.atOrAbove()) {
230+
wrapped.modifier.withType(Optional.class).write(0, Optional.ofNullable(toNmsTeamColor(color)));
231+
wrapped.modifier.withType(byte.class).write(0, (byte) options);
232+
} else {
233+
wrapped.modifier.withType(EnumWrappers.getChatFormattingClass()).write(0, EnumWrappers.getChatFormattingConverter().getGeneric(color));
234+
wrapped.modifier.withType(int.class).write(0, options);
235+
}
215236
return wrapped;
216237
}
238+
239+
@SuppressWarnings({"unchecked", "rawtypes"})
240+
private static Object toNmsTeamColor(EnumWrappers.ChatFormatting color) {
241+
Class<?> teamColorClass = MinecraftReflection.getTeamColorClass()
242+
.orElseThrow(() -> new IllegalStateException("TeamColor class doesn't exist on this server version"));
243+
244+
try {
245+
return Enum.valueOf((Class) teamColorClass, color.name());
246+
} catch (IllegalArgumentException ex) {
247+
// formatting-only values (e.g. RESET) don't map to a team color
248+
return null;
249+
}
250+
}
217251
}
218252
}

src/test/java/com/comphenix/protocol/BukkitInitialization.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ public class BukkitInitialization {
7979
private boolean initialized;
8080
private boolean packaged;
8181

82+
private static ServerLevel mockServerLevel;
83+
84+
/**
85+
* @return the mocked NMS server level set up during initialization, usable as a Level for constructing test entities
86+
*/
87+
public static ServerLevel getMockServerLevel() {
88+
return mockServerLevel;
89+
}
90+
8291
private BukkitInitialization() {
8392
System.out.println("Created new BukkitInitialization on " + Thread.currentThread().getName());
8493
}
@@ -246,6 +255,7 @@ private void initialize() {
246255

247256
CraftWorld world = mock(CraftWorld.class);
248257
when(world.getHandle()).thenReturn(nmsWorld);
258+
mockServerLevel = nmsWorld;
249259

250260
List<World> worlds = Collections.singletonList(world);
251261
when(mockedServer.getWorlds()).thenReturn(worlds);

0 commit comments

Comments
 (0)