9
0
mirror of https://github.com/HibiscusMC/HibiscusCommons.git synced 2025-12-19 15:09:26 +00:00

feat: add 1.21.6 support

This commit is contained in:
LoJoSho
2025-06-19 14:15:04 -05:00
parent e4618e4a42
commit 4e7dbf5ed9
8 changed files with 503 additions and 1 deletions

View File

@@ -11,7 +11,7 @@ plugins {
} }
group = "me.lojosho" group = "me.lojosho"
version = "0.6.4${getGitCommitHash()}" version = "0.6.5${getGitCommitHash()}"
allprojects { allprojects {
apply(plugin = "java") apply(plugin = "java")
@@ -137,6 +137,7 @@ dependencies {
implementation(project(path = ":v1_21_R2", configuration = "reobf")) implementation(project(path = ":v1_21_R2", configuration = "reobf"))
implementation(project(path = ":v1_21_R3", configuration = "reobf")) implementation(project(path = ":v1_21_R3", configuration = "reobf"))
implementation(project(path = ":v1_21_R4", configuration = "reobf")) implementation(project(path = ":v1_21_R4", configuration = "reobf"))
implementation(project(path = ":v1_21_R5", configuration = "reobf"))
} }
tasks { tasks {
@@ -172,6 +173,7 @@ tasks {
dependsOn(":v1_21_R2:reobfJar") dependsOn(":v1_21_R2:reobfJar")
dependsOn(":v1_21_R3:reobfJar") dependsOn(":v1_21_R3:reobfJar")
dependsOn(":v1_21_R4:reobfJar") dependsOn(":v1_21_R4:reobfJar")
dependsOn(":v1_21_R5:reobfJar")
mergeServiceFiles() mergeServiceFiles()
relocate("org.bstats", "me.lojosho.shaded.bstats") relocate("org.bstats", "me.lojosho.shaded.bstats")

View File

@@ -10,6 +10,7 @@ public enum MinecraftVersion {
v1_21_3, v1_21_3,
v1_21_4, v1_21_4,
v1_21_5, v1_21_5,
v1_21_6,
; ;
public boolean isHigher(MinecraftVersion other) { public boolean isHigher(MinecraftVersion other) {

View File

@@ -19,6 +19,7 @@ public class NMSHandlers {
put(MinecraftVersion.v1_21_3, "v1_21_R2"); put(MinecraftVersion.v1_21_3, "v1_21_R2");
put(MinecraftVersion.v1_21_4, "v1_21_R3"); put(MinecraftVersion.v1_21_4, "v1_21_R3");
put(MinecraftVersion.v1_21_5, "v1_21_R4"); put(MinecraftVersion.v1_21_5, "v1_21_R4");
put(MinecraftVersion.v1_21_6, "v1_21_R5");
}}; }};
private static NMSHandler handler; private static NMSHandler handler;

View File

@@ -18,4 +18,5 @@ include(
"v1_21_R2", "v1_21_R2",
"v1_21_R3", "v1_21_R3",
"v1_21_R4", "v1_21_R4",
"v1_21_R5",
) )

30
v1_21_R5/build.gradle.kts Normal file
View File

@@ -0,0 +1,30 @@
plugins {
id("java")
id("io.papermc.paperweight.userdev")
}
dependencies {
paperweight.paperDevBundle("1.21.6-R0.1-SNAPSHOT")
implementation(project(":common"))
}
tasks {
build {
dependsOn(reobfJar)
}
compileJava {
options.encoding = Charsets.UTF_8.name()
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21));
}
javadoc {
options.encoding = Charsets.UTF_8.name()
}
processResources {
filteringCharset = Charsets.UTF_8.name()
}
}

View File

@@ -0,0 +1,17 @@
package me.lojosho.hibiscuscommons.nms.v1_21_R5;
import net.minecraft.network.protocol.Packet;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerPlayerConnection;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
public class NMSCommon {
public void sendPacket(Player player, Packet packet) {
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
ServerPlayerConnection connection = serverPlayer.connection;
connection.send(packet);
}
}

View File

@@ -0,0 +1,396 @@
package me.lojosho.hibiscuscommons.nms.v1_21_R5;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.JsonOps;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntList;
import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.minecraft.advancements.*;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.*;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.PositionMoveRotation;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.level.portal.TeleportTransition;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.world.scores.Team;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.craftbukkit.CraftEquipmentSlot;
import org.bukkit.craftbukkit.entity.CraftEntityType;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.scoreboard.CraftScoreboard;
import org.bukkit.entity.Display;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ItemDisplay;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.components.CustomModelDataComponent;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import java.lang.reflect.Constructor;
import java.util.*;
public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons.nms.NMSPackets {
static Constructor<ClientboundSetPassengersPacket> passengerConstructor;
static Constructor<ClientboundSetEntityLinkPacket> linkConstructor;
static Constructor<ClientboundSetCameraPacket> cameraConstructor;
static Constructor<ClientboundPlayerLookAtPacket> lookAtConstructor;
static {
try {
passengerConstructor = ClientboundSetPassengersPacket.class.getDeclaredConstructor(FriendlyByteBuf.class);
passengerConstructor.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
try {
linkConstructor = ClientboundSetEntityLinkPacket.class.getDeclaredConstructor(FriendlyByteBuf.class);
linkConstructor.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
try {
cameraConstructor = ClientboundSetCameraPacket.class.getDeclaredConstructor(FriendlyByteBuf.class);
cameraConstructor.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
try {
lookAtConstructor = ClientboundPlayerLookAtPacket.class.getDeclaredConstructor(FriendlyByteBuf.class);
lookAtConstructor.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void sendEquipmentSlotUpdate(
int entityId,
org.bukkit.inventory.EquipmentSlot slot,
ItemStack item,
List<Player> sendTo
) {
EquipmentSlot nmsSlot = null;
net.minecraft.world.item.ItemStack nmsItem = null;
// Converting EquipmentSlot and ItemStack to NMS ones.
nmsSlot = CraftEquipmentSlot.getNMS(slot);
nmsItem = CraftItemStack.asNMSCopy(item);
if (nmsSlot == null) return;
Pair<EquipmentSlot, net.minecraft.world.item.ItemStack> pair = new Pair<>(nmsSlot, nmsItem);
List<Pair<EquipmentSlot, net.minecraft.world.item.ItemStack>> pairs = Collections.singletonList(pair);
ClientboundSetEquipmentPacket packet = new ClientboundSetEquipmentPacket(entityId, pairs);
for (Player p : sendTo) sendPacket(p, packet);
}
@Override
public void sendEquipmentSlotUpdate(
int entityId,
HashMap<org.bukkit.inventory.EquipmentSlot, ItemStack> equipment,
List<Player> sendTo
) {
List<Pair<EquipmentSlot, net.minecraft.world.item.ItemStack>> pairs = new ArrayList<>();
for (org.bukkit.inventory.EquipmentSlot slot : equipment.keySet()) {
EquipmentSlot nmsSlot = CraftEquipmentSlot.getNMS(slot);
net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(equipment.get(slot));
Pair<EquipmentSlot, net.minecraft.world.item.ItemStack> pair = new Pair<>(nmsSlot, nmsItem);
pairs.add(pair);
}
ClientboundSetEquipmentPacket packet = new ClientboundSetEquipmentPacket(entityId, pairs);
for (Player p : sendTo) sendPacket(p, packet);
}
@Override
public void sendSlotUpdate(
Player player,
int slot
) {
int index = 0;
ServerPlayer player1 = ((CraftPlayer) player).getHandle();
if (index < Inventory.getSelectionSize()) {
index += 36;
} else if (index > 39) {
index += 5; // Off hand
} else if (index > 35) {
index = 8 - (index - 36);
}
ItemStack item = player.getInventory().getItem(slot);
Packet packet = new ClientboundContainerSetSlotPacket(player1.inventoryMenu.containerId, player1.inventoryMenu.incrementStateId(), index, CraftItemStack.asNMSCopy(item));
sendPacket(player, packet);
}
@Override
public void sendScoreboardHideNamePacket(Player player, String name) {
//Creating the team
PlayerTeam team = new PlayerTeam(((CraftScoreboard) Bukkit.getScoreboardManager().getMainScoreboard()).getHandle(), name);
//Setting name visibility
team.setNameTagVisibility(Team.Visibility.NEVER);
//Remove the Team (i assume so if it exists)
ClientboundSetPlayerTeamPacket removeTeamPacket = ClientboundSetPlayerTeamPacket.createRemovePacket(team);
sendPacket(player, removeTeamPacket);
//Creating the Team
ClientboundSetPlayerTeamPacket createTeamPacket = ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true);
sendPacket(player, createTeamPacket);
//Adding players to the team (You have to use the NPC's name, and add it to a list)
ClientboundSetPlayerTeamPacket createPlayerTeamPacket = ClientboundSetPlayerTeamPacket.createMultiplePlayerPacket(team, new ArrayList<String>() {{
add(name);
}}, ClientboundSetPlayerTeamPacket.Action.ADD);
sendPacket(player, createPlayerTeamPacket);
}
@Override
public void sendMountPacket(int mountId, int[] passengerIds, List<Player> sendTo) {
FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer());
byteBuf.writeVarInt(mountId);
byteBuf.writeVarIntArray(passengerIds);
try {
ClientboundSetPassengersPacket packet = passengerConstructor.newInstance(byteBuf);
for (Player p : sendTo) sendPacket(p, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void sendLeashPacket(int leashEntity, int entityId, List<Player> sendTo) {
FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer());
byteBuf.writeInt(leashEntity);
byteBuf.writeInt(entityId);
try {
ClientboundSetEntityLinkPacket packet = linkConstructor.newInstance(byteBuf);
for (Player p : sendTo) sendPacket(p, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void sendTeleportPacket(
int entityId,
double x,
double y,
double z,
float yaw,
float pitch,
boolean onGround,
List<Player> sendTo
) {
try {
ClientboundTeleportEntityPacket packet = ClientboundTeleportEntityPacket.teleport(entityId, new PositionMoveRotation(new Vec3(x, y, z), Vec3.ZERO, yaw, pitch), java.util.Set.of(), onGround);
for (Player p : sendTo) sendPacket(p, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void sendRotationPacket(int entityId, float yaw, boolean onGround, List<Player> sendTo) {
FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer());
byteBuf.writeVarInt(entityId);
byteBuf.writeFloat(yaw);
byteBuf.writeBoolean(onGround);
try {
ClientboundPlayerLookAtPacket packet = lookAtConstructor.newInstance(byteBuf);
for (Player p : sendTo) sendPacket(p, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void sendCameraPacket(int entityId, List<Player> sendTo) {
FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer());
byteBuf.writeVarInt(entityId);
try {
ClientboundSetCameraPacket packet = cameraConstructor.newInstance(byteBuf);
for (Player p : sendTo) sendPacket(p, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void sendSpawnEntityPacket(int entityId, UUID uuid, EntityType entityType, Location location, List<Player> sendTo) {
net.minecraft.world.entity.EntityType<?> nmsEntityType = CraftEntityType.bukkitToMinecraft(entityType);
double x = location.getX();
double y = location.getY();
double z = location.getZ();
float yaw = location.getYaw();
float pitch = location.getPitch();
Vec3 velocity = Vec3.ZERO;
float headYaw = 0f;
ClientboundAddEntityPacket packet = new ClientboundAddEntityPacket(entityId, uuid, x, y, z, yaw, pitch, nmsEntityType, 0, velocity, headYaw);
for (Player p : sendTo) sendPacket(p, packet);
}
@Override
public void sendEntityDestroyPacket(IntList entityIds, List<Player> sendTo) {
ClientboundRemoveEntitiesPacket packet = new ClientboundRemoveEntitiesPacket(entityIds);
for (Player p : sendTo) sendPacket(p, packet);
}
@Override
public void sendItemDisplayMetadata(int entityId,
Vector3f translation,
Vector3f scale,
Quaternionf rotationLeft,
Quaternionf rotationRight,
Display.Billboard billboard,
int blockLight, int skyLight, float viewRange, float width, float height,
ItemDisplay.ItemDisplayTransform transform, ItemStack itemStack,
List<Player> sendTo) {
List<SynchedEntityData.DataValue<?>> dataValues = new ArrayList<>();
dataValues.add(new SynchedEntityData.DataValue<>(10, EntityDataSerializers.INT, POSITION_INTERPOLATION_DURATION));
dataValues.add(new SynchedEntityData.DataValue<>(11, EntityDataSerializers.VECTOR3, translation));
dataValues.add(new SynchedEntityData.DataValue<>(12, EntityDataSerializers.VECTOR3, scale));
dataValues.add(new SynchedEntityData.DataValue<>(13, EntityDataSerializers.QUATERNION, rotationLeft));
dataValues.add(new SynchedEntityData.DataValue<>(14, EntityDataSerializers.QUATERNION, rotationRight));
dataValues.add(new SynchedEntityData.DataValue<>(15, EntityDataSerializers.BYTE, (byte) billboard.ordinal()));
dataValues.add(new SynchedEntityData.DataValue<>(16, EntityDataSerializers.INT, (blockLight << 4 | skyLight << 20)));
dataValues.add(new SynchedEntityData.DataValue<>(17, EntityDataSerializers.FLOAT, viewRange));
dataValues.add(new SynchedEntityData.DataValue<>(20, EntityDataSerializers.FLOAT, width));
dataValues.add(new SynchedEntityData.DataValue<>(21, EntityDataSerializers.FLOAT, height));
dataValues.add(new SynchedEntityData.DataValue<>(23, EntityDataSerializers.ITEM_STACK, CraftItemStack.asNMSCopy(itemStack)));
dataValues.add(new SynchedEntityData.DataValue<>(24, EntityDataSerializers.BYTE, (byte) transform.ordinal()));
ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entityId, dataValues);
for (Player p : sendTo) sendPacket(p, packet);
}
public void sendToastPacket(Player player, ItemStack icon, Component title, Component description) {
final var key = ResourceLocation.fromNamespaceAndPath("hibiscuscommons", UUID.randomUUID().toString());
JsonObject json = new JsonObject();
// Creating the "criteria" object
JsonObject impossibleCriteria = new JsonObject();
JsonObject impossible = new JsonObject();
impossible.addProperty("trigger", "minecraft:impossible");
impossibleCriteria.add("impossible", impossible);
json.add("criteria", impossibleCriteria);
// Creating the "display" object
JsonObject display = new JsonObject();
JsonObject iconObj = new JsonObject();
iconObj.addProperty("id", icon.getType().getKey().toString());
if (icon.hasItemMeta()) {
ItemMeta meta = icon.getItemMeta();
JsonObject components = new JsonObject();
if (!meta.getEnchants().isEmpty()) {
components.addProperty("minecraft:enchantment_glint_override", true);
}
if (meta.hasCustomModelData()) {
CustomModelDataComponent customModelDataComponent = meta.getCustomModelDataComponent();
JsonObject customModelDataComponentJson = new JsonObject();
List<Float> floats = customModelDataComponent.getFloats();
if (!floats.isEmpty()) {
JsonArray floatsArray = new JsonArray();
floats.forEach(floatsArray::add);
customModelDataComponentJson.add("floats", floatsArray);
}
List<Boolean> flags = customModelDataComponent.getFlags();
if (!flags.isEmpty()) {
JsonArray flagsArray = new JsonArray();
flags.forEach(flagsArray::add);
customModelDataComponentJson.add("flags", flagsArray);
}
List<String> strings = customModelDataComponent.getStrings();
if (!strings.isEmpty()) {
JsonArray stringsArray = new JsonArray();
strings.forEach(stringsArray::add);
customModelDataComponentJson.add("strings", stringsArray);
}
List<Color> colors = customModelDataComponent.getColors();
if (!colors.isEmpty()) {
JsonArray colorsArray = new JsonArray();
colors.forEach(color -> colorsArray.add(color.asRGB()));
customModelDataComponentJson.add("colors", colorsArray);
}
components.add("minecraft:custom_model_data", customModelDataComponentJson);
}
iconObj.add("components", components);
}
display.add("icon", iconObj);
display.add("title", GsonComponentSerializer.gson().serializeToTree(title));
display.add("description", GsonComponentSerializer.gson().serializeToTree(description));
display.addProperty("description", "Toast Description");
display.addProperty("frame", "task");
display.addProperty("announce_to_chat", false);
display.addProperty("show_toast", true);
display.addProperty("hidden", true);
json.add("display", display);
final var advancement = Advancement.CODEC.parse(MinecraftServer.getServer().registryAccess().createSerializationContext(JsonOps.INSTANCE), json);
final var advancementHolder = new AdvancementHolder(key, advancement.result().orElseThrow());
final var nmsPlayer = ((CraftPlayer) player).getHandle();
final var progress = nmsPlayer.getAdvancements().getOrStartProgress(advancementHolder);
MinecraftServer.getServer().getAdvancements().tree().addAll(Set.of(advancementHolder));
progress.getRemainingCriteria().forEach(criteria -> nmsPlayer.getAdvancements().award(advancementHolder, criteria));
Bukkit.getScheduler().runTaskLater(HibiscusCommonsPlugin.getInstance(), () -> {
progress.getRemainingCriteria().forEach(criteria -> nmsPlayer.getAdvancements().revoke(advancementHolder, criteria));
MinecraftServer.getServer().getAdvancements().tree().remove(Set.of(key));
// Remove the advancement from the player's client to prevent it from being displayed again
// Was not working without this?
ClientboundUpdateAdvancementsPacket removePacket = new ClientboundUpdateAdvancementsPacket(
false,
Collections.emptyList(),
Set.of(key),
Map.of(),
false
);
sendPacket(player, removePacket);
}, 2L);
}
}

View File

@@ -0,0 +1,54 @@
package me.lojosho.hibiscuscommons.nms.v1_21_R5;
import net.minecraft.core.component.DataComponents;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.component.DyedItemColor;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class NMSUtils extends NMSCommon implements me.lojosho.hibiscuscommons.nms.NMSUtils {
@Override
public int getNextEntityId() {
return net.minecraft.world.entity.Entity.nextEntityId();
}
@Override
public org.bukkit.entity.Entity getEntity(int entityId) {
net.minecraft.world.entity.Entity entity = getNMSEntity(entityId);
if (entity == null) return null;
return entity.getBukkitEntity();
}
@Override
public @Nullable Color getColor(ItemStack itemStack) {
if (itemStack == null) return null;
net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(itemStack);
if (nmsItem == null) return null;
DyedItemColor color = nmsItem.get(DataComponents.DYED_COLOR);
if (color == null) return null;
return Color.fromRGB(color.rgb());
}
@Override
public ItemStack setColor(@NotNull ItemStack itemStack, Color color) {
net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack);
nmsStack.set(DataComponents.DYED_COLOR, new DyedItemColor(color.asRGB()));
return CraftItemStack.asBukkitCopy(nmsStack);
}
private net.minecraft.world.entity.Entity getNMSEntity(int entityId) {
for (ServerLevel world : ((CraftServer) Bukkit.getServer()).getHandle().getServer().getAllLevels()) {
net.minecraft.world.entity.Entity entity = world.getEntity(entityId);
if (entity == null) continue;
return entity;
}
return null;
}
}