package net.glowstone.inventory.crafting;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import lombok.Data;
import net.glowstone.entity.GlowPlayer;
import net.glowstone.net.message.play.game.UnlockRecipesMessage;
import net.glowstone.util.nbt.CompoundTag;
import net.glowstone.util.nbt.TagType;

@Data
public final class PlayerRecipeMonitor {

    private final GlowPlayer player;
    private final Set<String> recipes, toBeDisplayed;
    private boolean bookOpen;
    private boolean filterCraftable;

    public PlayerRecipeMonitor(GlowPlayer player) {
        this.player = player;
        this.bookOpen = false;
        this.filterCraftable = false;
        this.recipes = new HashSet<>();
        this.toBeDisplayed = new HashSet<>();
    }

    public UnlockRecipesMessage createInitMessage() {
        int status = UnlockRecipesMessage.ACTION_INIT;
        int[] recipeIds = new int[0]; // todo: conversion to internal IDs
        int[] toBeDisplayedIds = new int[0]; // todo: conversion to internal IDs
        return new UnlockRecipesMessage(status, bookOpen, filterCraftable, toBeDisplayedIds,
            recipeIds);
    }

    public void read(CompoundTag playerData) {
        if (!playerData.isCompound("recipeBook")) {
            return;
        }
        CompoundTag recipeBook = playerData.getCompound("recipeBook");
        if (recipeBook.isByte("isFilteringCraftable")) {
            setFilterCraftable(recipeBook.getBool("isFilteringCraftable"));
        }
        if (recipeBook.isByte("isGuiOpen")) {
            setBookOpen(recipeBook.getBool("isGuiOpen"));
        }
        if (recipeBook.isList("recipes", TagType.STRING)) {
            recipes.addAll(recipeBook.getList("recipes", TagType.STRING));
        }
        if (recipeBook.isList("toBeDisplayed", TagType.STRING)) {
            toBeDisplayed.addAll(recipeBook.getList("toBeDisplayed", TagType.STRING));
        }
    }

    public void write(CompoundTag playerData) {
        CompoundTag recipeBook = new CompoundTag();
        recipeBook.putBool("isFilteringCraftable", filterCraftable);
        recipeBook.putBool("isGuiOpen", bookOpen);
        recipeBook.putList("recipes", TagType.STRING, new ArrayList<>(recipes));
        recipeBook.putList("toBeDisplayed", TagType.STRING, new ArrayList<>(toBeDisplayed));
        playerData.putCompound("recipeBook", recipeBook);
    }
}

@@ -442,17 +442,47 @@
  recipes
-,
+;%0A    private final Set%3CString%3E
  toBeDis
@@ -557,16 +557,162 @@
 table;%0A%0A
+    /**%0A     * Creates an instance associated with the given player and with an empty recipe book.%0A     *%0A     * @param player the player%0A     */%0A
     publ
@@ -939,32 +939,211 @@
 Set%3C%3E();%0A    %7D%0A%0A
+    /**%0A     * Creates a message to send this recipe book's state to the client.%0A     *%0A     * @return an %7B@link UnlockRecipesMessage%7D containing this recipe book's state%0A     */%0A
     public Unloc
@@ -1506,32 +1506,176 @@
 ipeIds);%0A    %7D%0A%0A
+    /**%0A     * Restores state from an NBT tag.%0A     *%0A     * @param playerData an NBT tag containing a compound subtag named recipeBook%0A     */%0A
     public void 
@@ -2426,24 +2426,185 @@
    %7D%0A    %7D%0A%0A
+    /**%0A     * Populates a recipeBook compound subtag and adds it to the given tag.%0A     *%0A     * @param playerData a compound tag describing the player%0A     */%0A
     public v

Fix CheckStyle issues in inventory/crafting/PlayerRecipeMonitor.java (#756)