diff --git a/build.gradle.kts b/build.gradle.kts index 2a0872a..0a729dd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -98,6 +98,7 @@ allprojects { compileOnly("com.ticxo.modelengine:ModelEngine:R4.0.2") compileOnly("com.comphenix.protocol:ProtocolLib:5.3.0") compileOnly("org.joml:joml:1.10.8") + compileOnly("com.github.Gecolay.GSit:core:2.0.0") // Lombok <3 annotationProcessor("org.projectlombok:lombok:1.18.36") @@ -108,6 +109,7 @@ allprojects { // Spigot Auto Loader Libraries compileOnly("net.kyori:adventure-api:4.18.0") compileOnly("net.kyori:adventure-text-minimessage:4.18.0") + compileOnly("net.kyori:adventure-text-serializer-gson:4.18.0") compileOnly("net.kyori:adventure-platform-bukkit:4.3.4") compileOnly("org.apache.commons:commons-lang3:3.17.0") @@ -136,7 +138,7 @@ tasks { runServer { dependsOn(shadowJar) dependsOn(jar) - minecraftVersion("1.21.1") + minecraftVersion("1.21.4") downloadPlugins { hangar("PlaceholderAPI", "2.11.6") @@ -216,6 +218,7 @@ bukkit { libraries = listOf( "net.kyori:adventure-api:4.18.0", "net.kyori:adventure-text-minimessage:4.18.0", + "net.kyori:adventure-text-serializer-gson:4.18.0", "net.kyori:adventure-platform-bukkit:4.3.4", "org.apache.commons:commons-lang3:3.17.0" //"org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT" // Readd when 4.2.0 releases diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookCustomFishing.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookCustomFishing.java index bfa9462..743b45d 100644 --- a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookCustomFishing.java +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookCustomFishing.java @@ -2,19 +2,29 @@ package me.lojosho.hibiscuscommons.hooks.misc; import me.lojosho.hibiscuscommons.api.events.HibiscusPluginFishEvent; import me.lojosho.hibiscuscommons.hooks.Hook; +import me.lojosho.hibiscuscommons.hooks.HookFlag; +import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.event.FishingLootSpawnEvent; +import net.momirealms.customfishing.api.mechanic.context.Context; import org.bukkit.Bukkit; import org.bukkit.entity.Item; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; public class HookCustomFishing extends Hook { public HookCustomFishing() { - super("CustomFishing"); + super("CustomFishing", HookFlag.ITEM_SUPPORT); setActive(true); } + @Override + public ItemStack getItem(@NotNull String itemId) { + return BukkitCustomFishingPlugin.getInstance().getItemManager().buildAny(Context.player(null), itemId); + } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerFish(FishingLootSpawnEvent event) { if (event.getEntity() == null) return; diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookGSit.java b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookGSit.java index 428115d..4702f35 100644 --- a/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookGSit.java +++ b/common/src/main/java/me/lojosho/hibiscuscommons/hooks/misc/HookGSit.java @@ -1,7 +1,7 @@ package me.lojosho.hibiscuscommons.hooks.misc; -import dev.geco.gsit.api.event.PlayerGetUpPoseEvent; import dev.geco.gsit.api.event.PlayerPoseEvent; +import dev.geco.gsit.api.event.PlayerStopPoseEvent; import me.lojosho.hibiscuscommons.api.events.HibiscusPlayerPoseEvent; import me.lojosho.hibiscuscommons.hooks.Hook; import org.bukkit.Bukkit; @@ -22,7 +22,7 @@ public class HookGSit extends Hook { } @EventHandler(ignoreCancelled = true, priority = EventPriority.LOW) - public void onPlayerGetUp(PlayerGetUpPoseEvent event) { + public void onPlayerGetUp(PlayerStopPoseEvent event) { HibiscusPlayerPoseEvent newEvent = new HibiscusPlayerPoseEvent(this, event.getPlayer(), true); Bukkit.getPluginManager().callEvent(newEvent); } diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSPackets.java b/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSPackets.java index 088009c..06b7e47 100644 --- a/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSPackets.java +++ b/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSPackets.java @@ -1,6 +1,7 @@ package me.lojosho.hibiscuscommons.nms; import it.unimi.dsi.fastutil.ints.IntList; +import net.kyori.adventure.text.Component; import org.bukkit.Location; import org.bukkit.entity.Display; import org.bukkit.entity.EntityType; @@ -74,4 +75,6 @@ public interface NMSPackets { int blockLight, int skyLight, float viewRange, float width, float height, ItemDisplay.ItemDisplayTransform transform, ItemStack itemStack, List sendTo); + + void sendToastPacket(Player player, ItemStack icon, Component title, Component description); } diff --git a/lib/GSit-1.10.0.jar b/lib/GSit-1.10.0.jar deleted file mode 100644 index 995ae7d..0000000 Binary files a/lib/GSit-1.10.0.jar and /dev/null differ diff --git a/v1_20_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R3/NMSPackets.java b/v1_20_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R3/NMSPackets.java index b153ced..d3501df 100644 --- a/v1_20_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R3/NMSPackets.java +++ b/v1_20_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R3/NMSPackets.java @@ -1,13 +1,23 @@ package me.lojosho.hibiscuscommons.nms.v1_20_R3; +import com.google.gson.JsonDeserializationContext; +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.Advancement; +import net.minecraft.advancements.AdvancementHolder; 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.player.Inventory; @@ -26,6 +36,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.joml.Quaternionf; import org.joml.Vector3f; @@ -295,4 +306,9 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entityId, dataValues); for (Player p : sendTo) sendPacket(p, packet); } + + @Override + public void sendToastPacket(Player player, ItemStack icon, Component title, Component description) { + throw new UnsupportedOperationException("Not implemented in this version."); + } } diff --git a/v1_20_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R4/NMSPackets.java b/v1_20_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R4/NMSPackets.java index ffa83ca..afe43fb 100644 --- a/v1_20_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R4/NMSPackets.java +++ b/v1_20_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R4/NMSPackets.java @@ -1,13 +1,22 @@ package me.lojosho.hibiscuscommons.nms.v1_20_R4; +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.Advancement; +import net.minecraft.advancements.AdvancementHolder; 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.player.Inventory; @@ -26,6 +35,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.joml.Quaternionf; import org.joml.Vector3f; @@ -293,4 +303,73 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entityId, dataValues); for (Player p : sendTo) sendPacket(p, packet); } + + @Override + public void sendToastPacket(Player player, ItemStack icon, Component title, Component description) { + final var key = new ResourceLocation("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()) { + components.addProperty("minecraft:custom_model_data", meta.getCustomModelData()); + } + + 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() + ); + + sendPacket(player, removePacket); + }, 2L); + } } diff --git a/v1_21_R1/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R1/NMSPackets.java b/v1_21_R1/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R1/NMSPackets.java index ac711e2..0433390 100644 --- a/v1_21_R1/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R1/NMSPackets.java +++ b/v1_21_R1/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R1/NMSPackets.java @@ -1,14 +1,23 @@ package me.lojosho.hibiscuscommons.nms.v1_21_R1; +import com.google.gson.JsonObject; import com.mojang.datafixers.kinds.Const; 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.Advancement; +import net.minecraft.advancements.AdvancementHolder; 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.player.Inventory; @@ -27,6 +36,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.joml.Quaternionf; import org.joml.Vector3f; @@ -302,4 +312,73 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entityId, dataValues); for (Player p : sendTo) sendPacket(p, packet); } + + @Override + 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()) { + components.addProperty("minecraft:custom_model_data", meta.getCustomModelData()); + } + + 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() + ); + + sendPacket(player, removePacket); + }, 2L); + } } diff --git a/v1_21_R2/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R2/NMSPackets.java b/v1_21_R2/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R2/NMSPackets.java index 80093b0..6170489 100644 --- a/v1_21_R2/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R2/NMSPackets.java +++ b/v1_21_R2/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R2/NMSPackets.java @@ -1,13 +1,22 @@ package me.lojosho.hibiscuscommons.nms.v1_21_R2; +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.Advancement; +import net.minecraft.advancements.AdvancementHolder; 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; @@ -29,6 +38,7 @@ 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.joml.Quaternionf; import org.joml.Vector3f; @@ -281,4 +291,73 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entityId, dataValues); for (Player p : sendTo) sendPacket(p, packet); } + + @Override + 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()) { + components.addProperty("minecraft:custom_model_data", meta.getCustomModelData()); + } + + 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() + ); + + sendPacket(player, removePacket); + }, 2L); + } } diff --git a/v1_21_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R3/NMSPackets.java b/v1_21_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R3/NMSPackets.java index 861c811..72f1426 100644 --- a/v1_21_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R3/NMSPackets.java +++ b/v1_21_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R3/NMSPackets.java @@ -1,13 +1,22 @@ package me.lojosho.hibiscuscommons.nms.v1_21_R3; +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.kyori.adventure.text.serializer.json.JSONComponentSerializer; +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; @@ -29,6 +38,7 @@ 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.joml.Quaternionf; import org.joml.Vector3f; @@ -42,6 +52,7 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. static Constructor linkConstructor; static Constructor cameraConstructor; static Constructor lookAtConstructor; + static { try { passengerConstructor = ClientboundSetPassengersPacket.class.getDeclaredConstructor(FriendlyByteBuf.class); @@ -281,4 +292,72 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. 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()) { + components.addProperty("minecraft:custom_model_data", meta.getCustomModelData()); + } + + 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() + ); + + sendPacket(player, removePacket); + }, 2L); + } }