--- a/net/minecraft/stats/ServerRecipeBook.java
+++ b/net/minecraft/stats/ServerRecipeBook.java
@@ -32,7 +_,7 @@
     private static final Codec<List<ResourceKey<Recipe<?>>>> RECIPE_LIST_CODEC = Recipe.KEY_CODEC.listOf();
     private final ServerRecipeBook.DisplayResolver displayResolver;
     @VisibleForTesting
-    protected final Set<ResourceKey<Recipe<?>>> known = Sets.newIdentityHashSet();
+    public final Set<ResourceKey<Recipe<?>>> known = Sets.newIdentityHashSet();
     @VisibleForTesting
     protected final Set<ResourceKey<Recipe<?>>> highlight = Sets.newIdentityHashSet();
 
@@ -66,7 +_,7 @@
 
         for (RecipeHolder<?> recipeHolder : recipes) {
             ResourceKey<Recipe<?>> resourceKey = recipeHolder.id();
-            if (!this.known.contains(resourceKey) && !recipeHolder.value().isSpecial()) {
+            if (!this.known.contains(resourceKey) && !recipeHolder.value().isSpecial() && org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerRecipeListUpdateEvent(player, resourceKey.location())) { // CraftBukkit
                 this.add(resourceKey);
                 this.addHighlight(resourceKey);
                 this.displayResolver
@@ -77,7 +_,7 @@
             }
         }
 
-        if (!list.isEmpty()) {
+        if (!list.isEmpty() && player.connection != null) { // SPIGOT-4478 during PlayerLoginEvent
             player.connection.send(new ClientboundRecipeBookAddPacket(list, false));
         }
 
@@ -95,7 +_,7 @@
             }
         }
 
-        if (!list.isEmpty()) {
+        if (!list.isEmpty() && player.connection != null) { // SPIGOT-4478 during PlayerLoginEvent
             player.connection.send(new ClientboundRecipeBookRemovePacket(list));
         }
 
