From aa4ef032555c72979736d3031f41c4c25b91ce95 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Fri, 11 Jul 2025 22:51:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0advancement=E5=8C=85=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compatibility/item/MMOItemsProvider.java | 2 - .../bukkit/item/BukkitItemManager.java | 1 - .../item/recipe/CrafterEventListener.java | 1 - .../plugin/injector/RecipeInjector.java | 1 - .../plugin/network/BukkitNetworkManager.java | 1 + .../plugin/network/PacketConsumers.java | 36 ++++++ .../bukkit/plugin/network/PacketIds.java | 2 + .../plugin/network/id/PacketIds1_20.java | 5 + .../plugin/network/id/PacketIds1_20_5.java | 5 + .../minecraft/NetworkReflections.java | 7 ++ .../bukkit/util/InteractUtils.java | 1 - common-files/src/main/resources/config.yml | 3 +- .../core/advancement/AdvancementType.java | 23 ++++ .../core/advancement/network/Advancement.java | 67 ++++++++++ .../network/AdvancementDisplay.java | 115 ++++++++++++++++++ .../network/AdvancementHolder.java | 23 ++++ .../network/AdvancementProgress.java | 27 ++++ .../network/AdvancementRequirements.java | 23 ++++ .../network/CriterionProgress.java | 42 +++++++ .../core/plugin/config/Config.java | 6 + .../core/util/FriendlyByteBuf.java | 26 ++++ 21 files changed, 410 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/net/momirealms/craftengine/core/advancement/AdvancementType.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/advancement/network/Advancement.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementDisplay.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementHolder.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementProgress.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementRequirements.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/advancement/network/CriterionProgress.java diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsProvider.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsProvider.java index a2a536fdd..49d38b9f9 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsProvider.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsProvider.java @@ -9,8 +9,6 @@ import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; -import java.util.Locale; - import static java.util.Objects.requireNonNull; public class MMOItemsProvider implements ExternalItemProvider { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index 3c1a6467c..74569a54d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -29,7 +29,6 @@ import net.momirealms.craftengine.core.plugin.logger.Debugger; import net.momirealms.craftengine.core.util.*; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.NamespacedKey; import org.bukkit.Registry; import org.bukkit.event.HandlerList; import org.bukkit.inventory.ItemStack; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/CrafterEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/CrafterEventListener.java index 8b9725e4d..e5036f7cd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/CrafterEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/CrafterEventListener.java @@ -11,7 +11,6 @@ import net.momirealms.craftengine.core.item.recipe.RecipeTypes; import net.momirealms.craftengine.core.item.recipe.input.CraftingInput; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.util.UniqueKey; import org.bukkit.block.Crafter; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/RecipeInjector.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/RecipeInjector.java index 54340ca9a..811dfe889 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/RecipeInjector.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/RecipeInjector.java @@ -25,7 +25,6 @@ import net.momirealms.craftengine.core.item.recipe.RecipeTypes; import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ReflectionUtils; -import net.momirealms.craftengine.core.util.UniqueKey; import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.inventory.ItemStack; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index 0910d30b9..31fc1c5d8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -176,6 +176,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerS2CByteBufPacketConsumer(PacketConsumers.ADD_RECIPE_BOOK, this.packetIds.clientboundRecipeBookAddPacket()); registerS2CByteBufPacketConsumer(PacketConsumers.PLACE_GHOST_RECIPE, this.packetIds.clientboundPlaceGhostRecipePacket()); registerS2CByteBufPacketConsumer(PacketConsumers.UPDATE_RECIPES, this.packetIds.clientboundUpdateRecipesPacket()); + registerS2CByteBufPacketConsumer(PacketConsumers.UPDATE_ADVANCEMENTS, this.packetIds.clientboundUpdateAdvancementsPacket()); registerS2CByteBufPacketConsumer(PacketConsumers.REMOVE_ENTITY, this.packetIds.clientboundRemoveEntitiesPacket()); registerS2CByteBufPacketConsumer(PacketConsumers.ADD_ENTITY, this.packetIds.clientboundAddEntityPacket()); registerS2CByteBufPacketConsumer(PacketConsumers.SOUND, this.packetIds.clientboundSoundPacket()); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 95ac62ed2..34e931cc4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.bukkit.plugin.network; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Either; import io.netty.buffer.ByteBuf; @@ -34,6 +35,8 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityType import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.util.*; +import net.momirealms.craftengine.core.advancement.network.AdvancementHolder; +import net.momirealms.craftengine.core.advancement.network.AdvancementProgress; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.font.FontManager; @@ -2534,4 +2537,37 @@ public class PacketConsumers { CraftEngine.instance().logger().warn("Failed to handle ClientboundUpdateRecipesPacket", e); } }; + + public static final BiConsumer UPDATE_ADVANCEMENTS = (user, event) -> { + try { + FriendlyByteBuf buf = event.getBuffer(); + boolean reset = buf.readBoolean(); + List added = buf.readCollection(ArrayList::new, byteBuf -> { + AdvancementHolder holder = AdvancementHolder.read(byteBuf); + holder.applyClientboundData((BukkitServerPlayer) user); + return holder; + }); + Set removed = buf.readCollection(Sets::newLinkedHashSetWithExpectedSize, FriendlyByteBuf::readKey); + Map progress = buf.readMap(FriendlyByteBuf::readKey, AdvancementProgress::read); + + boolean showAdvancement = false; + if (VersionHelper.isOrAbove1_21_5()) { + showAdvancement = buf.readBoolean(); + } + + event.setChanged(true); + buf.clear(); + buf.writeVarInt(event.packetID()); + + buf.writeBoolean(reset); + buf.writeCollection(added, (byteBuf, advancementHolder) -> advancementHolder.write(byteBuf)); + buf.writeCollection(removed, FriendlyByteBuf::writeKey); + buf.writeMap(progress, FriendlyByteBuf::writeKey, (byteBuf, advancementProgress) -> advancementProgress.write(byteBuf)); + if (VersionHelper.isOrAbove1_21_5()) { + buf.writeBoolean(showAdvancement); + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ClientboundUpdateAdvancementsPacket", e); + } + }; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java index e401b9b96..bef170327 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java @@ -58,6 +58,8 @@ public interface PacketIds { int clientboundPlaceGhostRecipePacket(); + int clientboundUpdateAdvancementsPacket(); + int serverboundContainerClickPacket(); int serverboundSetCreativeModeSlotPacket(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java index b379e2a62..34981a06b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java @@ -164,4 +164,9 @@ public class PacketIds1_20 implements PacketIds { public int clientboundUpdateRecipesPacket() { return PacketIdFinder.clientboundByClazz(NetworkReflections.clazz$ClientboundUpdateRecipesPacket); } + + @Override + public int clientboundUpdateAdvancementsPacket() { + return PacketIdFinder.clientboundByClazz(NetworkReflections.clazz$ClientboundUpdateAdvancementsPacket); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java index d5c5b1349..216b11d56 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java @@ -149,6 +149,11 @@ public class PacketIds1_20_5 implements PacketIds { return PacketIdFinder.clientboundByName("minecraft:update_recipes"); } + @Override + public int clientboundUpdateAdvancementsPacket() { + return PacketIdFinder.clientboundByName("minecraft:update_advancements"); + } + @Override public int serverboundContainerClickPacket() { return PacketIdFinder.serverboundByName("minecraft:container_click"); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java index 577f843bc..5da7c5b90 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java @@ -1580,4 +1580,11 @@ public final class NetworkReflections { "network.protocol.game.ClientboundUpdateRecipesPacket" ) ); + + public static final Class clazz$ClientboundUpdateAdvancementsPacket = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "network.protocol.game.PacketPlayOutAdvancements", + "network.protocol.game.ClientboundUpdateAdvancementsPacket" + ) + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java index 13a1968a8..8b4fd002f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java @@ -12,7 +12,6 @@ import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.QuadFunction; -import net.momirealms.craftengine.core.util.UniqueKey; import net.momirealms.craftengine.core.world.BlockHitResult; import net.momirealms.craftengine.core.world.BlockPos; import org.bukkit.block.data.BlockData; diff --git a/common-files/src/main/resources/config.yml b/common-files/src/main/resources/config.yml index 03c240f82..06eb8285b 100644 --- a/common-files/src/main/resources/config.yml +++ b/common-files/src/main/resources/config.yml @@ -221,7 +221,7 @@ image: intercept-packets: system-chat: true tab-list: true # Tab list header and footer - player-info: true # User list in tab + player-info: true # Player list in tab set-score: true actionbar: true title: true @@ -233,6 +233,7 @@ image: armor-stand: true # Legacy Holograms text-display: true # Modern Holograms item: true + advancement: true # Defines Unicode characters used for positioning # - Must match the font defined in resource packs # - Do NOT modify unless you understand text rendering mechanics diff --git a/core/src/main/java/net/momirealms/craftengine/core/advancement/AdvancementType.java b/core/src/main/java/net/momirealms/craftengine/core/advancement/AdvancementType.java new file mode 100644 index 000000000..b1038933f --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/advancement/AdvancementType.java @@ -0,0 +1,23 @@ +package net.momirealms.craftengine.core.advancement; + +public enum AdvancementType { + TASK("task"), + CHALLENGE("challenge"), + GOAL("goal"),; + + private final String id; + + AdvancementType(String id) { + this.id = id; + } + + public String id() { + return id; + } + + public static final AdvancementType[] VALUES = values(); + + public static AdvancementType byId(int id) { + return VALUES[id]; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/advancement/network/Advancement.java b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/Advancement.java new file mode 100644 index 000000000..c58194ae9 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/Advancement.java @@ -0,0 +1,67 @@ +package net.momirealms.craftengine.core.advancement.network; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.util.FriendlyByteBuf; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.VersionHelper; +import org.jetbrains.annotations.ApiStatus; + +import java.util.Map; +import java.util.Optional; + +public class Advancement { + private final Optional parent; + private final Optional displayInfo; + + // 1.20-1.20.1 + private final Map criteria; + + private final AdvancementRequirements requirements; + private final boolean sendsTelemetryEvent; + + public Advancement(Optional parent, Optional displayInfo, AdvancementRequirements requirements, boolean sendsTelemetryEvent) { + this.criteria = null; + this.displayInfo = displayInfo; + this.parent = parent; + this.requirements = requirements; + this.sendsTelemetryEvent = sendsTelemetryEvent; + } + + @ApiStatus.Obsolete + public Advancement(Optional parent, Optional displayInfo, Map criteria, AdvancementRequirements requirements, boolean sendsTelemetryEvent) { + this.criteria = criteria; + this.displayInfo = displayInfo; + this.parent = parent; + this.requirements = requirements; + this.sendsTelemetryEvent = sendsTelemetryEvent; + } + + public static Advancement read(FriendlyByteBuf buf) { + Optional parent = buf.readOptional(FriendlyByteBuf::readKey); + Optional displayInfo = buf.readOptional(byteBuf -> AdvancementDisplay.read(buf)); + if (VersionHelper.isOrAbove1_20_2()) { + AdvancementRequirements requirements = AdvancementRequirements.read(buf); + boolean sendsTelemetryEvent = buf.readBoolean(); + return new Advancement(parent, displayInfo, requirements, sendsTelemetryEvent); + } else { + Map criteria = buf.readMap(FriendlyByteBuf::readUtf, (byteBuf -> null)); + AdvancementRequirements requirements = AdvancementRequirements.read(buf); + boolean sendsTelemetryEvent = buf.readBoolean(); + return new Advancement(parent, displayInfo, criteria, requirements, sendsTelemetryEvent); + } + } + + public void write(FriendlyByteBuf buf) { + buf.writeOptional(this.parent, FriendlyByteBuf::writeKey); + buf.writeOptional(this.displayInfo, (byteBuf, info) -> info.write(buf)); + if (!VersionHelper.isOrAbove1_20_2()) { + buf.writeMap(this.criteria, FriendlyByteBuf::writeUtf, ((byteBuf, unused) -> {})); + } + this.requirements.write(buf); + buf.writeBoolean(this.sendsTelemetryEvent); + } + + public void applyClientboundData(Player player) { + this.displayInfo.ifPresent(info -> info.applyClientboundData(player)); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementDisplay.java b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementDisplay.java new file mode 100644 index 000000000..93924daf9 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementDisplay.java @@ -0,0 +1,115 @@ +package net.momirealms.craftengine.core.advancement.network; + +import net.kyori.adventure.text.Component; +import net.momirealms.craftengine.core.advancement.AdvancementType; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.config.Config; +import net.momirealms.craftengine.core.util.AdventureHelper; +import net.momirealms.craftengine.core.util.FriendlyByteBuf; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.VersionHelper; +import net.momirealms.sparrow.nbt.Tag; + +import java.util.Map; +import java.util.Optional; + +public class AdvancementDisplay { + public static final int FLAG_BACKGROUND = 0b001; + public static final int FLAG_SHOW_TOAST = 0b010; + public static final int FLAG_HIDDEN = 0b100; + private Component title; + private Component description; + private Item icon; + private Optional background; + private final AdvancementType type; + private final boolean showToast; + private final boolean hidden; + private float x; + private float y; + + public AdvancementDisplay(Component title, + Component description, + Item icon, + Optional background, + AdvancementType type, + boolean showToast, + boolean hidden, + float x, + float y) { + this.type = type; + this.showToast = showToast; + this.hidden = hidden; + this.background = background; + this.description = description; + this.icon = icon; + this.title = title; + this.x = x; + this.y = y; + } + + public void applyClientboundData(Player player) { + this.icon = CraftEngine.instance().itemManager().s2c(this.icon, player); + } + + public void write(FriendlyByteBuf buf) { + buf.writeComponent(this.title); + buf.writeComponent(this.description); + CraftEngine.instance().itemManager().encode(buf, this.icon); + buf.writeVarInt(this.type.ordinal()); + int flags = 0; + if (this.background.isPresent()) { + flags |= FLAG_BACKGROUND; + } + if (this.showToast) { + flags |= FLAG_SHOW_TOAST; + } + if (this.hidden) { + flags |= FLAG_HIDDEN; + } + buf.writeInt(flags); + this.background.ifPresent(buf::writeKey); + buf.writeFloat(this.x); + buf.writeFloat(this.y); + } + + public static AdvancementDisplay read(FriendlyByteBuf buf) { + Component title = readComponent(buf); + Component description = readComponent(buf); + Item icon = CraftEngine.instance().itemManager().decode(buf); + AdvancementType type = AdvancementType.byId(buf.readVarInt()); + int flags = buf.readInt(); + boolean hasBackground = (flags & 1) != 0; + Optional background = hasBackground ? Optional.of(buf.readKey()) : Optional.empty(); + boolean showToast = (flags & 2) != 0; + boolean hidden = (flags & 4) != 0; + float x = buf.readFloat(); + float y = buf.readFloat(); + return new AdvancementDisplay(title, description, icon, background, type, showToast, hidden, x, y); + } + + private static Component readComponent(FriendlyByteBuf buf) { + if (Config.interceptAdvancement()) { + if (VersionHelper.isOrAbove1_20_3()) { + Tag nbt = buf.readNbt(false); + Map tokens = CraftEngine.instance().fontManager().matchTags(nbt.getAsString()); + Component component = AdventureHelper.nbtToComponent(nbt); + if (!tokens.isEmpty()) { + component = AdventureHelper.replaceText(component, tokens); + } + return component; + } else { + String json = buf.readUtf(); + Component component = AdventureHelper.jsonToComponent(json); + Map tokens = CraftEngine.instance().fontManager().matchTags(json); + if (!tokens.isEmpty()) { + component = AdventureHelper.replaceText(component, tokens); + } + return component; + } + } else { + return buf.readComponent(); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementHolder.java b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementHolder.java new file mode 100644 index 000000000..9e4ed5d7e --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementHolder.java @@ -0,0 +1,23 @@ +package net.momirealms.craftengine.core.advancement.network; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.util.FriendlyByteBuf; +import net.momirealms.craftengine.core.util.Key; + +public record AdvancementHolder(Key id, Advancement advancement) { + + public static AdvancementHolder read(FriendlyByteBuf buf) { + Key key = buf.readKey(); + Advancement ad = Advancement.read(buf); + return new AdvancementHolder(key, ad); + } + + public void write(FriendlyByteBuf buf) { + buf.writeKey(this.id); + this.advancement.write(buf); + } + + public void applyClientboundData(Player player) { + this.advancement.applyClientboundData(player); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementProgress.java b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementProgress.java new file mode 100644 index 000000000..9024a496b --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementProgress.java @@ -0,0 +1,27 @@ +package net.momirealms.craftengine.core.advancement.network; + +import net.momirealms.craftengine.core.util.FriendlyByteBuf; + +import java.util.HashMap; +import java.util.Map; + +public class AdvancementProgress { + private final Map progress; + + public AdvancementProgress(Map progress) { + this.progress = progress; + } + + public AdvancementProgress() { + this.progress = new HashMap<>(); + } + + public void write(FriendlyByteBuf buf) { + buf.writeMap(this.progress, FriendlyByteBuf::writeUtf, ((byteBuf, criterionProgress) -> criterionProgress.write(buf))); + } + + public static AdvancementProgress read(FriendlyByteBuf buf) { + Map progress = buf.readMap(FriendlyByteBuf::readUtf, CriterionProgress::read); + return new AdvancementProgress(progress); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementRequirements.java b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementRequirements.java new file mode 100644 index 000000000..f3eb80037 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/AdvancementRequirements.java @@ -0,0 +1,23 @@ +package net.momirealms.craftengine.core.advancement.network; + +import net.momirealms.craftengine.core.util.FriendlyByteBuf; + +import java.util.ArrayList; +import java.util.List; + +public class AdvancementRequirements { + public static final AdvancementRequirements EMPTY = new AdvancementRequirements(List.of()); + private final List> requirements; + + public AdvancementRequirements(List> requirements) { + this.requirements = requirements; + } + + public void write(FriendlyByteBuf byteBuf) { + byteBuf.writeCollection(this.requirements, ((buf, strings) -> buf.writeCollection(strings, FriendlyByteBuf::writeUtf))); + } + + public static AdvancementRequirements read(FriendlyByteBuf byteBuf) { + return new AdvancementRequirements(byteBuf.readCollection(ArrayList::new, buf -> buf.readCollection(ArrayList::new, FriendlyByteBuf::readUtf))); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/advancement/network/CriterionProgress.java b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/CriterionProgress.java new file mode 100644 index 000000000..87a0456e4 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/advancement/network/CriterionProgress.java @@ -0,0 +1,42 @@ +package net.momirealms.craftengine.core.advancement.network; + +import net.momirealms.craftengine.core.util.FriendlyByteBuf; +import org.jetbrains.annotations.Nullable; + +import java.time.Instant; + +public class CriterionProgress { + @Nullable + private Instant obtainedTimestamp; + + public CriterionProgress() { + } + + public CriterionProgress(@Nullable Instant obtainedTimestamp) { + this.obtainedTimestamp = obtainedTimestamp; + } + + public boolean isDone() { + return this.obtainedTimestamp != null; + } + + public void grant() { + this.obtainedTimestamp = Instant.now(); + } + + public void revoke() { + this.obtainedTimestamp = null; + } + + public @Nullable Instant obtainedTimestamp() { + return obtainedTimestamp; + } + + public void write(FriendlyByteBuf buf) { + buf.writeNullable(this.obtainedTimestamp, FriendlyByteBuf::writeInstant); + } + + public static CriterionProgress read(FriendlyByteBuf buf) { + return new CriterionProgress(buf.readNullable(FriendlyByteBuf::readInstant)); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java index 23ab0aaeb..425de32f9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java @@ -150,6 +150,7 @@ public class Config { protected boolean image$intercept_packets$player_info; protected boolean image$intercept_packets$set_score; protected boolean image$intercept_packets$item; + protected boolean image$intercept_packets$advancement; protected boolean item$client_bound_model; protected boolean item$non_italic_tag; @@ -393,6 +394,7 @@ public class Config { image$intercept_packets$player_info = config.getBoolean("image.intercept-packets.player-info", true); image$intercept_packets$set_score = config.getBoolean("image.intercept-packets.set-score", true); image$intercept_packets$item = config.getBoolean("image.intercept-packets.item", true); + image$intercept_packets$advancement = config.getBoolean("image.intercept-packets.advancement", true); // emoji emoji$chat = config.getBoolean("emoji.chat", true); @@ -742,6 +744,10 @@ public class Config { return instance.image$intercept_packets$item; } + public static boolean interceptAdvancement() { + return instance.image$intercept_packets$advancement; + } + public static boolean predictBreaking() { return instance.block$predict_breaking; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java b/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java index c78cd94c4..68e30c8a2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/FriendlyByteBuf.java @@ -11,6 +11,7 @@ import io.netty.handler.codec.EncoderException; import io.netty.util.ByteProcessor; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; +import net.kyori.adventure.text.Component; import net.momirealms.craftengine.core.registry.Registry; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.sparrow.nbt.NBT; @@ -29,6 +30,7 @@ import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.time.Instant; import java.util.*; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -47,6 +49,30 @@ public class FriendlyByteBuf extends ByteBuf { return source; } + public Component readComponent() { + if (VersionHelper.isOrAbove1_20_3()) { + return AdventureHelper.nbtToComponent(this.readNbt(false)); + } else { + return AdventureHelper.jsonToComponent(this.readUtf()); + } + } + + public void writeComponent(Component component) { + if (VersionHelper.isOrAbove1_20_3()) { + this.writeNbt(AdventureHelper.componentToNbt(component), false); + } else { + this.writeUtf(AdventureHelper.componentToJson(component)); + } + } + + public Instant readInstant() { + return Instant.ofEpochMilli(this.readLong()); + } + + public void writeInstant(Instant instant) { + this.writeLong(instant.toEpochMilli()); + } + public > C readCollection(IntFunction collectionFactory, Reader reader) { int i = this.readVarInt(); C collection = collectionFactory.apply(i);