|
5 | 5 | import net.kyori.adventure.util.TriState;
|
6 | 6 | import net.minecraft.advancements.AdvancementHolder;
|
7 | 7 | import net.minecraft.advancements.AdvancementProgress;
|
| 8 | +import net.minecraft.network.protocol.game.ClientboundRecipeBookAddPacket; |
| 9 | +import net.minecraft.resources.ResourceKey; |
8 | 10 | import net.minecraft.resources.ResourceLocation;
|
9 | 11 | import net.minecraft.server.PlayerAdvancements;
|
10 | 12 | import net.minecraft.server.level.ServerPlayer;
|
| 13 | +import net.minecraft.stats.ServerRecipeBook; |
11 | 14 | import net.minecraft.world.entity.Pose;
|
| 15 | +import net.minecraft.world.item.crafting.RecipeHolder; |
12 | 16 | import net.thenextlvl.perworlds.GroupSettings;
|
13 | 17 | import net.thenextlvl.perworlds.WorldGroup;
|
14 | 18 | import net.thenextlvl.perworlds.data.AdvancementData;
|
|
25 | 29 | import org.bukkit.craftbukkit.CraftServer;
|
26 | 30 | import org.bukkit.craftbukkit.advancement.CraftAdvancement;
|
27 | 31 | import org.bukkit.craftbukkit.entity.CraftPlayer;
|
| 32 | +import org.bukkit.craftbukkit.inventory.CraftRecipe; |
28 | 33 | import org.bukkit.entity.EntityType;
|
29 | 34 | import org.bukkit.entity.Player;
|
30 | 35 | import org.bukkit.inventory.ItemStack;
|
|
36 | 41 | import org.jspecify.annotations.Nullable;
|
37 | 42 | import org.spigotmc.SpigotConfig;
|
38 | 43 |
|
| 44 | +import java.util.ArrayList; |
39 | 45 | import java.util.Collection;
|
40 | 46 | import java.util.HashSet;
|
41 | 47 | import java.util.LinkedHashMap;
|
@@ -346,15 +352,50 @@ private void applyRecipes(Player player, GroupSettings settings) {
|
346 | 352 | if (settings.recipes()) {
|
347 | 353 | var toAdd = new HashSet<>(recipes);
|
348 | 354 | toAdd.removeAll(player.getDiscoveredRecipes());
|
349 |
| - // todo: discover internally, don't send toast |
350 |
| - player.discoverRecipes(toAdd); |
| 355 | + discoverRecipes(player, toAdd); |
351 | 356 |
|
352 | 357 | var toRemove = new HashSet<>(player.getDiscoveredRecipes());
|
353 | 358 | toRemove.removeAll(recipes);
|
354 | 359 | player.undiscoverRecipes(toRemove);
|
355 | 360 | } else player.undiscoverRecipes(player.getDiscoveredRecipes());
|
356 | 361 | }
|
357 | 362 |
|
| 363 | + private void discoverRecipes(Player player, Set<NamespacedKey> recipes) { |
| 364 | + var handle = ((CraftPlayer) player).getHandle(); |
| 365 | + var list = new ArrayList<ClientboundRecipeBookAddPacket.Entry>(); |
| 366 | + var manager = ((CraftServer) player.getServer()).getServer().getRecipeManager(); |
| 367 | + var recipeBook = handle.getRecipeBook(); |
| 368 | + |
| 369 | + var recipeHolders = recipes.stream().map(CraftRecipe::toMinecraft) |
| 370 | + .map(manager::byKey) |
| 371 | + .map(recipeHolder -> recipeHolder.orElse(null)) |
| 372 | + .filter(Objects::nonNull); |
| 373 | + |
| 374 | + recipeHolders.forEach(recipeHolder -> { |
| 375 | + if (recipeBook.known.contains(recipeHolder.id()) || recipeHolder.value().isSpecial()) return; |
| 376 | + recipeBook.add(recipeHolder.id()); |
| 377 | + manager.listDisplaysForRecipe(recipeHolder.id(), (entry) -> { |
| 378 | + list.add(new ClientboundRecipeBookAddPacket.Entry(entry, false, true)); |
| 379 | + }); |
| 380 | + addHighlight(player, recipeHolder, recipeBook); |
| 381 | + }); |
| 382 | + |
| 383 | + if (!list.isEmpty()) handle.connection.send(new ClientboundRecipeBookAddPacket(list, false)); |
| 384 | + } |
| 385 | + |
| 386 | + private void addHighlight(Player player, RecipeHolder<?> recipeHolder, ServerRecipeBook recipeBook) { |
| 387 | + try { |
| 388 | + var addHighlight = recipeBook.getClass().getDeclaredMethod("addHighlight", ResourceKey.class); |
| 389 | + var access = addHighlight.canAccess(recipeBook); |
| 390 | + if (!access) addHighlight.setAccessible(true); |
| 391 | + addHighlight.invoke(recipeBook, recipeHolder.id()); |
| 392 | + addHighlight.setAccessible(access); |
| 393 | + } catch (Exception e) { |
| 394 | + group().getGroupProvider().getLogger().error("Failed to add recipe highlight for player {}", player.getName(), e); |
| 395 | + group().getGroupProvider().getLogger().error("Please look for similar issues or report this on GitHub: {}", ISSUES); |
| 396 | + } |
| 397 | + } |
| 398 | + |
358 | 399 | private void applyAdvancements(Player player, GroupSettings settings) {
|
359 | 400 | try {
|
360 | 401 | var handle = ((CraftPlayer) player).getHandle();
|
|
0 commit comments