From 94c646aefc0e610069ffaa3dc31d365f8f344cb6 Mon Sep 17 00:00:00 2001 From: LoJoSho Date: Wed, 11 Jan 2023 14:56:25 -0600 Subject: [PATCH] Support for 1.19.3 --- build.gradle.kts | 2 + .../hmccosmetics/nms/NMSHandlers.java | 17 +- .../hmccosmetics/util/ServerUtils.java | 17 ++ settings.gradle.kts | 3 +- v1_19_R2/build.gradle.kts | 27 ++ .../nms/v1_19_R2/InvisibleArmorstand.java | 23 ++ .../hmccosmetics/nms/v1_19_R2/MEGEntity.java | 31 +++ .../hmccosmetics/nms/v1_19_R2/NMSHandler.java | 243 ++++++++++++++++++ 8 files changed, 360 insertions(+), 3 deletions(-) create mode 100644 v1_19_R2/build.gradle.kts create mode 100644 v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/InvisibleArmorstand.java create mode 100644 v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/MEGEntity.java create mode 100644 v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/NMSHandler.java diff --git a/build.gradle.kts b/build.gradle.kts index 9dc2ab14..cea459a2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -43,6 +43,7 @@ allprojects { dependencies { implementation(project(path = ":common")) implementation(project(path = ":v1_19_R1", configuration = "reobf")) + implementation(project(path = ":v1_19_R2", configuration = "reobf")) //implementation(files("v1_19_R1/build/libs/1_19_R1-unspecified.jar")) compileOnly("com.mojang:authlib:1.5.25") @@ -87,6 +88,7 @@ tasks { shadowJar { dependsOn(":v1_19_R1:reobfJar") + dependsOn(":v1_19_R2:reobfJar") mergeServiceFiles() relocate("dev.triumphteam.gui", "com.hisbiscusmc.hmccosmetics.gui") diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/nms/NMSHandlers.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/nms/NMSHandlers.java index 8b4ff86d..ffcac34f 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/nms/NMSHandlers.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/nms/NMSHandlers.java @@ -1,10 +1,15 @@ package com.hibiscusmc.hmccosmetics.nms; +import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; +import com.hibiscusmc.hmccosmetics.util.MessagesUtil; +import org.bukkit.Bukkit; + import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; public class NMSHandlers { - private static final String[] SUPPORTED_VERSION = new String[]{"v1_19_R1"}; + private static final String[] SUPPORTED_VERSION = new String[]{"v1_19_R1", "v1_19_R2"}; private static NMSHandler handler; public static NMSHandler getHandler() { @@ -18,10 +23,18 @@ public class NMSHandlers { public static void setup() { if (handler != null) return; + final String packageName = HMCCosmeticsPlugin.getInstance().getServer().getClass().getPackage().getName(); + String packageVersion = packageName.substring(packageName.lastIndexOf('.') + 1); + for (String version : SUPPORTED_VERSION) { + MessagesUtil.sendDebugMessages(packageVersion + " has been detected.", Level.SEVERE); + if (!version.contains(packageVersion)) { + continue; + } try { //Class.forName("org.bukkit.craftbukkit." + version + ".block.CraftBlock").getName(); - handler = (NMSHandler) Class.forName("com.hibiscusmc.hmccosmetics.nms." + version + ".NMSHandler").getConstructor().newInstance(); + handler = (NMSHandler) Class.forName("com.hibiscusmc.hmccosmetics.nms." + packageVersion + ".NMSHandler").getConstructor().newInstance(); + return; } catch (ClassNotFoundException | InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) { throw new RuntimeException(e); diff --git a/common/src/main/java/com/hibiscusmc/hmccosmetics/util/ServerUtils.java b/common/src/main/java/com/hibiscusmc/hmccosmetics/util/ServerUtils.java index adcfb4be..ab2947cf 100644 --- a/common/src/main/java/com/hibiscusmc/hmccosmetics/util/ServerUtils.java +++ b/common/src/main/java/com/hibiscusmc/hmccosmetics/util/ServerUtils.java @@ -1,10 +1,16 @@ package com.hibiscusmc.hmccosmetics.util; import com.hibiscusmc.hmccosmetics.nms.NMSHandlers; +import org.bukkit.Color; import org.bukkit.GameMode; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class ServerUtils { + private static String COLOR_CHAR = "&"; + /** * Converts a bukkit gamemode into an integer for use in packets * @param gamemode Bukkit gamemode to convert. @@ -22,4 +28,15 @@ public class ServerUtils { public static org.bukkit.entity.Entity getEntity(int entityId) { return NMSHandlers.getHandler().getEntity(entityId); } + + public static Color hex2Rgb(String colorStr) { + try { + return Color.fromRGB( + Integer.valueOf(colorStr.substring(1, 3), 16), + Integer.valueOf(colorStr.substring(3, 5), 16), + Integer.valueOf(colorStr.substring(5, 7), 16)); + } catch (StringIndexOutOfBoundsException e) { + return null; + } + } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 7b2ce9c5..62692f60 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,5 +7,6 @@ pluginManagement { rootProject.name = "HMCCosmetics" include( "common", - "v1_19_R1" + "v1_19_R1", + "v1_19_R2" ) diff --git a/v1_19_R2/build.gradle.kts b/v1_19_R2/build.gradle.kts new file mode 100644 index 00000000..37d9fadb --- /dev/null +++ b/v1_19_R2/build.gradle.kts @@ -0,0 +1,27 @@ +plugins { + id("java") + id("io.papermc.paperweight.userdev") version "1.3.8" +} + +dependencies { + paperDevBundle("1.19.3-R0.1-SNAPSHOT") + implementation(project(":common")) +} + +tasks { + + build { + dependsOn(reobfJar) + } + + compileJava { + options.encoding = Charsets.UTF_8.name() + options.release.set(17) + } + javadoc { + options.encoding = Charsets.UTF_8.name() + } + processResources { + filteringCharset = Charsets.UTF_8.name() + } +} \ No newline at end of file diff --git a/v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/InvisibleArmorstand.java b/v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/InvisibleArmorstand.java new file mode 100644 index 00000000..1112f998 --- /dev/null +++ b/v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/InvisibleArmorstand.java @@ -0,0 +1,23 @@ +package com.hibiscusmc.hmccosmetics.nms.v1_19_R2; + +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.level.Level; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; + +public class InvisibleArmorstand extends ArmorStand { + + public InvisibleArmorstand(Level world, double x, double y, double z) { + super(world, x, y, z); + } + + public InvisibleArmorstand(Location loc) { + super(((CraftWorld) loc.getWorld()).getHandle(), loc.getX(), loc.getY(), loc.getZ()); + this.setPos(loc.getX(), loc.getY(), loc.getZ()); + setInvisible(true); + setInvulnerable(true); + setMarker(true); + getBukkitLivingEntity().setCollidable(false); + persist = false; + } +} diff --git a/v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/MEGEntity.java b/v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/MEGEntity.java new file mode 100644 index 00000000..1de088ab --- /dev/null +++ b/v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/MEGEntity.java @@ -0,0 +1,31 @@ +package com.hibiscusmc.hmccosmetics.nms.v1_19_R2; + +import com.hibiscusmc.hmccosmetics.HMCCosmeticsPlugin; +import com.hibiscusmc.hmccosmetics.util.MessagesUtil; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ambient.Bat; +import net.minecraft.world.entity.animal.Cod; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; +import org.bukkit.persistence.PersistentDataType; + +public class MEGEntity extends Cod { + + public MEGEntity(Location loc) { + super(EntityType.COD, ((CraftWorld) loc.getWorld()).getHandle()); + this.setPos(loc.getX(), loc.getY(), loc.getZ()); + MessagesUtil.sendDebugMessages("Spawned MEGEntity at " + loc); + getBukkitLivingEntity().setInvisible(true); + getBukkitLivingEntity().setInvulnerable(true); // NOTE - CREATIVE PLAYERS CAN DESTROY IT STILL + getBukkitLivingEntity().setAI(false); + getBukkitLivingEntity().setGravity(false); + getBukkitLivingEntity().setSilent(true); + getBukkitLivingEntity().setCollidable(false); + persist = false; + + getBukkitEntity().getPersistentDataContainer().set(new NamespacedKey(HMCCosmeticsPlugin.getInstance(), "cosmeticMob"), PersistentDataType.SHORT, Short.valueOf("1")); + + ((CraftWorld) loc.getWorld()).getHandle().addFreshEntity(this); + } +} diff --git a/v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/NMSHandler.java b/v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/NMSHandler.java new file mode 100644 index 00000000..251169f9 --- /dev/null +++ b/v1_19_R2/src/main/java/com/hibiscusmc/hmccosmetics/nms/v1_19_R2/NMSHandler.java @@ -0,0 +1,243 @@ +package com.hibiscusmc.hmccosmetics.nms.v1_19_R2; + +import com.hibiscusmc.hmccosmetics.config.Settings; +import com.hibiscusmc.hmccosmetics.cosmetic.CosmeticSlot; +import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticArmorType; +import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBackpackType; +import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticBalloonType; +import com.hibiscusmc.hmccosmetics.cosmetic.types.CosmeticMainhandType; +import com.hibiscusmc.hmccosmetics.entities.BalloonEntity; +import com.hibiscusmc.hmccosmetics.user.CosmeticUser; +import com.hibiscusmc.hmccosmetics.util.InventoryUtils; +import com.hibiscusmc.hmccosmetics.util.MessagesUtil; +import com.hibiscusmc.hmccosmetics.util.PlayerUtils; +import com.hibiscusmc.hmccosmetics.util.packets.PacketManager; +import com.mojang.datafixers.util.Pair; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; +import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; +import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerPlayerConnection; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.scores.PlayerTeam; +import net.minecraft.world.scores.Team; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_19_R2.CraftEquipmentSlot; +import org.bukkit.craftbukkit.v1_19_R2.CraftServer; +import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_19_R2.scoreboard.CraftScoreboard; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class NMSHandler implements com.hibiscusmc.hmccosmetics.nms.NMSHandler { + @Override + public int getNextEntityId() { + return 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(); + } + + 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) return null; + return entity; + } + return null; + } + + @Override + public org.bukkit.entity.Entity getInvisibleArmorstand(Location loc) { + InvisibleArmorstand invisibleArmorstand = new InvisibleArmorstand(loc); + return invisibleArmorstand.getBukkitEntity(); + } + + @Override + public org.bukkit.entity.Entity getMEGEntity(Location loc) { + return new MEGEntity(loc).getBukkitEntity(); + } + + @Override + public org.bukkit.entity.Entity spawnBackpack(CosmeticUser user, CosmeticBackpackType cosmeticBackpackType) { + InvisibleArmorstand invisibleArmorstand = new InvisibleArmorstand(user.getPlayer().getLocation()); + + ItemStack item = user.getUserCosmeticItem(cosmeticBackpackType); + + invisibleArmorstand.setItemSlot(EquipmentSlot.HEAD, CraftItemStack.asNMSCopy(item)); + ((CraftWorld) user.getPlayer().getWorld()).getHandle().addFreshEntity(invisibleArmorstand, CreatureSpawnEvent.SpawnReason.CUSTOM); + + MessagesUtil.sendDebugMessages("spawnBackpack NMS"); + + return invisibleArmorstand.getBukkitLivingEntity(); + //PacketManager.armorStandMetaPacket(invisibleArmorstand.getBukkitEntity(), sentTo); + //PacketManager.ridingMountPacket(player.getEntityId(), invisibleArmorstand.getId(), sentTo); + + } + + + + @Override + public BalloonEntity spawnBalloon(CosmeticUser user, CosmeticBalloonType cosmeticBalloonType) { + Player player = user.getPlayer(); + Location newLoc = player.getLocation().clone().add(Settings.getBalloonOffset()); + + BalloonEntity balloonEntity1 = new BalloonEntity(user.getPlayer().getLocation()); + List sentTo = PlayerUtils.getNearbyPlayers(player.getLocation()); + balloonEntity1.getModelEntity().teleport(user.getPlayer().getLocation().add(Settings.getBalloonOffset())); + + balloonEntity1.spawnModel(cosmeticBalloonType.getModelName(), user.getCosmeticColor(cosmeticBalloonType.getSlot())); + balloonEntity1.addPlayerToModel(player, cosmeticBalloonType.getModelName(), user.getCosmeticColor(cosmeticBalloonType.getSlot())); + + PacketManager.sendEntitySpawnPacket(newLoc, balloonEntity1.getPufferfishBalloonId(), EntityType.PUFFERFISH, balloonEntity1.getPufferfishBalloonUniqueId(), sentTo); + PacketManager.sendInvisibilityPacket(balloonEntity1.getPufferfishBalloonId(), sentTo); + PacketManager.sendLeashPacket(balloonEntity1.getPufferfishBalloonId(), player.getEntityId(), sentTo); + + return balloonEntity1; + } + + @Override + public void equipmentSlotUpdate( + int entityId, + CosmeticUser user, + CosmeticSlot cosmeticSlot, + List sendTo + ) { + + EquipmentSlot nmsSlot = null; + net.minecraft.world.item.ItemStack nmsItem = null; + + if (!(user.getCosmetic(cosmeticSlot) instanceof CosmeticArmorType)) { + + if (user.getCosmetic(cosmeticSlot) instanceof CosmeticMainhandType) { + CosmeticMainhandType cosmeticMainhandType = (CosmeticMainhandType) user.getCosmetic(CosmeticSlot.MAINHAND); + nmsItem = CraftItemStack.asNMSCopy(user.getUserCosmeticItem(cosmeticMainhandType)); + } else { + nmsItem = CraftItemStack.asNMSCopy(user.getPlayer().getInventory().getItem(InventoryUtils.getEquipmentSlot(cosmeticSlot))); + } + + nmsSlot = CraftEquipmentSlot.getNMS(InventoryUtils.getEquipmentSlot(cosmeticSlot)); + + if (nmsSlot == null) return; + + Pair pair = new Pair<>(nmsSlot, nmsItem); + + List> pairs = Collections.singletonList(pair); + + ClientboundSetEquipmentPacket packet = new ClientboundSetEquipmentPacket(entityId, pairs); + for (Player p : sendTo) sendPacket(p, packet); + return; + } + CosmeticArmorType cosmeticArmor = (CosmeticArmorType) user.getCosmetic(cosmeticSlot); + + // Converting EquipmentSlot and ItemStack to NMS ones. + nmsSlot = CraftEquipmentSlot.getNMS(cosmeticArmor.getEquipSlot()); + nmsItem = CraftItemStack.asNMSCopy(user.getUserCosmeticItem(cosmeticArmor)); + + if (nmsSlot == null) return; + + Pair pair = new Pair<>(nmsSlot, nmsItem); + + List> pairs = Collections.singletonList(pair); + + ClientboundSetEquipmentPacket packet = new ClientboundSetEquipmentPacket(entityId, pairs); + for (Player p : sendTo) sendPacket(p, packet); + } + + + @Override + public void equipmentSlotUpdate( + int entityId, + org.bukkit.inventory.EquipmentSlot slot, + ItemStack item, + List 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 pair = new Pair<>(nmsSlot, nmsItem); + + List> pairs = Collections.singletonList(pair); + + ClientboundSetEquipmentPacket packet = new ClientboundSetEquipmentPacket(entityId, pairs); + for (Player p : sendTo) sendPacket(p, packet); + } + + + @Override + public void slotUpdate( + 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); + } + + public void hideNPCName(Player player, String NPCName) { + //Creating the team + PlayerTeam team = new PlayerTeam(((CraftScoreboard) Bukkit.getScoreboardManager().getMainScoreboard()).getHandle(), NPCName); + + //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() {{ + add(NPCName); + }}, ClientboundSetPlayerTeamPacket.Action.ADD); + sendPacket(player, createPlayerTeamPacket); + } + + public void sendPacket(Player player, Packet packet) { + ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); + ServerPlayerConnection connection = serverPlayer.connection; + connection.send(packet); + } + + @Override + public boolean getSupported() { + return true; + } +}